Mercurial > hg > graal-jvmci-8
changeset 7918:0dea5ef60303
Merge
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Mon, 04 Mar 2013 10:00:49 +0100 |
parents | 1a83cef20ee5 (diff) 9bff64f43299 (current diff) |
children | 0ae70d44ec9a |
files | mxtool/mx.py |
diffstat | 263 files changed, 9183 insertions(+), 4268 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64Address.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2010, 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.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; + +/** + * Represents an address in target machine memory, specified via some combination of a base + * register, an index register, a displacement and a scale. Note that the base and index registers + * may be a variable that will get a register assigned later by the register allocator. + */ +public final class AMD64Address extends Address { + + private static final long serialVersionUID = -4101548147426595051L; + + private final Value[] baseIndex; + private final Scale scale; + private final int displacement; + + /** + * Creates an {@link AMD64Address} with given base register, no scaling and no displacement. + * + * @param kind the kind of the value being addressed + * @param base the base register + */ + public AMD64Address(Kind kind, Value base) { + this(kind, base, ILLEGAL, Scale.Times1, 0); + } + + /** + * Creates an {@link AMD64Address} with given base register, no scaling and a given + * displacement. + * + * @param kind the kind of the value being addressed + * @param base the base register + * @param displacement the displacement + */ + public AMD64Address(Kind kind, Value base, int displacement) { + this(kind, base, ILLEGAL, Scale.Times1, displacement); + } + + /** + * Creates an {@link AMD64Address} with given base and index registers, scaling and + * displacement. This is the most general constructor. + * + * @param kind the kind of the value being addressed + * @param base the base register + * @param index the index register + * @param scale the scaling factor + * @param displacement the displacement + */ + public AMD64Address(Kind kind, Value base, Value index, Scale scale, int displacement) { + super(kind); + this.baseIndex = new Value[2]; + this.setBase(base); + this.setIndex(index); + this.scale = scale; + this.displacement = displacement; + + assert !isConstant(base) && !isStackSlot(base); + assert !isConstant(index) && !isStackSlot(index); + } + + /** + * A scaling factor used in the SIB addressing mode. + */ + public enum Scale { + Times1(1, 0), Times2(2, 1), Times4(4, 2), Times8(8, 3); + + private Scale(int value, int log2) { + this.value = value; + this.log2 = log2; + } + + /** + * The value (or multiplier) of this scale. + */ + public final int value; + + /** + * The {@linkplain #value value} of this scale log 2. + */ + public final int log2; + + public static Scale fromInt(int scale) { + switch (scale) { + case 1: + return Times1; + case 2: + return Times2; + case 4: + return Times4; + case 8: + return Times8; + default: + throw new IllegalArgumentException(String.valueOf(scale)); + } + } + } + + @Override + public Value[] components() { + return baseIndex; + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append(getKind().getJavaName()).append("["); + String sep = ""; + if (isLegal(getBase())) { + s.append(getBase()); + sep = " + "; + } + if (isLegal(getIndex())) { + s.append(sep).append(getIndex()).append(" * ").append(getScale().value); + sep = " + "; + } + if (getDisplacement() < 0) { + s.append(" - ").append(-getDisplacement()); + } else if (getDisplacement() > 0) { + s.append(sep).append(getDisplacement()); + } + s.append("]"); + return s.toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof AMD64Address) { + AMD64Address addr = (AMD64Address) obj; + return getKind() == addr.getKind() && getDisplacement() == addr.getDisplacement() && getBase().equals(addr.getBase()) && getScale() == addr.getScale() && + getIndex().equals(addr.getIndex()); + } + return false; + } + + @Override + public int hashCode() { + return getBase().hashCode() ^ getIndex().hashCode() ^ (getDisplacement() << 4) ^ (getScale().value << 8) ^ (getKind().ordinal() << 12); + } + + /** + * @return Base register that defines the start of the address computation. If not present, is + * denoted by {@link Value#ILLEGAL}. + */ + public Value getBase() { + return baseIndex[0]; + } + + public void setBase(Value base) { + this.baseIndex[0] = base; + } + + /** + * @return Index register, the value of which (possibly scaled by {@link #scale}) is added to + * {@link #getBase}. If not present, is denoted by {@link Value#ILLEGAL}. + */ + public Value getIndex() { + return baseIndex[1]; + } + + public void setIndex(Value index) { + this.baseIndex[1] = index; + } + + /** + * @return Scaling factor for indexing, dependent on target operand size. + */ + public Scale getScale() { + return scale; + } + + /** + * @return Optional additive displacement. + */ + public int getDisplacement() { + return displacement; + } +}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Address.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Address.java Mon Mar 04 10:00:49 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -22,185 +22,23 @@ */ package com.oracle.graal.api.code; -import static com.oracle.graal.api.code.ValueUtil.*; - import com.oracle.graal.api.meta.*; /** - * Represents an address in target machine memory, specified via some combination of a base - * register, an index register, a displacement and a scale. Note that the base and index registers - * may be a variable that will get a register assigned later by the register allocator. + * Base class to represent an address in target machine memory. The concrete representation of the + * address is platform dependent. */ -public final class Address extends Value { +public abstract class Address extends Value { private static final long serialVersionUID = -1003772042519945089L; - /** - * A sentinel value used as a place holder in an instruction stream for an address that will be - * patched. - */ - public static final Address Placeholder = new Address(Kind.Illegal, Value.ILLEGAL); - - private Value base; - private Value index; - private final Scale scale; - private final int displacement; - - /** - * Creates an {@link Address} with given base register, no scaling and no displacement. - * - * @param kind the kind of the value being addressed - * @param base the base register - */ - public Address(Kind kind, Value base) { - this(kind, base, ILLEGAL, Scale.Times1, 0); - } - - /** - * Creates an {@link Address} with given base register, no scaling and a given displacement. - * - * @param kind the kind of the value being addressed - * @param base the base register - * @param displacement the displacement - */ - public Address(Kind kind, Value base, int displacement) { - this(kind, base, ILLEGAL, Scale.Times1, displacement); - } - - /** - * Creates an {@link Address} with given base and index registers, scaling and displacement. - * This is the most general constructor. - * - * @param kind the kind of the value being addressed - * @param base the base register - * @param index the index register - * @param scale the scaling factor - * @param displacement the displacement - */ - public Address(Kind kind, Value base, Value index, Scale scale, int displacement) { + public Address(Kind kind) { super(kind); - this.setBase(base); - this.setIndex(index); - this.scale = scale; - this.displacement = displacement; - - assert !isConstant(base) && !isStackSlot(base); - assert !isConstant(index) && !isStackSlot(index); } /** - * A scaling factor used in complex addressing modes such as those supported by x86 platforms. + * The values that this address is composed of. Used by the register allocator to manipulate + * addresses in a platform independent way. */ - public enum Scale { - Times1(1, 0), Times2(2, 1), Times4(4, 2), Times8(8, 3); - - private Scale(int value, int log2) { - this.value = value; - this.log2 = log2; - } - - /** - * The value (or multiplier) of this scale. - */ - public final int value; - - /** - * The {@linkplain #value value} of this scale log 2. - */ - public final int log2; - - public static Scale fromInt(int scale) { - switch (scale) { - case 1: - return Times1; - case 2: - return Times2; - case 4: - return Times4; - case 8: - return Times8; - default: - throw new IllegalArgumentException(String.valueOf(scale)); - } - } - } - - @Override - public String toString() { - if (this == Placeholder) { - return "[<placeholder>]"; - } - - StringBuilder s = new StringBuilder(); - s.append(getKind().getJavaName()).append("["); - String sep = ""; - if (isLegal(getBase())) { - s.append(getBase()); - sep = " + "; - } - if (isLegal(getIndex())) { - s.append(sep).append(getIndex()).append(" * ").append(getScale().value); - sep = " + "; - } - if (getDisplacement() < 0) { - s.append(" - ").append(-getDisplacement()); - } else if (getDisplacement() > 0) { - s.append(sep).append(getDisplacement()); - } - s.append("]"); - return s.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Address) { - Address addr = (Address) obj; - return getKind() == addr.getKind() && getDisplacement() == addr.getDisplacement() && getBase().equals(addr.getBase()) && getScale() == addr.getScale() && - getIndex().equals(addr.getIndex()); - } - return false; - } - - @Override - public int hashCode() { - return getBase().hashCode() ^ getIndex().hashCode() ^ (getDisplacement() << 4) ^ (getScale().value << 8) ^ (getKind().ordinal() << 12); - } - - /** - * @return Base register that defines the start of the address computation. If not present, is - * denoted by {@link Value#ILLEGAL}. - */ - public Value getBase() { - return base; - } - - public void setBase(Value base) { - this.base = base; - } - - /** - * @return Index register, the value of which (possibly scaled by {@link #scale}) is added to - * {@link #base}. If not present, is denoted by {@link Value#ILLEGAL}. - */ - public Value getIndex() { - return index; - } - - public void setIndex(Value index) { - this.index = index; - } - - /** - * @return Scaling factor for indexing, dependent on target operand size. - */ - public Scale getScale() { - return scale; - } - - /** - * @return Optional additive displacement. - */ - public int getDisplacement() { - return displacement; - } + public abstract Value[] components(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/AllocatableValue.java Mon Mar 04 10:00:49 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.api.code; + +import com.oracle.graal.api.meta.*; + +/** + * Common base class for values that can be manipulated by the register allocator. + */ +public abstract class AllocatableValue extends Value { + + private static final long serialVersionUID = 153019506717492133L; + + /** + * Marker to tell the register allocator that no storage location needs to be allocated for this + * value. + */ + @SuppressWarnings("serial") public static final AllocatableValue UNUSED = new AllocatableValue(Kind.Illegal) { + + @Override + public String toString() { + return "-"; + } + }; + + public AllocatableValue(Kind kind) { + super(kind); + } + +}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Mon Mar 04 10:00:49 2013 +0100 @@ -23,9 +23,6 @@ package com.oracle.graal.api.code; import java.nio.*; -import java.util.*; - -import com.oracle.graal.api.code.Register.RegisterFlag; /** * Represents a CPU architecture, including information such as its endianness, CPU registers, word @@ -79,22 +76,6 @@ */ private final int returnAddressSize; - private final EnumMap<RegisterFlag, Register[]> registersByTypeAndEncoding; - - /** - * Gets the register for a given {@linkplain Register#encoding encoding} and type. - * - * @param encoding a register value as used in a machine instruction - * @param type the type of the register - */ - public Register registerFor(int encoding, RegisterFlag type) { - Register[] regs = registersByTypeAndEncoding.get(type); - assert encoding >= 0 && encoding < regs.length; - Register reg = regs[encoding]; - assert reg != null; - return reg; - } - protected Architecture(String name, int wordSize, ByteOrder byteOrder, Register[] registers, int implicitMemoryBarriers, int nativeCallDisplacementOffset, int registerReferenceMapBitCount, int returnAddressSize) { this.name = name; @@ -105,18 +86,6 @@ this.machineCodeCallDisplacementOffset = nativeCallDisplacementOffset; this.registerReferenceMapBitCount = registerReferenceMapBitCount; this.returnAddressSize = returnAddressSize; - - registersByTypeAndEncoding = new EnumMap<>(RegisterFlag.class); - EnumMap<RegisterFlag, Register[]> categorizedRegs = Register.categorize(registers); - for (RegisterFlag type : RegisterFlag.values()) { - Register[] regs = categorizedRegs.get(type); - int max = Register.maxRegisterEncoding(regs); - Register[] regsByEnc = new Register[max + 1]; - for (Register reg : regs) { - regsByEnc[reg.encoding] = reg; - } - registersByTypeAndEncoding.put(type, regsByEnc); - } } /** @@ -161,14 +130,6 @@ } /** - * Gets a mask of the barrier constants denoting the barriers that are not required to be - * explicitly inserted under this architecture. - */ - public int getImplicitMemoryBarriers() { - return implicitMemoryBarriers; - } - - /** * Gets the size of the return address pushed to the stack by a call instruction. A value of 0 * denotes that call linkage uses registers instead. */
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Mon Mar 04 10:00:49 2013 +0100 @@ -60,10 +60,8 @@ /** * Gets the register configuration to use when compiling a given method. - * - * @param method the top level method of a compilation */ - RegisterConfig lookupRegisterConfig(ResolvedJavaMethod method); + RegisterConfig lookupRegisterConfig(); /** * Custom area on the stack of each compiled method that the VM can use for its own purposes. @@ -81,11 +79,6 @@ int getMinimumOutgoingSize(); /** - * Performs any runtime-specific conversion on the object used to describe the target of a call. - */ - Object lookupCallTarget(Object callTarget); - - /** * Gets the signature and linkage information for a runtime call. */ RuntimeCallTarget lookupRuntimeCall(Descriptor descriptor);
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java Mon Mar 04 10:00:49 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -22,6 +22,7 @@ */ package com.oracle.graal.api.code; +import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.meta.*; @@ -310,4 +311,19 @@ } return sb; } + + /** + * Create a calling convention from a {@link ResolvedJavaMethod}. + */ + public static CallingConvention getCallingConvention(CodeCacheProvider codeCache, CallingConvention.Type type, ResolvedJavaMethod method, boolean stackOnly) { + Signature sig = method.getSignature(); + JavaType retType = sig.getReturnType(null); + JavaType[] argTypes = new JavaType[sig.getParameterCount(!Modifier.isStatic(method.getModifiers()))]; + for (int i = 0; i < argTypes.length; i++) { + argTypes[i] = sig.getParameterType(i, null); + } + + RegisterConfig registerConfig = codeCache.lookupRegisterConfig(); + return registerConfig.getCallingConvention(type, retType, argTypes, codeCache.getTarget(), stackOnly); + } }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Mon Mar 04 10:00:49 2013 +0100 @@ -94,7 +94,7 @@ /** * The target of the call. */ - public final Object target; + public final InvokeTarget target; /** * The size of the call instruction. @@ -108,7 +108,7 @@ */ public final boolean direct; - public Call(Object target, int pcOffset, int size, boolean direct, DebugInfo debugInfo) { + public Call(InvokeTarget target, int pcOffset, int size, boolean direct, DebugInfo debugInfo) { super(pcOffset, debugInfo); this.size = size; this.target = target; @@ -196,25 +196,6 @@ } /** - * Labels some inline data in the code. - */ - public static final class InlineData extends CodeAnnotation { - - private static final long serialVersionUID = 305997507263827108L; - public final int size; - - public InlineData(int position, int size) { - super(position); - this.size = size; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "@" + position + ": size=" + size; - } - } - - /** * Describes a table of signed offsets embedded in the code. The offsets are relative to the * starting address of the table. This type of table maybe generated when translating a * multi-way branch based on a key value from a dense value set (e.g. the {@code tableswitch} @@ -256,43 +237,6 @@ } /** - * Describes a table of key and offset pairs. The offset in each table entry is relative to the - * address of the table. This type of table maybe generated when translating a multi-way branch - * based on a key value from a sparse value set (e.g. the {@code lookupswitch} JVM instruction). - */ - public static final class LookupTable extends CodeAnnotation { - - private static final long serialVersionUID = 8367952567559116160L; - - /** - * The number of entries in the table. - */ - public final int npairs; - - /** - * The size (in bytes) of entry's key. - */ - public final int keySize; - - /** - * The size (in bytes) of entry's offset value. - */ - public final int offsetSize; - - public LookupTable(int position, int npairs, int keySize, int offsetSize) { - super(position); - this.npairs = npairs; - this.keySize = keySize; - this.offsetSize = offsetSize; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "@" + position + ": [npairs=" + npairs + ", keySize=" + keySize + ", offsetSize=" + offsetSize + "]"; - } - } - - /** * Represents exception handler information for a specific code position. It includes the catch * code position as well as the caught exception type. */ @@ -349,8 +293,6 @@ private int customStackAreaOffset = -1; private int registerRestoreEpilogueOffset = -1; - private CalleeSaveLayout calleeSaveLayout; - /** * The buffer containing the emitted machine code. */ @@ -410,15 +352,6 @@ } /** - * Sets the info on callee-saved registers used by this method. - * - * @param csl the register-saving info. - */ - public void setCalleeSaveLayout(CalleeSaveLayout csl) { - calleeSaveLayout = csl; - } - - /** * Records a reference to the data section in the code section (e.g. to load an integer or * floating point constant). * @@ -438,11 +371,11 @@ * * @param codePos the position of the call in the code array * @param size the size of the call instruction - * @param target the {@link CodeCacheProvider#lookupCallTarget(Object) target} being called + * @param target the being called * @param debugInfo the debug info for the call * @param direct specifies if this is a {@linkplain Call#direct direct} call */ - public void recordCall(int codePos, int size, Object target, DebugInfo debugInfo, boolean direct) { + public void recordCall(int codePos, int size, InvokeTarget target, DebugInfo debugInfo, boolean direct) { final Call call = new Call(target, codePos, size, direct, debugInfo); addSafepoint(call); } @@ -537,13 +470,6 @@ } /** - * @return the layout information for callee-saved registers used by this method. - */ - public CalleeSaveLayout getCalleeSaveLayout() { - return calleeSaveLayout; - } - - /** * @return the machine code generated for this method */ public byte[] getTargetCode() {
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DisassemblerProvider.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DisassemblerProvider.java Mon Mar 04 10:00:49 2013 +0100 @@ -29,6 +29,10 @@ /** * Gets a textual disassembly of some given installed code. + * + * @return a non-zero length string containing a disassembly of {@code code} or null if + * {@code code} is {@link InstalledCode#isValid() invalid} or it could not be + * disassembled for some other reason */ String disassemble(InstalledCode code); }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java Mon Mar 04 10:00:49 2013 +0100 @@ -65,6 +65,13 @@ public final int encoding; /** + * The assembler calls this method to get the register's encoding. + */ + public int encoding() { + return encoding; + } + + /** * The size of the stack slot used to spill the value of this register. */ public final int spillSlotSize;
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterValue.java Mon Mar 04 10:00:49 2013 +0100 @@ -30,7 +30,7 @@ * {@link Register#asValue(Kind)} to retrieve the canonical {@link RegisterValue} instance for a * given (register,kind) pair. */ -public final class RegisterValue extends Value { +public final class RegisterValue extends AllocatableValue { private static final long serialVersionUID = 7999341472196897163L;
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java Mon Mar 04 10:00:49 2013 +0100 @@ -24,11 +24,13 @@ import java.util.*; +import com.oracle.graal.api.meta.*; + /** * The name, signature and calling convention of a call from compiled code to the runtime. The * target of such a call may be a leaf stub or a call into the runtime code proper. */ -public interface RuntimeCallTarget { +public interface RuntimeCallTarget extends InvokeTarget { /** * The name and signature of a runtime call.
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackSlot.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackSlot.java Mon Mar 04 10:00:49 2013 +0100 @@ -30,7 +30,7 @@ * Represents a compiler spill slot or an outgoing stack-based argument in a method's frame or an * incoming stack-based argument in a method's {@linkplain #isInCallerFrame() caller's frame}. */ -public final class StackSlot extends Value { +public final class StackSlot extends AllocatableValue { private static final long serialVersionUID = -7725071921307318433L; @@ -165,7 +165,7 @@ private static StackSlot[][] makeCache(int cachePerKindSize, int sign, boolean addFrameSize) { StackSlot[][] cache = new StackSlot[Kind.values().length][]; - for (Kind kind : new Kind[]{Illegal, Int, Long, Float, Double, Object, Jsr}) { + for (Kind kind : new Kind[]{Illegal, Int, Long, Float, Double, Object}) { StackSlot[] slots = new StackSlot[cachePerKindSize]; for (int i = 0; i < cachePerKindSize; i++) { slots[i] = new StackSlot(kind, sign * i * CACHE_GRANULARITY, addFrameSize);
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java Mon Mar 04 10:00:49 2013 +0100 @@ -33,11 +33,6 @@ public final Architecture arch; /** - * The OS page size. - */ - public final int pageSize; - - /** * Specifies if this is a multi-processor system. */ public final boolean isMP; @@ -72,44 +67,19 @@ public final int stackAlignment; /** - * @see "http://docs.oracle.com/cd/E19455-01/806-0477/overview-4/index.html" - */ - public final int stackBias; - - /** - * The cache alignment. - */ - public final int cacheAlignment; - - /** * Maximum constant displacement at which a memory access can no longer be an implicit null * check. */ public final int implicitNullCheckLimit; - /** - * Specifies how {@code long} and {@code double} constants are to be stored in - * {@linkplain BytecodeFrame frames}. This is useful for VMs such as HotSpot where convention - * the interpreter uses is that the second local holds the first raw word of the native long or - * double representation. This is actually reasonable, since locals and stack arrays grow - * downwards in all implementations. If, on some machine, the interpreter's Java locals or stack - * were to grow upwards, the embedded doubles would be word-swapped.) - */ - public final boolean debugInfoDoubleWordsInSecondSlot; - - public TargetDescription(Architecture arch, boolean isMP, int stackAlignment, int stackBias, int implicitNullCheckLimit, int pageSize, int cacheAlignment, boolean inlineObjects, - boolean debugInfoDoubleWordsInSecondSlot) { + public TargetDescription(Architecture arch, boolean isMP, int stackAlignment, int implicitNullCheckLimit, boolean inlineObjects) { this.arch = arch; - this.pageSize = pageSize; this.isMP = isMP; this.wordSize = arch.getWordSize(); this.wordKind = Kind.fromWordSize(wordSize); this.stackAlignment = stackAlignment; - this.stackBias = stackBias; this.implicitNullCheckLimit = implicitNullCheckLimit; - this.cacheAlignment = cacheAlignment; this.inlineObjects = inlineObjects; - this.debugInfoDoubleWordsInSecondSlot = debugInfoDoubleWordsInSecondSlot; } /** @@ -139,8 +109,6 @@ return 8; case Object: return wordSize; - case Jsr: - return 4; default: return 0; }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Mon Mar 04 10:00:49 2013 +0100 @@ -58,6 +58,16 @@ return (Constant) value; } + public static boolean isAllocatableValue(Value value) { + assert value != null; + return value instanceof AllocatableValue; + } + + public static AllocatableValue asAllocatableValue(Value value) { + assert value != null; + return (AllocatableValue) value; + } + public static boolean isStackSlot(Value value) { assert value != null; return value instanceof StackSlot; @@ -89,7 +99,7 @@ } public static Register asIntReg(Value value) { - assert value.getKind() == Kind.Int || value.getKind() == Kind.Jsr; + assert value.getKind() == Kind.Int; return asRegister(value); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,61 @@ +/* + * 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.meta.test; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; + +/** + * Tests for {@link BytecodeDisassemblerProvider}. + */ +public class TestBytecodeDisassemblerProvider { + + public TestBytecodeDisassemblerProvider() { + } + + /** + * Tests that successive disassembling of the same method produces the same result. + */ + @Test + public void disassembleTest() { + BytecodeDisassemblerProvider dis = Graal.getRuntime().getCapability(BytecodeDisassemblerProvider.class); + if (dis != null) { + int count = 0; + for (ResolvedJavaMethod m : TestJavaMethod.methods.values()) { + String disasm1 = dis.disassemble(m); + String disasm2 = dis.disassemble(m); + if (disasm1 == null) { + Assert.assertTrue(disasm2 == null); + } else { + Assert.assertTrue(String.valueOf(m), disasm1.length() > 0); + Assert.assertEquals(String.valueOf(m), disasm1, disasm2); + } + if (count++ > 20) { + break; + } + } + } + } +}
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Mon Mar 04 10:00:49 2013 +0100 @@ -49,11 +49,14 @@ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) { ResolvedJavaMethod m = e.getValue(); byte[] code = m.getCode(); - assertNotNull(code); - if (isAbstract(m.getModifiers())) { - assertTrue(code.length == 0); - } else if (!isNative(m.getModifiers())) { - assertTrue(code.length > 0); + if (code == null) { + assertTrue(m.getCodeSize() == 0); + } else { + if (isAbstract(m.getModifiers())) { + assertTrue(code.length == 0); + } else if (!isNative(m.getModifiers())) { + assertTrue(code.length > 0); + } } } }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java Mon Mar 04 10:00:49 2013 +0100 @@ -29,6 +29,7 @@ import java.lang.annotation.*; import java.lang.reflect.*; +import java.net.*; import java.util.*; import org.junit.*; @@ -541,4 +542,36 @@ } } } + + @Test + public void memberClassesTest() { + for (Class c : classes) { + ResolvedJavaType type = runtime.lookupJavaType(c); + assertEquals(c.isLocalClass(), type.isLocal()); + assertEquals(c.isMemberClass(), type.isMember()); + Class enclc = c.getEnclosingClass(); + ResolvedJavaType enclt = type.getEnclosingType(); + assertFalse(enclc == null ^ enclt == null); + if (enclc != null) { + assertEquals(enclt, runtime.lookupJavaType(enclc)); + } + } + } + + @Test + public void classFilePathTest() { + for (Class c : classes) { + ResolvedJavaType type = runtime.lookupJavaType(c); + URL path = type.getClassFilePath(); + if (type.isPrimitive() || type.isArray()) { + assertEquals(null, path); + } else { + assertNotNull(path); + String pathString = path.getPath(); + if (type.isLocal() || type.isMember()) { + assertTrue(pathString.indexOf('$') > 0); + } + } + } + } }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/BytecodeDisassemblerProvider.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/BytecodeDisassemblerProvider.java Mon Mar 04 10:00:49 2013 +0100 @@ -28,7 +28,11 @@ public interface BytecodeDisassemblerProvider { /** - * Gets a textual disassembly of the bytecode for a given method. + * Gets a textual disassembly of the bytecode for a given method. In the absence of bytecode + * rewriting, disassembling a method will produce the same result. + * + * @return a non-zero length string containing a disassembly of {@code method}'s bytecode or + * null if {@code method} has no bytecode (i.e., {@code method.getCodeSize() == 0}) */ String disassemble(ResolvedJavaMethod method); }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Mon Mar 04 10:00:49 2013 +0100 @@ -134,8 +134,6 @@ return (short) primitive; case Char: return (char) primitive; - case Jsr: - return (int) primitive; case Int: return (int) primitive; case Long: @@ -163,12 +161,12 @@ /** * Returns the primitive int value this constant represents. The constant must have a - * {@link Kind#getStackKind()} of {@link Kind#Int}, or kind {@link Kind#Jsr}. + * {@link Kind#getStackKind()} of {@link Kind#Int}. * * @return the constant value */ public int asInt() { - assert getKind().getStackKind() == Kind.Int || getKind() == Kind.Jsr; + assert getKind().getStackKind() == Kind.Int; return (int) primitive; } @@ -185,13 +183,12 @@ /** * Returns the primitive long value this constant represents. The constant must have kind - * {@link Kind#Long}, a {@link Kind#getStackKind()} of {@link Kind#Int}, or kind - * {@link Kind#Jsr}. + * {@link Kind#Long}, a {@link Kind#getStackKind()} of {@link Kind#Int}. * * @return the constant value */ public long asLong() { - assert getKind() == Kind.Long || getKind().getStackKind() == Kind.Int || getKind() == Kind.Jsr; + assert getKind() == Kind.Long || getKind().getStackKind() == Kind.Int; return primitive; } @@ -365,16 +362,6 @@ } /** - * Creates a boxed address (jsr/ret address) constant. - * - * @param i the address value to box - * @return a boxed copy of {@code value} - */ - public static Constant forJsr(int i) { - return new Constant(Kind.Jsr, null, i); - } - - /** * Creates a boxed object constant. * * @param o the object value to box
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/InvokeTarget.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.meta; + +/** + * Represents the resolved target of an invocation. + */ +public interface InvokeTarget { +}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java Mon Mar 04 10:00:49 2013 +0100 @@ -60,9 +60,6 @@ /** The void float kind. */ Void('v', "void", false, java.lang.Void.TYPE, java.lang.Void.class), - /** Denote a bytecode address in a {@code JSR} bytecode. */ - Jsr('r', "jsr", false, null, null), - /** The non-type. */ Illegal('-', "illegal", false, null, null); @@ -318,7 +315,6 @@ return java.lang.Character.MIN_VALUE; case Short: return java.lang.Short.MIN_VALUE; - case Jsr: case Int: return java.lang.Integer.MIN_VALUE; case Long: @@ -343,7 +339,6 @@ return java.lang.Character.MAX_VALUE; case Short: return java.lang.Short.MAX_VALUE; - case Jsr: case Int: return java.lang.Integer.MAX_VALUE; case Long: @@ -367,7 +362,6 @@ case Char: case Short: return 16; - case Jsr: case Int: return 32; case Long:
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Mon Mar 04 10:00:49 2013 +0100 @@ -87,10 +87,11 @@ /** * Reads a value of this kind using a base address and a displacement. - * + * * @param base the base address from which the value is read * @param displacement the displacement within the object in bytes - * @return the read value encapsulated in a {@link Constant} object, or {@code null} if the value cannot be read. + * @return the read value encapsulated in a {@link Constant} object, or {@code null} if the + * value cannot be read. */ Constant readUnsafeConstant(Kind kind, Object base, long displacement); }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Mon Mar 04 10:00:49 2013 +0100 @@ -135,7 +135,7 @@ String prefix = ""; Class<?> enclosingClass = clazz; while ((enclosingClass = enclosingClass.getEnclosingClass()) != null) { - prefix = prefix + enclosingClass.getSimpleName() + "."; + prefix = enclosingClass.getSimpleName() + "." + prefix; } return prefix + simpleName; }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Mon Mar 04 10:00:49 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -31,21 +31,21 @@ * Represents a resolved Java method. Methods, like fields and types, are resolved through * {@link ConstantPool constant pools}. */ -public interface ResolvedJavaMethod extends JavaMethod { +public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget { /** - * Returns the bytecodes of this method, if the method has code. The returned byte array does - * not contain breakpoints or non-Java bytecodes. + * Returns the bytecode of this method, if the method has code. The returned byte array does not + * contain breakpoints or non-Java bytecodes. * - * @return the bytecodes of the method, or {@code null} if none is available + * @return the bytecode of the method, or {@code null} if {@code getCodeSize() == 0} */ byte[] getCode(); /** - * Returns the size of the bytecodes of this method, if the method has code. This is equivalent + * Returns the size of the bytecode of this method, if the method has code. This is equivalent * to {@link #getCode()}. {@code length} if the method has code. * - * @return the size of the bytecodes in bytes, or 0 if no bytecodes is available + * @return the size of the bytecode in bytes, or 0 if no bytecode is available */ int getCodeSize();
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Mon Mar 04 10:00:49 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -24,6 +24,7 @@ import java.lang.annotation.*; import java.lang.reflect.*; +import java.net.*; /** * Represents a resolved Java type. Types include primitives, objects, {@code void}, and arrays @@ -253,4 +254,24 @@ * Returns name of source file of this type. */ String getSourceFileName(); + + /** + * Returns the class file path - if available - of this type, or {@code null}. + */ + URL getClassFilePath(); + + /** + * Returns {@code true} if the type is a local type. + */ + boolean isLocal(); + + /** + * Returns {@code true} if the type is a member type. + */ + boolean isMember(); + + /** + * Returns the enclosing type of this type, if it exists, or {@code null}. + */ + ResolvedJavaType getEnclosingType(); }
--- a/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -57,7 +57,7 @@ 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.movdbl(ret, asm.getPlaceholder()); asm.ret(0); return asm.codeBuffer; }
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Mon Mar 04 10:00:49 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -47,15 +47,38 @@ private static final int MinEncodingNeedsRex = 8; /** + * A sentinel value used as a place holder in an instruction stream for an address that will be + * patched. + */ + private static final AMD64Address Placeholder = new AMD64Address(Kind.Illegal, rip.asValue()); + + /** * The x86 condition codes used for conditional jumps/moves. */ public enum ConditionFlag { - zero(0x4, "|zero|"), notZero(0x5, "|nzero|"), equal(0x4, "="), notEqual(0x5, "!="), less(0xc, "<"), lessEqual(0xe, "<="), greater(0xf, ">"), greaterEqual(0xd, ">="), below(0x2, "|<|"), belowEqual( - 0x6, "|<=|"), above(0x7, "|>|"), aboveEqual(0x3, "|>=|"), overflow(0x0, "|of|"), noOverflow(0x1, "|nof|"), carrySet(0x2, "|carry|"), carryClear(0x3, "|ncarry|"), negative(0x8, - "|neg|"), positive(0x9, "|pos|"), parity(0xa, "|par|"), noParity(0xb, "|npar|"); + Zero(0x4, "|zero|"), + NotZero(0x5, "|nzero|"), + Equal(0x4, "="), + NotEqual(0x5, "!="), + Less(0xc, "<"), + LessEqual(0xe, "<="), + Greater(0xf, ">"), + GreaterEqual(0xd, ">="), + Below(0x2, "|<|"), + BelowEqual(0x6, "|<=|"), + Above(0x7, "|>|"), + AboveEqual(0x3, "|>=|"), + Overflow(0x0, "|of|"), + NoOverflow(0x1, "|nof|"), + CarrySet(0x2, "|carry|"), + CarryClear(0x3, "|ncarry|"), + Negative(0x8, "|neg|"), + Positive(0x9, "|pos|"), + Parity(0xa, "|par|"), + NoParity(0xb, "|npar|"); - public final int value; - public final String operator; + private final int value; + private final String operator; private ConditionFlag(int value, String operator) { this.value = value; @@ -64,49 +87,58 @@ public ConditionFlag negate() { switch (this) { - case zero: - return notZero; - case notZero: - return zero; - case equal: - return notEqual; - case notEqual: - return equal; - case less: - return greaterEqual; - case lessEqual: - return greater; - case greater: - return lessEqual; - case greaterEqual: - return less; - case below: - return aboveEqual; - case belowEqual: - return above; - case above: - return belowEqual; - case aboveEqual: - return below; - case overflow: - return noOverflow; - case noOverflow: - return overflow; - case carrySet: - return carryClear; - case carryClear: - return carrySet; - case negative: - return positive; - case positive: - return negative; - case parity: - return noParity; - case noParity: - return parity; + case Zero: + return NotZero; + case NotZero: + return Zero; + case Equal: + return NotEqual; + case NotEqual: + return Equal; + case Less: + return GreaterEqual; + case LessEqual: + return Greater; + case Greater: + return LessEqual; + case GreaterEqual: + return Less; + case Below: + return AboveEqual; + case BelowEqual: + return Above; + case Above: + return BelowEqual; + case AboveEqual: + return Below; + case Overflow: + return NoOverflow; + case NoOverflow: + return Overflow; + case CarrySet: + return CarryClear; + case CarryClear: + return CarrySet; + case Negative: + return Positive; + case Positive: + return Negative; + case Parity: + return NoParity; + case NoParity: + return Parity; } throw new IllegalArgumentException(); } + + public int getValue() { + return value; + } + + @Override + public String toString() { + return operator; + } } /** @@ -155,16 +187,6 @@ return r.encoding & 0x7; } - private void emitArithB(int op1, int op2, Register dst, int imm8) { - assert dst.isByte() : "must have byte register"; - assert isUByte(op1) && isUByte(op2) : "wrong opcode"; - assert isUByte(imm8) : "not a byte"; - assert (op1 & 0x01) == 0 : "should be 8bit operation"; - emitByte(op1); - emitByte(op2 | encode(dst)); - emitByte(imm8); - } - private void emitArith(int op1, int op2, Register dst, int imm32) { assert isUByte(op1) && isUByte(op2) : "wrong opcode"; assert (op1 & 0x01) == 1 : "should be 32bit operation"; @@ -181,7 +203,7 @@ } // immediate-to-memory forms - private void emitArithOperand(int op1, Register rm, Address adr, int imm32) { + private void emitArithOperand(int op1, Register rm, AMD64Address adr, int imm32) { assert (op1 & 0x01) == 1 : "should be 32bit operation"; assert (op1 & 0x02) == 0 : "sign-extension bit should not be set"; if (isByte(imm32)) { @@ -201,21 +223,16 @@ emitByte(op2 | encode(dst) << 3 | encode(src)); } - protected void emitOperandHelper(Register reg, Address addr) { + protected void emitOperandHelper(Register reg, AMD64Address addr) { Register base = isLegal(addr.getBase()) ? asRegister(addr.getBase()) : Register.None; Register index = isLegal(addr.getIndex()) ? asRegister(addr.getIndex()) : Register.None; - Address.Scale scale = addr.getScale(); + AMD64Address.Scale scale = addr.getScale(); int disp = addr.getDisplacement(); if (base == Register.Frame) { assert frameRegister != null : "cannot use register " + Register.Frame + " in assembler with null register configuration"; base = frameRegister; - // } else if (base == Register.CallerFrame) { - // assert frameRegister != null : "cannot use register " + Register.Frame + - // " in assembler with null register configuration"; - // base = frameRegister; - // disp += targetMethod.frameSize() + 8; } // Encode the registers as needed in the fields they are used in @@ -223,15 +240,11 @@ assert reg != Register.None; int regenc = encode(reg) << 3; - if (base == AMD64.rip) { + if (base == AMD64.rip) { // also matches Placeholder // [00 000 101] disp32 + assert index == Register.None : "cannot use RIP relative addressing with index register"; emitByte(0x05 | regenc); emitInt(disp); - } else if (addr == Address.Placeholder) { - // [00 000 101] disp32 - emitByte(0x05 | regenc); - emitInt(0); - } else if (base.isValid()) { int baseenc = base.isValid() ? encode(base) : 0; if (index.isValid()) { @@ -316,23 +329,17 @@ } } - public final void addl(Address dst, int imm32) { + public final void addl(AMD64Address dst, int imm32) { prefix(dst); emitArithOperand(0x81, rax, dst, imm32); } - public final void addl(Address dst, Register src) { - prefix(dst, src); - emitByte(0x01); - emitOperandHelper(src, dst); - } - public final void addl(Register dst, int imm32) { prefix(dst); emitArith(0x81, 0xC0, dst, imm32); } - public final void addl(Register dst, Address src) { + public final void addl(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x03); emitOperandHelper(dst, src); @@ -386,7 +393,7 @@ emitByte(0xC0 | encode); } - public final void addsd(Register dst, Address src) { + public final void addsd(Register dst, AMD64Address src) { assert dst.isFpu(); emitByte(0xF2); prefix(src, dst); @@ -404,7 +411,7 @@ emitByte(0xC0 | encode); } - public final void addss(Register dst, Address src) { + public final void addss(Register dst, AMD64Address src) { assert dst.isFpu(); emitByte(0xF3); prefix(src, dst); @@ -418,7 +425,7 @@ emitArith(0x81, 0xE0, dst, imm32); } - public final void andl(Register dst, Address src) { + public final void andl(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x23); emitOperandHelper(dst, src); @@ -436,7 +443,7 @@ emitByte(0xC0 | encode); } - public final void bsfq(Register dst, Address src) { + public final void bsfq(Register dst, AMD64Address src) { prefixq(src, dst); emitByte(0xBC); emitOperandHelper(dst, src); @@ -449,7 +456,7 @@ emitByte(0xC0 | encode); } - public final void bsrq(Register dst, Address src) { + public final void bsrq(Register dst, AMD64Address src) { prefixq(src, dst); emitByte(0xBD); emitOperandHelper(dst, src); @@ -462,26 +469,18 @@ emitByte(0xC0 | encode); } - public final void bsrl(Register dst, Address src) { + public final void bsrl(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0xBD); emitOperandHelper(dst, src); } - public final void bswapl(Register reg) { // bswap + public final void bswapl(Register reg) { int encode = prefixAndEncode(reg.encoding); emitByte(0x0F); emitByte(0xC8 | encode); } - public final void btli(Address src, int imm8) { - prefixq(src); - emitByte(0x0F); - emitByte(0xBA); - emitOperandHelper(rsp, src); - emitByte(imm8); - } - public final void cdql() { emitByte(0x99); } @@ -489,31 +488,17 @@ public final void cmovl(ConditionFlag cc, Register dst, Register src) { int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); - emitByte(0x40 | cc.value); + emitByte(0x40 | cc.getValue()); emitByte(0xC0 | encode); } - public final void cmovl(ConditionFlag cc, Register dst, Address src) { + public final void cmovl(ConditionFlag cc, Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x0F); - emitByte(0x40 | cc.value); + emitByte(0x40 | cc.getValue()); emitOperandHelper(dst, src); } - public final void cmpb(Address dst, int imm8) { - prefix(dst); - emitByte(0x80); - emitOperandHelper(rdi, dst); - emitByte(imm8); - } - - public final void cmpl(Address dst, int imm32) { - prefix(dst); - emitByte(0x81); - emitOperandHelper(rdi, dst); - emitInt(imm32); - } - public final void cmpl(Register dst, int imm32) { prefix(dst); emitArith(0x81, 0xF8, dst, imm32); @@ -524,7 +509,7 @@ emitArith(0x3B, 0xC0, dst, src); } - public final void cmpl(Register dst, Address src) { + public final void cmpl(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x3B); emitOperandHelper(dst, src); @@ -533,7 +518,7 @@ // The 32-bit cmpxchg compares the value at adr with the contents of X86.rax, // and stores reg into adr if so; otherwise, the value at adr is loaded into X86.rax,. // The ZF is set if the compared values were equal, and cleared otherwise. - public final void cmpxchgl(Register reg, Address adr) { // cmpxchg + public final void cmpxchgl(Register reg, AMD64Address adr) { // cmpxchg if ((Atomics & 2) != 0) { // caveat: no instructionmark, so this isn't relocatable. // Emit a synthetic, non-atomic, CAS equivalent. @@ -543,7 +528,7 @@ movl(rax, adr); if (reg != rax) { Label l = new Label(); - jcc(ConditionFlag.notEqual, l); + jccb(ConditionFlag.NotEqual, l); movl(adr, reg); bind(l); } @@ -556,43 +541,6 @@ } } - public final void comisd(Register dst, Address src) { - assert dst.isFpu(); - // NOTE: dbx seems to decode this as comiss even though the - // 0x66 is there. Strangly ucomisd comes out correct - emitByte(0x66); - comiss(dst, src); - } - - public final void comiss(Register dst, Address src) { - assert dst.isFpu(); - - prefix(src, dst); - emitByte(0x0F); - emitByte(0x2F); - emitOperandHelper(dst, src); - } - - public final void cvtdq2pd(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); - - emitByte(0xF3); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xE6); - emitByte(0xC0 | encode); - } - - public final void cvtdq2ps(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x5B); - emitByte(0xC0 | encode); - } - public final void cvtsd2ss(Register dst, Register src) { assert dst.isFpu(); assert src.isFpu(); @@ -649,14 +597,13 @@ emitByte(0xC0 | encode); } - public final void decl(Address dst) { - // Don't use it directly. Use Macrodecrement() instead. + protected final void decl(AMD64Address dst) { prefix(dst); emitByte(0xFF); emitOperandHelper(rcx, dst); } - public final void divsd(Register dst, Address src) { + public final void divsd(Register dst, AMD64Address src) { assert dst.isFpu(); emitByte(0xF2); prefix(src, dst); @@ -675,7 +622,7 @@ emitByte(0xC0 | encode); } - public final void divss(Register dst, Address src) { + public final void divss(Register dst, AMD64Address src) { assert dst.isFpu(); emitByte(0xF3); prefix(src, dst); @@ -730,32 +677,31 @@ } } - public final void incl(Address dst) { - // Don't use it directly. Use Macroincrement() instead. + protected final void incl(AMD64Address dst) { prefix(dst); emitByte(0xFF); emitOperandHelper(rax, dst); } - public final void jcc(ConditionFlag cc, int jumpTarget, boolean forceDisp32) { + private void jcc(ConditionFlag cc, int jumpTarget, boolean forceDisp32) { int shortSize = 2; int longSize = 6; long disp = jumpTarget - codeBuffer.position(); if (!forceDisp32 && isByte(disp - shortSize)) { // 0111 tttn #8-bit disp - emitByte(0x70 | cc.value); + emitByte(0x70 | cc.getValue()); emitByte((int) ((disp - shortSize) & 0xFF)); } else { // 0000 1111 1000 tttn #32-bit disp assert isInt(disp - longSize) : "must be 32bit offset (call4)"; emitByte(0x0F); - emitByte(0x80 | cc.value); + emitByte(0x80 | cc.getValue()); emitInt((int) (disp - longSize)); } } public final void jcc(ConditionFlag cc, Label l) { - assert (0 <= cc.value) && (cc.value < 16) : "illegal cc"; + assert (0 <= cc.getValue()) && (cc.getValue() < 16) : "illegal cc"; if (l.isBound()) { jcc(cc, l.position(), false); } else { @@ -765,7 +711,7 @@ // an 8-bit displacement l.addPatchAt(codeBuffer.position()); emitByte(0x0F); - emitByte(0x80 | cc.value); + emitByte(0x80 | cc.getValue()); emitInt(0); } @@ -778,22 +724,16 @@ assert isByte(entry - (codeBuffer.position() + shortSize)) : "Dispacement too large for a short jmp"; long disp = entry - codeBuffer.position(); // 0111 tttn #8-bit disp - emitByte(0x70 | cc.value); + emitByte(0x70 | cc.getValue()); emitByte((int) ((disp - shortSize) & 0xFF)); } else { l.addPatchAt(codeBuffer.position()); - emitByte(0x70 | cc.value); + emitByte(0x70 | cc.getValue()); emitByte(0); } } - public final void jmp(Address adr) { - prefix(adr); - emitByte(0xFF); - emitOperandHelper(rsp, adr); - } - public final void jmp(int jumpTarget, boolean forceDisp32) { int shortSize = 2; int longSize = 5; @@ -845,18 +785,12 @@ } } - public final void leaq(Register dst, Address src) { + public final void leaq(Register dst, AMD64Address src) { prefixq(src, dst); emitByte(0x8D); emitOperandHelper(dst, src); } - public final void enter(int imm16, int imm8) { - emitByte(0xC8); - emitShort(imm16); - emitByte(imm8); - } - public final void leave() { emitByte(0xC9); } @@ -870,17 +804,6 @@ } } - // Emit mfence instruction - public final void mfence() { - emitByte(0x0F); - emitByte(0xAE); - emitByte(0xF0); - } - - public final void mov(Register dst, Register src) { - movq(dst, src); - } - public final void movapd(Register dst, Register src) { assert dst.isFpu(); assert src.isFpu(); @@ -930,20 +853,14 @@ emitByte(0xC0 | dstenc << 3 | srcenc); } - public final void movb(Register dst, Address src) { - prefix(src, dst); // , true) - emitByte(0x8A); - emitOperandHelper(dst, src); - } - - public final void movb(Address dst, int imm8) { + public final void movb(AMD64Address dst, int imm8) { prefix(dst); emitByte(0xC6); emitOperandHelper(rax, dst); emitByte(imm8); } - public final void movb(Address dst, Register src) { + public final void movb(AMD64Address dst, Register src) { assert src.isByte() : "must have byte register"; prefix(dst, src); // , true) emitByte(0x88); @@ -969,63 +886,6 @@ } } - public final void movdqa(Register dst, Address src) { - assert dst.isFpu(); - emitByte(0x66); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x6F); - emitOperandHelper(dst, src); - } - - public final void movdqa(Register dst, Register src) { - assert dst.isFpu(); - emitByte(0x66); - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x6F); - emitByte(0xC0 | encode); - } - - public final void movdqa(Address dst, Register src) { - assert src.isFpu(); - emitByte(0x66); - prefix(dst, src); - emitByte(0x0F); - emitByte(0x7F); - emitOperandHelper(src, dst); - } - - public final void movdqu(Register dst, Address src) { - assert dst.isFpu(); - emitByte(0xF3); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x6F); - emitOperandHelper(dst, src); - } - - public final void movdqu(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); - - emitByte(0xF3); - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x6F); - emitByte(0xC0 | encode); - } - - public final void movdqu(Address dst, Register src) { - assert src.isFpu(); - - emitByte(0xF3); - prefix(dst, src); - emitByte(0x0F); - emitByte(0x7F); - emitOperandHelper(src, dst); - } - public final void movl(Register dst, int imm32) { int encode = prefixAndEncode(dst.encoding); emitByte(0xB8 | encode); @@ -1038,20 +898,20 @@ emitByte(0xC0 | encode); } - public final void movl(Register dst, Address src) { + public final void movl(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x8B); emitOperandHelper(dst, src); } - public final void movl(Address dst, int imm32) { + public final void movl(AMD64Address dst, int imm32) { prefix(dst); emitByte(0xC7); emitOperandHelper(rax, dst); emitInt(imm32); } - public final void movl(Address dst, Register src) { + public final void movl(AMD64Address dst, Register src) { prefix(dst, src); emitByte(0x89); emitOperandHelper(src, dst); @@ -1060,10 +920,10 @@ /** * New CPUs require use of movsd and movss to avoid partial register stall when loading from * memory. But for old Opteron use movlpd instead of movsd. The selection is done in - * {@link AMD64MacroAssembler#movdbl(Register, Address)} and + * {@link AMD64MacroAssembler#movdbl(Register, AMD64Address)} and * {@link AMD64MacroAssembler#movflt(Register, Register)}. */ - public final void movlpd(Register dst, Address src) { + public final void movlpd(Register dst, AMD64Address src) { assert dst.isFpu(); emitByte(0x66); prefix(src, dst); @@ -1072,16 +932,7 @@ emitOperandHelper(dst, src); } - public final void movlpd(Address dst, Register src) { - assert src.isFpu(); - emitByte(0x66); - prefix(dst, src); - emitByte(0x0F); - emitByte(0x13); - emitOperandHelper(src, dst); - } - - public final void movq(Register dst, Address src) { + public final void movq(Register dst, AMD64Address src) { if (dst.isFpu()) { emitByte(0xF3); prefixq(src, dst); @@ -1101,7 +952,7 @@ emitByte(0xC0 | encode); } - public final void movq(Address dst, Register src) { + public final void movq(AMD64Address dst, Register src) { if (src.isFpu()) { emitByte(0x66); prefixq(dst, src); @@ -1115,14 +966,14 @@ } } - public final void movsxb(Register dst, Address src) { // movsxb + public final void movsxb(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x0F); emitByte(0xBE); emitOperandHelper(dst, src); } - public final void movsxb(Register dst, Register src) { // movsxb + public final void movsxb(Register dst, Register src) { int encode = prefixAndEncode(dst.encoding, src.encoding, true); emitByte(0x0F); emitByte(0xBE); @@ -1139,7 +990,7 @@ emitByte(0xC0 | encode); } - public final void movsd(Register dst, Address src) { + public final void movsd(Register dst, AMD64Address src) { assert dst.isFpu(); emitByte(0xF2); prefix(src, dst); @@ -1148,7 +999,7 @@ emitOperandHelper(dst, src); } - public final void movsd(Address dst, Register src) { + public final void movsd(AMD64Address dst, Register src) { assert src.isFpu(); emitByte(0xF2); prefix(dst, src); @@ -1167,7 +1018,7 @@ emitByte(0xC0 | encode); } - public final void movss(Register dst, Address src) { + public final void movss(Register dst, AMD64Address src) { assert dst.isFpu(); emitByte(0xF3); prefix(src, dst); @@ -1176,7 +1027,7 @@ emitOperandHelper(dst, src); } - public final void movss(Address dst, Register src) { + public final void movss(AMD64Address dst, Register src) { assert src.isFpu(); emitByte(0xF3); prefix(dst, src); @@ -1185,40 +1036,21 @@ emitOperandHelper(src, dst); } - public final void movswl(Register dst, Address src) { + public final void movswl(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x0F); emitByte(0xBF); emitOperandHelper(dst, src); } - public final void movsxw(Register dst, Register src) { // movsxw + public final void movsxw(Register dst, Register src) { int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); emitByte(0xBF); emitByte(0xC0 | encode); } - public final void movsxw(Register dst, Address src) { // movsxw - prefix(src, dst); - emitByte(0x0F); - emitByte(0xBF); - emitOperandHelper(dst, src); - } - - public final void movzxd(Register dst, Register src) { // movzxd - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x63); - emitByte(0xC0 | encode); - } - - public final void movzxd(Register dst, Address src) { // movzxd - prefix(src, dst); - emitByte(0x63); - emitOperandHelper(dst, src); - } - - public final void movw(Address dst, int imm16) { + public final void movw(AMD64Address dst, int imm16) { emitByte(0x66); // switch to 16-bit mode prefix(dst); emitByte(0xC7); @@ -1226,55 +1058,21 @@ emitShort(imm16); } - public final void movw(Register dst, Address src) { - emitByte(0x66); - prefix(src, dst); - emitByte(0x8B); - emitOperandHelper(dst, src); - } - - public final void movw(Address dst, Register src) { + public final void movw(AMD64Address dst, Register src) { emitByte(0x66); prefix(dst, src); emitByte(0x89); emitOperandHelper(src, dst); } - public final void movzxb(Register dst, Address src) { // movzxb - prefix(src, dst); - emitByte(0x0F); - emitByte(0xB6); - emitOperandHelper(dst, src); - } - - public final void movzxb(Register dst, Register src) { // movzxb - int encode = prefixAndEncode(dst.encoding, src.encoding, true); - emitByte(0x0F); - emitByte(0xB6); - emitByte(0xC0 | encode); - } - - public final void movzxl(Register dst, Address src) { // movzxw + public final void movzxl(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x0F); emitByte(0xB7); emitOperandHelper(dst, src); } - public final void movzxl(Register dst, Register src) { // movzxw - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xB7); - emitByte(0xC0 | encode); - } - - public final void mull(Address src) { - prefix(src); - emitByte(0xF7); - emitOperandHelper(rsp, src); - } - - public final void mulsd(Register dst, Address src) { + public final void mulsd(Register dst, AMD64Address src) { assert dst.isFpu(); emitByte(0xF2); prefix(src, dst); @@ -1294,7 +1092,7 @@ emitByte(0xC0 | encode); } - public final void mulss(Register dst, Address src) { + public final void mulss(Register dst, AMD64Address src) { assert dst.isFpu(); emitByte(0xF3); @@ -1530,25 +1328,12 @@ } } - public final void notl(Register dst) { - int encode = prefixAndEncode(dst.encoding); - emitByte(0xF7); - emitByte(0xD0 | encode); - } - - public final void orl(Address dst, int imm32) { - prefix(dst); - emitByte(0x81); - emitOperandHelper(rcx, dst); - emitInt(imm32); - } - public final void orl(Register dst, int imm32) { prefix(dst); emitArith(0x81, 0xC8, dst, imm32); } - public final void orl(Register dst, Address src) { + public final void orl(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x0B); emitOperandHelper(dst, src); @@ -1559,7 +1344,7 @@ emitArith(0x0B, 0xC0, dst, src); } - public final void popcntl(Register dst, Address src) { + public final void popcntl(Register dst, AMD64Address src) { emitByte(0xF3); prefix(src, dst); emitByte(0x0F); @@ -1575,7 +1360,7 @@ emitByte(0xC0 | encode); } - public final void popcntq(Register dst, Address src) { + public final void popcntq(Register dst, AMD64Address src) { emitByte(0xF3); prefixq(src, dst); emitByte(0x0F); @@ -1591,223 +1376,16 @@ emitByte(0xC0 | encode); } - // generic public final void pop(Register dst) { int encode = prefixAndEncode(dst.encoding); emitByte(0x58 | encode); } - public final void prefetchPrefix(Address src) { - prefix(src); - emitByte(0x0F); - } - - public final void prefetchnta(Address src) { - prefetchPrefix(src); - emitByte(0x18); - emitOperandHelper(rax, src); // 0, src - } - - public final void prefetchr(Address src) { - prefetchPrefix(src); - emitByte(0x0D); - emitOperandHelper(rax, src); // 0, src - } - - public final void prefetcht0(Address src) { - prefetchPrefix(src); - emitByte(0x18); - emitOperandHelper(rcx, src); // 1, src - - } - - public final void prefetcht1(Address src) { - prefetchPrefix(src); - emitByte(0x18); - emitOperandHelper(rdx, src); // 2, src - } - - public final void prefetcht2(Address src) { - prefetchPrefix(src); - emitByte(0x18); - emitOperandHelper(rbx, src); // 3, src - } - - public final void prefetchw(Address src) { - prefetchPrefix(src); - emitByte(0x0D); - emitOperandHelper(rcx, src); // 1, src - } - - public final void pshufd(Register dst, Register src, int mode) { - assert dst.isFpu(); - assert src.isFpu(); - assert isUByte(mode) : "invalid value"; - - emitByte(0x66); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x70); - emitByte(0xC0 | encode); - emitByte(mode & 0xFF); - } - - public final void pshufd(Register dst, Address src, int mode) { - assert dst.isFpu(); - assert isUByte(mode) : "invalid value"; - - emitByte(0x66); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x70); - emitOperandHelper(dst, src); - emitByte(mode & 0xFF); - - } - - public final void pshuflw(Register dst, Register src, int mode) { - assert dst.isFpu(); - assert src.isFpu(); - assert isUByte(mode) : "invalid value"; - - emitByte(0xF2); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x70); - emitByte(0xC0 | encode); - emitByte(mode & 0xFF); - } - - public final void pshuflw(Register dst, Address src, int mode) { - assert dst.isFpu(); - assert isUByte(mode) : "invalid value"; - - emitByte(0xF2); - prefix(src, dst); // QQ new - emitByte(0x0F); - emitByte(0x70); - emitOperandHelper(dst, src); - emitByte(mode & 0xFF); - } - - public final void psrlq(Register dst, int shift) { - assert dst.isFpu(); - // HMM Table D-1 says sse2 or mmx - - int encode = prefixqAndEncode(xmm2.encoding, dst.encoding); - emitByte(0x66); - emitByte(0x0F); - emitByte(0x73); - emitByte(0xC0 | encode); - emitByte(shift); - } - - public final void punpcklbw(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); - emitByte(0x66); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0x60); - emitByte(0xC0 | encode); - } - - public final void push(int imm32) { - // in 64bits we push 64bits onto the stack but only - // take a 32bit immediate - emitByte(0x68); - emitInt(imm32); - } - public final void push(Register src) { int encode = prefixAndEncode(src.encoding); emitByte(0x50 | encode); } - public final void pushf() { - emitByte(0x9C); - } - - public final void pxor(Register dst, Address src) { - assert dst.isFpu(); - - emitByte(0x66); - prefix(src, dst); - emitByte(0x0F); - emitByte(0xEF); - emitOperandHelper(dst, src); - } - - public final void pxor(Register dst, Register src) { - assert dst.isFpu(); - assert src.isFpu(); - - emitByte(0x66); - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xEF); - emitByte(0xC0 | encode); - - } - - public final void rcll(Register dst, int imm8) { - assert isShiftCount(imm8) : "illegal shift count"; - int encode = prefixAndEncode(dst.encoding); - if (imm8 == 1) { - emitByte(0xD1); - emitByte(0xD0 | encode); - } else { - emitByte(0xC1); - emitByte(0xD0 | encode); - emitByte(imm8); - } - } - - public final void pause() { - emitByte(0xF3); - emitByte(0x90); - } - - // Copies data from [X86.rsi] to [X86.rdi] using X86.rcx heap words. - public final void repeatMoveWords() { - emitByte(0xF3); - emitByte(Prefix.REXW); - emitByte(0xA5); - } - - // Copies data from [X86.rsi] to [X86.rdi] using X86.rcx bytes. - public final void repeatMoveBytes() { - emitByte(0xF3); - emitByte(Prefix.REXW); - emitByte(0xA4); - } - - // sets X86.rcx pointer sized words with X86.rax, value at [edi] - // generic - public final void repSet() { // repSet - emitByte(0xF3); - // STOSQ - emitByte(Prefix.REXW); - emitByte(0xAB); - } - - // scans X86.rcx pointer sized words at [edi] for occurance of X86.rax, - // generic - public final void repneScan() { // repneScan - emitByte(0xF2); - // SCASQ - emitByte(Prefix.REXW); - emitByte(0xAF); - } - - // scans X86.rcx 4 byte words at [edi] for occurance of X86.rax, - // generic - public final void repneScanl() { // repneScan - emitByte(0xF2); - // SCASL - emitByte(0xAF); - } - public final void ret(int imm16) { if (imm16 == 0) { emitByte(0xC3); @@ -1836,35 +1414,6 @@ emitByte(0xF8 | encode); } - public final void sbbl(Address dst, int imm32) { - prefix(dst); - emitArithOperand(0x81, rbx, dst, imm32); - } - - public final void sbbl(Register dst, int imm32) { - prefix(dst); - emitArith(0x81, 0xD8, dst, imm32); - } - - public final void sbbl(Register dst, Address src) { - prefix(src, dst); - emitByte(0x1B); - emitOperandHelper(dst, src); - } - - public final void sbbl(Register dst, Register src) { - prefixAndEncode(dst.encoding, src.encoding); - emitArith(0x1B, 0xC0, dst, src); - } - - public final void setb(ConditionFlag cc, Register dst) { - assert 0 <= cc.value && cc.value < 16 : "illegal cc"; - int encode = prefixAndEncode(dst.encoding, true); - emitByte(0x0F); - emitByte(0x90 | cc.value); - emitByte(0xC0 | encode); - } - public final void shll(Register dst, int imm8) { assert isShiftCount(imm8) : "illegal shift count"; int encode = prefixAndEncode(dst.encoding); @@ -1898,11 +1447,6 @@ emitByte(0xE8 | encode); } - // copies a single word from [esi] to [edi] - public final void smovl() { - emitByte(0xA5); - } - public final void sqrtsd(Register dst, Register src) { assert dst.isFpu(); assert src.isFpu(); @@ -1915,7 +1459,7 @@ emitByte(0xC0 | encode); } - public final void subl(Address dst, int imm32) { + public final void subl(AMD64Address dst, int imm32) { prefix(dst); if (isByte(imm32)) { emitByte(0x83); @@ -1933,13 +1477,7 @@ emitArith(0x81, 0xE8, dst, imm32); } - public final void subl(Address dst, Register src) { - prefix(dst, src); - emitByte(0x29); - emitOperandHelper(src, dst); - } - - public final void subl(Register dst, Address src) { + public final void subl(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x2B); emitOperandHelper(dst, src); @@ -1960,7 +1498,7 @@ emitByte(0xC0 | encode); } - public final void subsd(Register dst, Address src) { + public final void subsd(Register dst, AMD64Address src) { assert dst.isFpu(); emitByte(0xF2); @@ -1980,7 +1518,7 @@ emitByte(0xC0 | encode); } - public final void subss(Register dst, Address src) { + public final void subss(Register dst, AMD64Address src) { assert dst.isFpu(); emitByte(0xF3); @@ -1990,11 +1528,6 @@ emitOperandHelper(dst, src); } - public final void testb(Register dst, int imm8) { - prefixAndEncode(dst.encoding, true); - emitArithB(0xF6, 0xC0, dst, imm8); - } - public final void testl(Register dst, int imm32) { // not using emitArith because test // doesn't support sign-extension of @@ -2015,13 +1548,13 @@ emitArith(0x85, 0xC0, dst, src); } - public final void testl(Register dst, Address src) { + public final void testl(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x85); emitOperandHelper(dst, src); } - public final void ucomisd(Register dst, Address src) { + public final void ucomisd(Register dst, AMD64Address src) { assert dst.isFpu(); emitByte(0x66); ucomiss(dst, src); @@ -2034,7 +1567,7 @@ ucomiss(dst, src); } - public final void ucomiss(Register dst, Address src) { + public final void ucomiss(Register dst, AMD64Address src) { assert dst.isFpu(); prefix(src, dst); @@ -2052,33 +1585,12 @@ emitByte(0xC0 | encode); } - public final void xaddl(Address dst, Register src) { - assert src.isFpu(); - - prefix(dst, src); - emitByte(0x0F); - emitByte(0xC1); - emitOperandHelper(src, dst); - } - - public final void xchgl(Register dst, Address src) { // xchg - prefix(src, dst); - emitByte(0x87); - emitOperandHelper(dst, src); - } - - public final void xchgl(Register dst, Register src) { - int encode = prefixAndEncode(dst.encoding, src.encoding); - emitByte(0x87); - emitByte(0xc0 | encode); - } - public final void xorl(Register dst, int imm32) { prefix(dst); emitArith(0x81, 0xF0, dst, imm32); } - public final void xorl(Register dst, Address src) { + public final void xorl(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x33); emitOperandHelper(dst, src); @@ -2094,7 +1606,7 @@ andps(dst, src); } - public final void andpd(Register dst, Address src) { + public final void andpd(Register dst, AMD64Address src) { emitByte(0x66); andps(dst, src); } @@ -2107,7 +1619,7 @@ emitByte(0xC0 | encode); } - public final void andps(Register dst, Address src) { + public final void andps(Register dst, AMD64Address src) { assert dst.isFpu(); prefix(src, dst); emitByte(0x0F); @@ -2120,7 +1632,7 @@ orps(dst, src); } - public final void orpd(Register dst, Address src) { + public final void orpd(Register dst, AMD64Address src) { emitByte(0x66); orps(dst, src); } @@ -2133,7 +1645,7 @@ emitByte(0xC0 | encode); } - public final void orps(Register dst, Address src) { + public final void orps(Register dst, AMD64Address src) { assert dst.isFpu(); prefix(src, dst); emitByte(0x0F); @@ -2146,7 +1658,7 @@ xorps(dst, src); } - public final void xorpd(Register dst, Address src) { + public final void xorpd(Register dst, AMD64Address src) { emitByte(0x66); xorps(dst, src); } @@ -2159,7 +1671,7 @@ emitByte(0xC0 | encode); } - public final void xorps(Register dst, Address src) { + public final void xorps(Register dst, AMD64Address src) { assert dst.isFpu(); prefix(src, dst); emitByte(0x0F); @@ -2167,29 +1679,25 @@ emitOperandHelper(dst, src); } - // 32bit only pieces of the assembler - - public final void decl(Register dst) { - // Don't use it directly. Use Macrodecrementl() instead. + protected final void decl(Register dst) { // Use two-byte form (one-byte form is a REX prefix in 64-bit mode) int encode = prefixAndEncode(dst.encoding); emitByte(0xFF); emitByte(0xC8 | encode); } - public final void incl(Register dst) { - // Don't use it directly. Use Macroincrementl() instead. + protected final void incl(Register dst) { // Use two-byte form (one-byte from is a REX prefix in 64-bit mode) int encode = prefixAndEncode(dst.encoding); emitByte(0xFF); emitByte(0xC0 | encode); } - int prefixAndEncode(int regEnc) { + private int prefixAndEncode(int regEnc) { return prefixAndEncode(regEnc, false); } - int prefixAndEncode(int regEnc, boolean byteinst) { + private int prefixAndEncode(int regEnc, boolean byteinst) { if (regEnc >= 8) { emitByte(Prefix.REXB); return regEnc - 8; @@ -2199,7 +1707,7 @@ return regEnc; } - int prefixqAndEncode(int regEnc) { + private int prefixqAndEncode(int regEnc) { if (regEnc < 8) { emitByte(Prefix.REXW); return regEnc; @@ -2209,11 +1717,11 @@ } } - int prefixAndEncode(int dstEnc, int srcEnc) { + private int prefixAndEncode(int dstEnc, int srcEnc) { return prefixAndEncode(dstEnc, srcEnc, false); } - int prefixAndEncode(int dstEncoding, int srcEncoding, boolean byteinst) { + private int prefixAndEncode(int dstEncoding, int srcEncoding, boolean byteinst) { int srcEnc = srcEncoding; int dstEnc = dstEncoding; if (dstEnc < 8) { @@ -2275,7 +1783,7 @@ return isRegister(value) && asRegister(value).encoding >= MinEncodingNeedsRex; } - private void prefix(Address adr) { + private void prefix(AMD64Address adr) { if (needsRex(adr.getBase())) { if (needsRex(adr.getIndex())) { emitByte(Prefix.REXXB); @@ -2289,7 +1797,7 @@ } } - private void prefixq(Address adr) { + private void prefixq(AMD64Address adr) { if (needsRex(adr.getBase())) { if (needsRex(adr.getIndex())) { emitByte(Prefix.REXWXB); @@ -2305,7 +1813,7 @@ } } - private void prefix(Address adr, Register reg) { + private void prefix(AMD64Address adr, Register reg) { if (reg.encoding < 8) { if (needsRex(adr.getBase())) { if (needsRex(adr.getIndex())) { @@ -2337,7 +1845,7 @@ } } - private void prefixq(Address adr, Register src) { + private void prefixq(AMD64Address adr, Register src) { if (src.encoding < 8) { if (needsRex(adr.getBase())) { if (needsRex(adr.getIndex())) { @@ -2369,23 +1877,12 @@ } } - public final void addq(Address dst, int imm32) { - prefixq(dst); - emitArithOperand(0x81, rax, dst, imm32); - } - - public final void addq(Address dst, Register src) { - prefixq(dst, src); - emitByte(0x01); - emitOperandHelper(src, dst); - } - public final void addq(Register dst, int imm32) { prefixqAndEncode(dst.encoding); emitArith(0x81, 0xC0, dst, imm32); } - public final void addq(Register dst, Address src) { + public final void addq(Register dst, AMD64Address src) { prefixq(src, dst); emitByte(0x03); emitOperandHelper(dst, src); @@ -2401,7 +1898,7 @@ emitArith(0x81, 0xE0, dst, imm32); } - public final void andq(Register dst, Address src) { + public final void andq(Register dst, AMD64Address src) { prefixq(src, dst); emitByte(0x23); emitOperandHelper(dst, src); @@ -2426,47 +1923,34 @@ public final void cmovq(ConditionFlag cc, Register dst, Register src) { int encode = prefixqAndEncode(dst.encoding, src.encoding); emitByte(0x0F); - emitByte(0x40 | cc.value); + emitByte(0x40 | cc.getValue()); emitByte(0xC0 | encode); } - public final void cmovq(ConditionFlag cc, Register dst, Address src) { + public final void cmovq(ConditionFlag cc, Register dst, AMD64Address src) { prefixq(src, dst); emitByte(0x0F); - emitByte(0x40 | cc.value); + emitByte(0x40 | cc.getValue()); emitOperandHelper(dst, src); } - public final void cmpq(Address dst, int imm32) { - prefixq(dst); - emitByte(0x81); - emitOperandHelper(rdi, dst); - emitInt(imm32); - } - public final void cmpq(Register dst, int imm32) { prefixqAndEncode(dst.encoding); emitArith(0x81, 0xF8, dst, imm32); } - public final void cmpq(Address dst, Register src) { - prefixq(dst, src); - emitByte(0x3B); - emitOperandHelper(src, dst); - } - public final void cmpq(Register dst, Register src) { prefixqAndEncode(dst.encoding, src.encoding); emitArith(0x3B, 0xC0, dst, src); } - public final void cmpq(Register dst, Address src) { + public final void cmpq(Register dst, AMD64Address src) { prefixq(src, dst); emitByte(0x3B); emitOperandHelper(dst, src); } - public final void cmpxchgq(Register reg, Address adr) { + public final void cmpxchgq(Register reg, AMD64Address adr) { prefixq(adr, reg); emitByte(0x0F); emitByte(0xB1); @@ -2509,16 +1993,14 @@ emitByte(0xC0 | encode); } - public final void decq(Register dst) { - // Don't use it directly. Use Macrodecrementq() instead. + protected final void decq(Register dst) { // Use two-byte form (one-byte from is a REX prefix in 64-bit mode) int encode = prefixqAndEncode(dst.encoding); emitByte(0xFF); emitByte(0xC8 | encode); } - public final void decq(Address dst) { - // Don't use it directly. Use Macrodecrementq() instead. + protected final void decq(AMD64Address dst) { prefixq(dst); emitByte(0xFF); emitOperandHelper(rcx, dst); @@ -2564,13 +2046,6 @@ emitByte(0xC0 | encode); } - public final void incq(Address dst) { - // Don't use it directly. Use Macroincrementq() instead. - prefixq(dst); - emitByte(0xFF); - emitOperandHelper(rax, dst); - } - public final void movq(Register dst, long imm64) { int encode = prefixqAndEncode(dst.encoding); emitByte(0xB8 | encode); @@ -2600,38 +2075,14 @@ } } - public final void movsbq(Register dst, Address src) { - prefixq(src, dst); - emitByte(0x0F); - emitByte(0xBE); - emitOperandHelper(dst, src); - } - - public final void movsbq(Register dst, Register src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xBE); - emitByte(0xC0 | encode); - } - - public final void movslq(Register dst, int imm32) { - int encode = prefixqAndEncode(dst.encoding); - emitByte(0xC7 | encode); - emitInt(imm32); - // dbx shows movslq(X86.rcx, 3) as movq $0x0000000049000000,(%X86.rbx) - // and movslq(X86.r8, 3); as movl $0x0000000048000000,(%X86.rbx) - // as a result we shouldn't use until tested at runtime... - throw new InternalError("untested"); - } - - public final void movslq(Address dst, int imm32) { + public final void movslq(AMD64Address dst, int imm32) { prefixq(dst); emitByte(0xC7); emitOperandHelper(rax, dst); emitInt(imm32); } - public final void movslq(Register dst, Address src) { + public final void movslq(Register dst, AMD64Address src) { prefixq(src, dst); emitByte(0x63); emitOperandHelper(dst, src); @@ -2643,73 +2094,18 @@ emitByte(0xC0 | encode); } - public final void movswq(Register dst, Address src) { - prefixq(src, dst); - emitByte(0x0F); - emitByte(0xBF); - emitOperandHelper(dst, src); - } - - public final void movswq(Register dst, Register src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xBF); - emitByte(0xC0 | encode); - } - - public final void movzbq(Register dst, Address src) { - prefixq(src, dst); - emitByte(0x0F); - emitByte(0xB6); - emitOperandHelper(dst, src); - } - - public final void movzbq(Register dst, Register src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xB6); - emitByte(0xC0 | encode); - } - - public final void movzwq(Register dst, Address src) { - prefixq(src, dst); - emitByte(0x0F); - emitByte(0xB7); - emitOperandHelper(dst, src); - } - - public final void movzwq(Register dst, Register src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x0F); - emitByte(0xB7); - emitByte(0xC0 | encode); - } - public final void negq(Register dst) { int encode = prefixqAndEncode(dst.encoding); emitByte(0xF7); emitByte(0xD8 | encode); } - public final void notq(Register dst) { - int encode = prefixqAndEncode(dst.encoding); - emitByte(0xF7); - emitByte(0xD0 | encode); - } - - public final void orq(Address dst, int imm32) { - prefixq(dst); - emitByte(0x81); - emitOperandHelper(rcx, dst); - emitInt(imm32); - } - public final void orq(Register dst, int imm32) { prefixqAndEncode(dst.encoding); emitArith(0x81, 0xC8, dst, imm32); } - public final void orq(Register dst, Address src) { + public final void orq(Register dst, AMD64Address src) { prefixq(src, dst); emitByte(0x0B); emitOperandHelper(dst, src); @@ -2720,31 +2116,6 @@ emitArith(0x0B, 0xC0, dst, src); } - public final void popq(Address dst) { - prefixq(dst); - emitByte(0x8F); - emitOperandHelper(rax, dst); - } - - public final void pushq(Address src) { - prefixq(src); - emitByte(0xFF); - emitOperandHelper(rsi, src); - } - - public final void rclq(Register dst, int imm8) { - assert isShiftCount(imm8 >> 1) : "illegal shift count"; - int encode = prefixqAndEncode(dst.encoding); - if (imm8 == 1) { - emitByte(0xD1); - emitByte(0xD0 | encode); - } else { - emitByte(0xC1); - emitByte(0xD0 | encode); - emitByte(imm8); - } - } - public final void sarq(Register dst, int imm8) { assert isShiftCount(imm8 >> 1) : "illegal shift count"; int encode = prefixqAndEncode(dst.encoding); @@ -2797,41 +2168,12 @@ emitByte(0xE8 | encode); } - public final void sqrtsd(Register dst, Address src) { - assert dst.isFpu(); - - emitByte(0xF2); - prefix(src, dst); - emitByte(0x0F); - emitByte(0x51); - emitOperandHelper(dst, src); - } - - public final void subq(Address dst, int imm32) { - prefixq(dst); - if (isByte(imm32)) { - emitByte(0x83); - emitOperandHelper(rbp, dst); - emitByte(imm32 & 0xFF); - } else { - emitByte(0x81); - emitOperandHelper(rbp, dst); - emitInt(imm32); - } - } - public final void subq(Register dst, int imm32) { prefixqAndEncode(dst.encoding); emitArith(0x81, 0xE8, dst, imm32); } - public final void subq(Address dst, Register src) { - prefixq(dst, src); - emitByte(0x29); - emitOperandHelper(src, dst); - } - - public final void subq(Register dst, Address src) { + public final void subq(Register dst, AMD64Address src) { prefixq(src, dst); emitByte(0x2B); emitOperandHelper(dst, src); @@ -2863,31 +2205,12 @@ emitArith(0x85, 0xC0, dst, src); } - public final void testq(Register dst, Address src) { + public final void testq(Register dst, AMD64Address src) { prefixq(src, dst); emitByte(0x85); emitOperandHelper(dst, src); } - public final void xaddq(Address dst, Register src) { - prefixq(dst, src); - emitByte(0x0F); - emitByte(0xC1); - emitOperandHelper(src, dst); - } - - public final void xchgq(Register dst, Address src) { - prefixq(src, dst); - emitByte(0x87); - emitOperandHelper(dst, src); - } - - public final void xchgq(Register dst, Register src) { - int encode = prefixqAndEncode(dst.encoding, src.encoding); - emitByte(0x87); - emitByte(0xc0 | encode); - } - public final void xorq(Register dst, int imm32) { prefixqAndEncode(dst.encoding); emitArith(0x81, 0xF0, dst, imm32); @@ -2898,12 +2221,10 @@ emitArith(0x33, 0xC0, dst, src); } - public final void xorq(Register dst, Address src) { - + public final void xorq(Register dst, AMD64Address src) { prefixq(src, dst); emitByte(0x33); emitOperandHelper(dst, src); - } public final void membar(int barriers) { @@ -2919,7 +2240,7 @@ // the code where this idiom is used, in particular the // orderAccess code. lock(); - addl(new Address(Word, RSP, 0), 0); // Assert the lock# signal here + addl(new AMD64Address(Word, RSP, 0), 0); // Assert the lock# signal here } } } @@ -2960,7 +2281,7 @@ } public void nullCheck(Register r) { - testl(AMD64.rax, new Address(Word, r.asValue(Word), 0)); + testl(AMD64.rax, new AMD64Address(Word, r.asValue(Word), 0)); } @Override @@ -2970,26 +2291,6 @@ } } - public void pushfq() { - emitByte(0x9c); - } - - public void popfq() { - emitByte(0x9D); - } - - /** - * Makes sure that a subsequent {@linkplain #call} does not fail the alignment check. - */ - public final void alignForPatchableDirectCall() { - int dispStart = codeBuffer.position() + 1; - int mask = target.wordSize - 1; - if ((dispStart & ~mask) != ((dispStart + 3) & ~mask)) { - nop(target.wordSize - (dispStart & mask)); - assert ((codeBuffer.position() + 1) & mask) == 0; - } - } - /** * Emits a direct call instruction. Note that the actual call target is not specified, because * all calls need patching anyway. Therefore, 0 is emitted as the call target, and the user is @@ -3006,74 +2307,67 @@ emitByte(0xD0 | encode); } - public void int3() { + public final void int3() { emitByte(0xCC); } - public void enter(short imm16, byte imm8) { - emitByte(0xC8); - // appended: - emitByte(imm16 & 0xff); - emitByte((imm16 >> 8) & 0xff); - emitByte(imm8); - } - private void emitx87(int b1, int b2, int i) { assert 0 <= i && i < 8 : "illegal stack offset"; emitByte(b1); emitByte(b2 + i); } - public void fld(Address src) { + public final void fld(AMD64Address src) { emitByte(0xDD); emitOperandHelper(rax, src); } - public void fld(int i) { - emitx87(0xD9, 0xC0, i); - } - - public void fldln2() { + public final void fldln2() { emitByte(0xD9); emitByte(0xED); } - public void fldlg2() { + public final void fldlg2() { emitByte(0xD9); emitByte(0xEC); } - public void fyl2x() { + public final void fyl2x() { emitByte(0xD9); emitByte(0xF1); } - public void fstp(Address src) { + public final void fstp(AMD64Address src) { emitByte(0xDD); emitOperandHelper(rbx, src); } - public void fsin() { + public final void fsin() { emitByte(0xD9); emitByte(0xFE); } - public void fcos() { + public final void fcos() { emitByte(0xD9); emitByte(0xFF); } - public void fptan() { + public final void fptan() { emitByte(0xD9); emitByte(0xF2); } - public void fstp(int i) { + public final void fstp(int i) { emitx87(0xDD, 0xD8, i); } @Override - public void bangStack(int disp) { - movq(new Address(target.wordKind, AMD64.RSP, -disp), AMD64.rax); + public AMD64Address makeAddress(Kind kind, Value base, int displacement) { + return new AMD64Address(kind, base, displacement); + } + + @Override + public AMD64Address getPlaceholder() { + return Placeholder; } }
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Mon Mar 04 10:00:49 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -27,7 +27,6 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; /** * This class implements commonly used X86 code patterns. @@ -38,25 +37,11 @@ super(target, registerConfig); } - public void pushptr(Address src) { - pushq(src); - } - - public void popptr(Address src) { - popq(src); - } - - public void xorptr(Register dst, Register src) { + public final void xorptr(Register dst, Register src) { xorq(dst, src); } - public void xorptr(Register dst, Address src) { - xorq(dst, src); - } - - // 64 bit versions - - public void decrementq(Register reg, int value) { + public final void decrementq(Register reg, int value) { if (value == Integer.MIN_VALUE) { subq(reg, value); return; @@ -94,83 +79,19 @@ } } - // These are mostly for initializing null - public void movptr(Address dst, int src) { + public final void movptr(AMD64Address dst, int src) { movslq(dst, src); } - public final void cmp32(Register src1, int imm) { - cmpl(src1, imm); - } - - public final void cmp32(Register src1, Address src2) { - cmpl(src1, src2); - } - - public void cmpsd2int(Register opr1, Register opr2, Register dst, boolean unorderedIsLess) { - assert opr1.isFpu() && opr2.isFpu(); - ucomisd(opr1, opr2); - - Label l = new Label(); - if (unorderedIsLess) { - movl(dst, -1); - jcc(AMD64Assembler.ConditionFlag.parity, l); - jcc(AMD64Assembler.ConditionFlag.below, l); - movl(dst, 0); - jcc(AMD64Assembler.ConditionFlag.equal, l); - incrementl(dst, 1); - } else { // unordered is greater - movl(dst, 1); - jcc(AMD64Assembler.ConditionFlag.parity, l); - jcc(AMD64Assembler.ConditionFlag.above, l); - movl(dst, 0); - jcc(AMD64Assembler.ConditionFlag.equal, l); - decrementl(dst, 1); - } - bind(l); - } - - public void cmpss2int(Register opr1, Register opr2, Register dst, boolean unorderedIsLess) { - assert opr1.isFpu(); - assert opr2.isFpu(); - ucomiss(opr1, opr2); - - Label l = new Label(); - if (unorderedIsLess) { - movl(dst, -1); - jcc(AMD64Assembler.ConditionFlag.parity, l); - jcc(AMD64Assembler.ConditionFlag.below, l); - movl(dst, 0); - jcc(AMD64Assembler.ConditionFlag.equal, l); - incrementl(dst, 1); - } else { // unordered is greater - movl(dst, 1); - jcc(AMD64Assembler.ConditionFlag.parity, l); - jcc(AMD64Assembler.ConditionFlag.above, l); - movl(dst, 0); - jcc(AMD64Assembler.ConditionFlag.equal, l); - decrementl(dst, 1); - } - bind(l); - } - - public void cmpptr(Register src1, Register src2) { + public final void cmpptr(Register src1, Register src2) { cmpq(src1, src2); } - public void cmpptr(Register src1, Address src2) { + public final void cmpptr(Register src1, AMD64Address src2) { cmpq(src1, src2); } - public void cmpptr(Register src1, int src2) { - cmpq(src1, src2); - } - - public void cmpptr(Address src1, int src2) { - cmpq(src1, src2); - } - - public void decrementl(Register reg, int value) { + public final void decrementl(Register reg, int value) { if (value == Integer.MIN_VALUE) { subl(reg, value); return; @@ -189,7 +110,7 @@ } } - public void decrementl(Address dst, int value) { + public final void decrementl(AMD64Address dst, int value) { if (value == Integer.MIN_VALUE) { subl(dst, value); return; @@ -208,7 +129,7 @@ } } - public void incrementl(Register reg, int value) { + public final void incrementl(Register reg, int value) { if (value == Integer.MIN_VALUE) { addl(reg, value); return; @@ -227,7 +148,7 @@ } } - public void incrementl(Address dst, int value) { + public final void incrementl(AMD64Address dst, int value) { if (value == Integer.MIN_VALUE) { addl(dst, value); return; @@ -246,21 +167,20 @@ } } - public void signExtendByte(Register reg) { + public final void signExtendByte(Register reg) { if (reg.isByte()) { - movsxb(reg, reg); // movsxb + movsxb(reg, reg); } else { shll(reg, 24); sarl(reg, 24); } } - public void signExtendShort(Register reg) { - movsxw(reg, reg); // movsxw + public final void signExtendShort(Register reg) { + movsxw(reg, reg); } - // Support optimal SSE move instructions. - public void movflt(Register dst, Register src) { + public final void movflt(Register dst, Register src) { assert dst.isFpu() && src.isFpu(); if (UseXmmRegToRegMoveAll) { movaps(dst, src); @@ -269,17 +189,17 @@ } } - public void movflt(Register dst, Address src) { + public final void movflt(Register dst, AMD64Address src) { assert dst.isFpu(); movss(dst, src); } - public void movflt(Address dst, Register src) { + public final void movflt(AMD64Address dst, Register src) { assert src.isFpu(); movss(dst, src); } - public void movdbl(Register dst, Register src) { + public final void movdbl(Register dst, Register src) { assert dst.isFpu() && src.isFpu(); if (UseXmmRegToRegMoveAll) { movapd(dst, src); @@ -288,7 +208,7 @@ } } - public void movdbl(Register dst, Address src) { + public final void movdbl(Register dst, AMD64Address src) { assert dst.isFpu(); if (UseXmmLoadAndClearUpper) { movsd(dst, src); @@ -297,75 +217,65 @@ } } - public void movdbl(Address dst, Register src) { - assert src.isFpu(); - movsd(dst, src); - } - /** * Non-atomic write of a 64-bit constant to memory. Do not use if the address might be a * volatile field! */ - public void movlong(Address dst, long src) { - Address high = new Address(dst.getKind(), dst.getBase(), dst.getIndex(), dst.getScale(), dst.getDisplacement() + 4); + public final void movlong(AMD64Address dst, long src) { + AMD64Address high = new AMD64Address(dst.getKind(), dst.getBase(), dst.getIndex(), dst.getScale(), dst.getDisplacement() + 4); movl(dst, (int) (src & 0xFFFFFFFF)); movl(high, (int) (src >> 32)); } - public void xchgptr(Register src1, Register src2) { - xchgq(src1, src2); - } + public final void flog(Register dest, Register value, boolean base10) { + assert dest.isFpu() && value.isFpu(); - public void flog(Register dest, Register value, boolean base10) { - assert value.spillSlotSize == dest.spillSlotSize; - - Address tmp = new Address(Kind.Double, AMD64.RSP); + AMD64Address tmp = new AMD64Address(Kind.Double, AMD64.RSP); if (base10) { fldlg2(); } else { fldln2(); } - subq(AMD64.rsp, value.spillSlotSize); + subq(AMD64.rsp, 8); movsd(tmp, value); fld(tmp); fyl2x(); - fstp(tmp); - movsd(dest, tmp); - addq(AMD64.rsp, dest.spillSlotSize); + trigEpilogue(dest, tmp); } - public void fsin(Register dest, Register value) { - ftrig(dest, value, 's'); + public final void fsin(Register dest, Register value) { + AMD64Address tmp = trigPrologue(value); + fsin(); + trigEpilogue(dest, tmp); } - public void fcos(Register dest, Register value) { - ftrig(dest, value, 'c'); - } - - public void ftan(Register dest, Register value) { - ftrig(dest, value, 't'); + public final void fcos(Register dest, Register value) { + AMD64Address tmp = trigPrologue(value); + fcos(); + trigEpilogue(dest, tmp); } - private void ftrig(Register dest, Register value, char op) { - assert value.spillSlotSize == dest.spillSlotSize; + public final void ftan(Register dest, Register value) { + AMD64Address tmp = trigPrologue(value); + fptan(); + fstp(0); // ftan pushes 1.0 in addition to the actual result, pop + trigEpilogue(dest, tmp); + } - Address tmp = new Address(Kind.Double, AMD64.RSP); - subq(AMD64.rsp, value.spillSlotSize); + private AMD64Address trigPrologue(Register value) { + assert value.isFpu(); + AMD64Address tmp = new AMD64Address(Kind.Double, AMD64.RSP); + subq(AMD64.rsp, 8); movsd(tmp, value); fld(tmp); - if (op == 's') { - fsin(); - } else if (op == 'c') { - fcos(); - } else if (op == 't') { - fptan(); - fstp(0); // ftan pushes 1.0 in addition to the actual result, pop - } else { - throw new InternalError("should not reach here"); - } + return tmp; + } + + private void trigEpilogue(Register dest, AMD64Address tmp) { + assert dest.isFpu(); fstp(tmp); movsd(dest, tmp); - addq(AMD64.rsp, dest.spillSlotSize); + addq(AMD64.rsp, 8); } /** @@ -375,19 +285,19 @@ * @param csl the description of the CSA * @param frameToCSA offset from the frame pointer to the CSA */ - public void save(CalleeSaveLayout csl, int frameToCSA) { + public final void save(CalleeSaveLayout csl, int frameToCSA) { RegisterValue frame = frameRegister.asValue(); for (Register r : csl.registers) { int offset = csl.offsetOf(r); - movq(new Address(target.wordKind, frame, frameToCSA + offset), r); + movq(new AMD64Address(target.wordKind, frame, frameToCSA + offset), r); } } - public void restore(CalleeSaveLayout csl, int frameToCSA) { + public final void restore(CalleeSaveLayout csl, int frameToCSA) { RegisterValue frame = frameRegister.asValue(); for (Register r : csl.registers) { int offset = csl.offsetOf(r); - movq(r, new Address(target.wordKind, frame, frameToCSA + offset)); + movq(r, new AMD64Address(target.wordKind, frame, frameToCSA + offset)); } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/AbstractPTXAssembler.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,63 @@ +/* + * 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.ptx; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.asm.*; + +/** + * The platform-dependent base class for the PTX assembler. + */ +public abstract class AbstractPTXAssembler extends AbstractAssembler { + + public AbstractPTXAssembler(TargetDescription target) { + super(target); + } + + public static final String UNBOUND_TARGET = "L" + Integer.MAX_VALUE; + + @Override + public final void bind(Label l) { + super.bind(l); + emitString0("L" + l.toString() + ":\n"); + } + + @Override + public void align(int modulus) { + // TODO Auto-generated method stub + } + + @Override + public void jmp(Label l) { + // TODO Auto-generated method stub + } + + @Override + protected void patchJumpTarget(int branch, int jumpTarget) { + final int spaces = UNBOUND_TARGET.length(); + String targetString = String.format("L%-" + spaces + "s", jumpTarget + ";"); + int offset = "\tbra ".length(); // XXX we need a better way to figure this out + codeBuffer.emitString(targetString, branch + offset); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAsmOptions.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,27 @@ +/* + * 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.ptx; + +public class PTXAsmOptions { + // Nothing for now +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,754 @@ +/* + * 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.ptx; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.ptx.*; + +public class PTXAssembler extends AbstractPTXAssembler { + + @SuppressWarnings("unused") + public PTXAssembler(TargetDescription target, RegisterConfig registerConfig) { + super(target); + } + + public final void at() { + emitString("@%p" + " " + ""); + } + + public final void add_s16(Register d, Register a, Register b) { + emitString("add.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void add_s32(Register d, Register a, Register b) { + emitString("add.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void add_s64(Register d, Register a, Register b) { + emitString("add.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void add_s16(Register d, Register a, short s16) { + emitString("add.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + ""); + } + + public final void add_s32(Register d, Register a, int s32) { + emitString("add.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + + public final void add_s64(Register d, Register a, long s64) { + emitString("add.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); + } + + public final void add_u16(Register d, Register a, Register b) { + emitString("add.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void add_u32(Register d, Register a, Register b) { + emitString("add.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void add_u64(Register d, Register a, Register b) { + emitString("add.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void add_u16(Register d, Register a, short u16) { + emitString("add.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + ""); + } + + public final void add_u32(Register d, Register a, int u32) { + emitString("add.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void add_u64(Register d, Register a, long u64) { + emitString("add.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + ""); + } + + public final void add_sat_s32(Register d, Register a, Register b) { + emitString("add.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void add_sat_s32(Register d, Register a, int s32) { + emitString("add.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + + public final void and_b16(Register d, Register a, Register b) { + emitString("and.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void and_b32(Register d, Register a, Register b) { + emitString("and.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void and_b64(Register d, Register a, Register b) { + emitString("and.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void and_b16(Register d, Register a, short b16) { + emitString("and.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + ""); + } + + public final void and_b32(Register d, Register a, int b32) { + emitString("and.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + ""); + } + + public final void and_b64(Register d, Register a, long b64) { + emitString("and.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + ""); + } + + public final void bra(String tgt) { + emitString("bra" + " " + tgt + ";" + ""); + } + + public final void bra_uni(String tgt) { + emitString("bra.uni" + " " + tgt + ";" + ""); + } + + public final void div_s16(Register d, Register a, Register b) { + emitString("div.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_s32(Register d, Register a, Register b) { + emitString("div.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_s64(Register d, Register a, Register b) { + emitString("div.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_s16(Register d, Register a, short s16) { + emitString("div.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + ""); + } + + public final void div_s32(Register d, Register a, int s32) { + emitString("div.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + + public final void div_s64(Register d, Register a, long s64) { + emitString("div.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); + } + + public final void div_u16(Register d, Register a, Register b) { + emitString("div.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_u32(Register d, Register a, Register b) { + emitString("div.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_u64(Register d, Register a, Register b) { + emitString("div.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_u16(Register d, Register a, short u16) { + emitString("div.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + ""); + } + + public final void div_u32(Register d, Register a, int u32) { + emitString("div.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void div_u64(Register d, Register a, long u64) { + emitString("div.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + ""); + } + + public final void exit() { + emitString("exit;" + " " + ""); + } + + public final void ld_global_b8(Register d, Register a, int immOff) { + emitString("ld.global.b8" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void ld_global_b16(Register d, Register a, long immOff) { + emitString("ld.global.b16" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void ld_global_b32(Register d, Register a, long immOff) { + emitString("ld.global.b32" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void ld_global_b64(Register d, Register a, long immOff) { + emitString("ld.global.b64" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void ld_global_u8(Register d, Register a, long immOff) { + emitString("ld.global.u8" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void ld_global_u16(Register d, Register a, long immOff) { + emitString("ld.global.u16" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void ld_global_u32(Register d, Register a, long immOff) { + emitString("ld.global.u32" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void ld_global_u64(Register d, Register a, long immOff) { + emitString("ld.global.u64" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void ld_global_s8(Register d, Register a, long immOff) { + emitString("ld.global.s8" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void ld_global_s16(Register d, Register a, long immOff) { + emitString("ld.global.s16" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void ld_global_s32(Register d, Register a, long immOff) { + emitString("ld.global.s32" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void ld_global_s64(Register d, Register a, long immOff) { + emitString("ld.global.s64" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void ld_global_f32(Register d, Register a, long immOff) { + emitString("ld.global.f32" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void ld_global_f64(Register d, Register a, long immOff) { + emitString("ld.global.f64" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); + } + + public final void mov_b16(Register d, Register a) { + emitString("mov.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void mov_b32(Register d, Register a) { + emitString("mov.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void mov_b64(Register d, Register a) { + emitString("mov.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void mov_u16(Register d, Register a) { + emitString("mov.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void mov_u32(Register d, Register a) { + emitString("mov.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void mov_u64(Register d, Register a) { + emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void mov_s16(Register d, Register a) { + emitString("mov.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void mov_s32(Register d, Register a) { + emitString("mov.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void mov_s64(Register d, Register a) { + emitString("mov.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void mov_f32(Register d, Register a) { + emitString("mov.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void mov_f64(Register d, Register a) { + emitString("mov.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void mov_b16(Register d, short b16) { + emitString("mov.b16" + " " + "%r" + d.encoding() + ", " + b16 + ";" + ""); + } + + public final void mov_b32(Register d, int b32) { + emitString("mov.b32" + " " + "%r" + d.encoding() + ", " + b32 + ";" + ""); + } + + public final void mov_b64(Register d, long b64) { + emitString("mov.b64" + " " + "%r" + d.encoding() + ", " + b64 + ";" + ""); + } + + public final void mov_u16(Register d, short u16) { + emitString("mov.u16" + " " + "%r" + d.encoding() + ", " + u16 + ";" + ""); + } + + public final void mov_u32(Register d, int u32) { + emitString("mov.u32" + " " + "%r" + d.encoding() + ", " + u32 + ";" + ""); + } + + public final void mov_u64(Register d, long u64) { + emitString("mov.u64" + " " + "%r" + d.encoding() + ", " + u64 + ";" + ""); + } + + public final void mov_s16(Register d, short s16) { + emitString("mov.s16" + " " + "%r" + d.encoding() + ", " + s16 + ";" + ""); + } + + public final void mov_s32(Register d, int s32) { + emitString("mov.s32" + " " + "%r" + d.encoding() + ", " + s32 + ";" + ""); + } + + public final void mov_s64(Register d, long s64) { + emitString("mov.s64" + " " + "%r" + d.encoding() + ", " + s64 + ";" + ""); + } + + public final void mov_f32(Register d, float f32) { + emitString("mov.f32" + " " + "%r" + d.encoding() + ", " + f32 + ";" + ""); + } + + public final void mov_f64(Register d, double f64) { + emitString("mov.f64" + " " + "%r" + d.encoding() + ", " + f64 + ";" + ""); + } + + public final void mul_s16(Register d, Register a, Register b) { + emitString("mul.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void mul_s32(Register d, Register a, Register b) { + emitString("mul.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void mul_s64(Register d, Register a, Register b) { + emitString("mul.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void mul_s16(Register d, Register a, short s16) { + emitString("mul.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + ""); + } + + public final void mul_s32(Register d, Register a, int s32) { + emitString("mul.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + + public final void mul_s64(Register d, Register a, long s64) { + emitString("mul.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); + } + + public final void mul_u16(Register d, Register a, Register b) { + emitString("mul.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void mul_u32(Register d, Register a, Register b) { + emitString("mul.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void mul_u64(Register d, Register a, Register b) { + emitString("mul.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void mul_u16(Register d, Register a, short u16) { + emitString("mul.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + ""); + } + + public final void mul_u32(Register d, Register a, int u32) { + emitString("mul.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void mul_u64(Register d, Register a, long u64) { + emitString("mul.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + ""); + } + + public final void neg_s16(Register d, Register a) { + emitString("neg.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void neg_s32(Register d, Register a) { + emitString("neg.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void neg_s64(Register d, Register a) { + emitString("neg.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void popc_b32(Register d, Register a) { + emitString("popc.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void popc_b64(Register d, Register a) { + emitString("popc.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void rem_s16(Register d, Register a, Register b) { + emitString("rem.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void rem_s32(Register d, Register a, Register b) { + emitString("rem.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void rem_s64(Register d, Register a, Register b) { + emitString("rem.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void rem_s16(Register d, Register a, short s16) { + emitString("rem.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + ""); + } + + public final void rem_s32(Register d, Register a, int s32) { + emitString("rem.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + + public final void rem_s64(Register d, Register a, long s64) { + emitString("rem.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); + } + + public final void rem_u16(Register d, Register a, Register b) { + emitString("rem.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void rem_u32(Register d, Register a, Register b) { + emitString("rem.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void rem_u64(Register d, Register a, Register b) { + emitString("rem.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void rem_u16(Register d, Register a, short u16) { + emitString("rem.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + ""); + } + + public final void rem_u32(Register d, Register a, int u32) { + emitString("rem.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void rem_u64(Register d, Register a, long u64) { + emitString("rem.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + ""); + } + + public final void ret() { + emitString("ret;" + " " + ""); + } + + public final void ret_uni() { + emitString("ret.uni;" + " " + ""); + } + + public final void setp_eq_s32(Register a, Register b) { + emitString("setp.eq.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ne_s32(Register a, Register b) { + emitString("setp.ne.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_lt_s32(Register a, Register b) { + emitString("setp.lt.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_le_s32(Register a, Register b) { + emitString("setp.le.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_gt_s32(Register a, Register b) { + emitString("setp.gt.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ge_s32(Register a, Register b) { + emitString("setp.ge.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_eq_s32(Register a, int s32) { + emitString("setp.eq.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + + public final void setp_ne_s32(Register a, int s32) { + emitString("setp.ne.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + + public final void setp_lt_s32(Register a, int s32) { + emitString("setp.lt.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + + public final void setp_le_s32(Register a, int s32) { + emitString("setp.le.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + + public final void setp_gt_s32(Register a, int s32) { + emitString("setp.gt.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + + public final void setp_ge_s32(Register a, int s32) { + emitString("setp.ge.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + + public final void setp_eq_s32(int s32, Register b) { + emitString("setp.eq.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ne_s32(int s32, Register b) { + emitString("setp.ne.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_lt_s32(int s32, Register b) { + emitString("setp.lt.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_le_s32(int s32, Register b) { + emitString("setp.le.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_gt_s32(int s32, Register b) { + emitString("setp.gt.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ge_s32(int s32, Register b) { + emitString("setp.ge.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_eq_u32(Register a, Register b) { + emitString("setp.eq.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ne_u32(Register a, Register b) { + emitString("setp.ne.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_lt_u32(Register a, Register b) { + emitString("setp.lt.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_le_u32(Register a, Register b) { + emitString("setp.le.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_gt_u32(Register a, Register b) { + emitString("setp.gt.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ge_u32(Register a, Register b) { + emitString("setp.ge.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_eq_u32(Register a, int u32) { + emitString("setp.eq.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void setp_ne_u32(Register a, int u32) { + emitString("setp.ne.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void setp_lt_u32(Register a, int u32) { + emitString("setp.lt.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void setp_le_u32(Register a, int u32) { + emitString("setp.le.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void setp_gt_u32(Register a, int u32) { + emitString("setp.gt.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void setp_ge_u32(Register a, int u32) { + emitString("setp.ge.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void setp_eq_u32(int u32, Register b) { + emitString("setp.eq.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ne_u32(int u32, Register b) { + emitString("setp.ne.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_lt_u32(int u32, Register b) { + emitString("setp.lt.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_le_u32(int u32, Register b) { + emitString("setp.le.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_gt_u32(int u32, Register b) { + emitString("setp.gt.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ge_u32(int u32, Register b) { + emitString("setp.ge.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void shr_s16(Register d, Register a, Register b) { + emitString("shr.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shr_s32(Register d, Register a, Register b) { + emitString("shr.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shr_s64(Register d, Register a, Register b) { + emitString("shr.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shr_s16(Register d, Register a, int u32) { + emitString("shr.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shr_s32(Register d, Register a, int u32) { + emitString("shr.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shr_s64(Register d, Register a, int u32) { + emitString("shr.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shr_u16(Register d, Register a, Register b) { + emitString("shr.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shr_u32(Register d, Register a, Register b) { + emitString("shr.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shr_u64(Register d, Register a, Register b) { + emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shr_u16(Register d, Register a, int u32) { + emitString("shr.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shr_u32(Register d, Register a, int u32) { + emitString("shr.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shr_u64(Register d, Register a, int u32) { + emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void st_global_b8(Register a, long immOff, Register b) { + emitString("st.global.b8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void st_global_b16(Register a, long immOff, Register b) { + emitString("st.global.b16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void st_global_b32(Register a, long immOff, Register b) { + emitString("st.global.b32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void st_global_b64(Register a, long immOff, Register b) { + emitString("st.global.b64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void st_global_u8(Register a, long immOff, Register b) { + emitString("st.global.u8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void st_global_u16(Register a, long immOff, Register b) { + emitString("st.global.u16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void st_global_u32(Register a, long immOff, Register b) { + emitString("st.global.u32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void st_global_u64(Register a, long immOff, Register b) { + emitString("st.global.u64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void st_global_s8(Register a, long immOff, Register b) { + emitString("st.global.s8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void st_global_s16(Register a, long immOff, Register b) { + emitString("st.global.s16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void st_global_s32(Register a, long immOff, Register b) { + emitString("st.global.s32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void st_global_s64(Register a, long immOff, Register b) { + emitString("st.global.s64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void st_global_f32(Register a, long immOff, Register b) { + emitString("st.global.f32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void st_global_f64(Register a, long immOff, Register b) { + emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); + } + + public final void sub_s16(Register d, Register a, Register b) { + emitString("sub.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void sub_s32(Register d, Register a, Register b) { + emitString("sub.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void sub_s64(Register d, Register a, Register b) { + emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void sub_s16(Register d, Register a, short s16) { + emitString("sub.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + ""); + } + + public final void sub_s32(Register d, Register a, int s32) { + emitString("sub.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + + public final void sub_s64(Register d, Register a, long s64) { + emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); + } + + public final void sub_s16(Register d, short s16, Register b) { + emitString("sub.s16" + " " + "%r" + d.encoding() + ", " + s16 + ", %r" + b.encoding() + ";" + ""); + } + + public final void sub_s32(Register d, int s32, Register b) { + emitString("sub.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void sub_s64(Register d, long s64, Register b) { + emitString("sub.s64" + " " + "%r" + d.encoding() + ", " + s64 + ", %r" + b.encoding() + ";" + ""); + } + + public final void sub_sat_s32(Register d, Register a, Register b) { + emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void sub_sat_s32(Register d, Register a, int s32) { + emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + + public final void sub_sat_s32(Register d, int s32, Register b) { + emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + ""); + } + + @Override + public PTXAddress makeAddress(Kind kind, Value base, int displacement) { + return new PTXAddress(kind, base, displacement); + } + + @Override + public PTXAddress getPlaceholder() { + // TODO Auto-generated method stub + return null; + } +}
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Mon Mar 04 10:00:49 2013 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.asm.sparc; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.sparc.*; @@ -54,7 +55,14 @@ } @Override - public void bangStack(int disp) { - // SPARC: Implement stack banging. + public Address makeAddress(Kind kind, Value base, int displacement) { + // SPARC: Implement address calculation. + return null; + } + + @Override + public Address getPlaceholder() { + // SPARC: Implement address patching. + return null; } }
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -47,22 +47,21 @@ protected InstalledCode assembleMethod(Method m, CodeGenTest test) { ResolvedJavaMethod method = codeCache.lookupJavaMethod(m); - RegisterConfig registerConfig = codeCache.lookupRegisterConfig(method); + RegisterConfig registerConfig = codeCache.lookupRegisterConfig(); + CallingConvention cc = CodeUtil.getCallingConvention(codeCache, CallingConvention.Type.JavaCallee, method, false); CompilationResult compResult = new CompilationResult(); - - Signature sig = method.getSignature(); - JavaType retType = sig.getReturnType(null); - JavaType[] argTypes = new JavaType[sig.getParameterCount(false)]; - for (int i = 0; i < argTypes.length; i++) { - argTypes[i] = sig.getParameterType(i, null); - } - CallingConvention cc = registerConfig.getCallingConvention(CallingConvention.Type.JavaCallee, retType, argTypes, codeCache.getTarget(), false); - Buffer codeBuffer = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); compResult.setTargetCode(codeBuffer.close(true), codeBuffer.position()); - return codeCache.addMethod(method, compResult, null); + InstalledCode code = codeCache.addMethod(method, compResult, null); + + DisassemblerProvider dis = Graal.getRuntime().getCapability(DisassemblerProvider.class); + if (dis != null) { + String disasm = dis.disassemble(code); + Assert.assertTrue(String.valueOf(code.getMethod()), disasm == null || disasm.length() > 0); + } + return code; } protected Object runTest(String methodName, CodeGenTest test, Object... args) { @@ -73,6 +72,6 @@ protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) { Object actual = runTest(methodName, test, args); - Assert.assertEquals("unexpected return value: " + actual, actual, expected); + Assert.assertEquals("unexpected return value", expected, actual); } }
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java Mon Mar 04 10:00:49 2013 +0100 @@ -25,6 +25,7 @@ import java.nio.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; /** * The platform-independent base class for the assembler. @@ -44,7 +45,7 @@ } } - public final void bind(Label l) { + public void bind(Label l) { assert !l.isBound() : "can bind label only once"; l.bind(codeBuffer.position()); l.patchInstructions(this); @@ -56,14 +57,6 @@ protected abstract void patchJumpTarget(int branch, int jumpTarget); - /** - * Emits instruction(s) that access an address specified by a given displacement from the stack - * pointer in the direction that the stack grows (which is down on most architectures). - * - * @param disp the displacement from the stack pointer at which the stack should be accessed - */ - public abstract void bangStack(int disp); - protected final void emitByte(int x) { codeBuffer.emitByte(x); } @@ -79,4 +72,27 @@ protected final void emitLong(long x) { codeBuffer.emitLong(x); } + + /** + * Some GPU architectures have a text based encoding. + */ + protected final void emitString(String x) { + codeBuffer.emitString(x); + } + + // XXX for pretty-printing + protected final void emitString0(String x) { + codeBuffer.emitString0(x); + } + + /** + * This is used by the TargetMethodAssembler to convert a {@link StackSlot} to an + * {@link Address}. + */ + public abstract Address makeAddress(Kind kind, Value base, int displacement); + + /** + * Returns a target specific placeholder address that can be used for code patching. + */ + public abstract Address getPlaceholder(); }
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java Mon Mar 04 10:00:49 2013 +0100 @@ -37,10 +37,6 @@ data = new byte[AsmOptions.InitialCodeBufferSize]; } - public void reset() { - position = 0; - } - public int position() { return position; } @@ -106,6 +102,27 @@ position = emitLong(b, position); } + private static final String NEWLINE = System.getProperty("line.separator"); + + public void emitString(String s) { + position = emitString("\t", position); // XXX REMOVE ME pretty-printing + position = emitString(s, position); + position = emitString(NEWLINE, position); + } + + // XXX for pretty-printing + public void emitString0(String s) { + emitBytes(s.getBytes(), 0, s.length()); + } + + public int emitBytes(byte[] arr, int pos) { + final int len = arr.length; + final int newPos = pos + len; + ensureSize(newPos); + System.arraycopy(arr, 0, data, pos, len); + return newPos; + } + public int emitByte(int b, int pos) { assert NumUtil.isUByte(b); int newPos = pos + 1; @@ -120,6 +137,10 @@ public abstract int emitLong(long b, int pos); + public int emitString(String s, int pos) { + return emitBytes(s.getBytes(), pos); + } + public int getByte(int pos) { return data[pos] & 0xff; }
--- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/Bytecodes.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/Bytecodes.java Mon Mar 04 10:00:49 2013 +0100 @@ -226,7 +226,7 @@ public static final int INVOKESPECIAL = 183; // 0xB7 public static final int INVOKESTATIC = 184; // 0xB8 public static final int INVOKEINTERFACE = 185; // 0xB9 - public static final int XXXUNUSEDXXX = 186; // 0xBA + public static final int INVOKEDYNAMIC = 186; // 0xBA public static final int NEW = 187; // 0xBB public static final int NEWARRAY = 188; // 0xBC public static final int ANEWARRAY = 189; // 0xBD @@ -552,7 +552,7 @@ def(INVOKESPECIAL , "invokespecial" , "bjj" , 5, TRAP | INVOKE); def(INVOKESTATIC , "invokestatic" , "bjj" , 5, TRAP | INVOKE); def(INVOKEINTERFACE , "invokeinterface" , "bjja_", 7, TRAP | INVOKE); - def(XXXUNUSEDXXX , "xxxunusedxxx" , "" , 0); + def(INVOKEDYNAMIC , "invokedynamic" , "bjjjj", 7, TRAP | INVOKE); def(NEW , "new" , "bii" , 6, TRAP); def(NEWARRAY , "newarray" , "bc" , 6, TRAP); def(ANEWARRAY , "anewarray" , "bii" , 6, TRAP);
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Mon Mar 04 10:00:49 2013 +0100 @@ -25,8 +25,8 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*; +import static com.oracle.graal.lir.amd64.AMD64BitManipulationOp.IntrinsicOpcode.*; import static com.oracle.graal.lir.amd64.AMD64Compare.*; -import static com.oracle.graal.lir.amd64.AMD64BitManipulationOp.IntrinsicOpcode.*; import static com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode.*; import com.oracle.graal.amd64.*; @@ -41,11 +41,12 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; import com.oracle.graal.lir.amd64.AMD64Arithmetic.DivOp; -import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op1Reg; -import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op1Stack; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.DivRemOp; import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op2Reg; import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op2Stack; import com.oracle.graal.lir.amd64.AMD64Arithmetic.ShiftOp; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary1Op; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2Op; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp; import com.oracle.graal.lir.amd64.AMD64Call.IndirectCallOp; @@ -66,10 +67,11 @@ import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp; import com.oracle.graal.lir.amd64.AMD64Move.NullCheckOp; import com.oracle.graal.lir.amd64.AMD64Move.SpillMoveOp; +import com.oracle.graal.lir.amd64.AMD64Move.StackLeaOp; +import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.util.*; @@ -137,65 +139,14 @@ } @Override - public Address makeAddress(LocationNode location, ValueNode object) { - Value base = operand(object); - Value index = Value.ILLEGAL; - int scale = 1; - int displacement = location.displacement(); - - if (isConstant(base)) { - if (asConstant(base).isNull()) { - base = Value.ILLEGAL; - } else if (asConstant(base).getKind() != Kind.Object) { - long newDisplacement = displacement + asConstant(base).asLong(); - if (NumUtil.isInt(newDisplacement)) { - assert !runtime.needsDataPatch(asConstant(base)); - displacement = (int) newDisplacement; - base = Value.ILLEGAL; - } else { - Value newBase = newVariable(Kind.Long); - emitMove(base, newBase); - base = newBase; - } - } - } - - if (location instanceof IndexedLocationNode) { - IndexedLocationNode indexedLoc = (IndexedLocationNode) location; - - index = operand(indexedLoc.index()); - if (indexedLoc.indexScalingEnabled()) { - scale = target().sizeInBytes(location.getValueKind()); - } - if (isConstant(index)) { - long newDisplacement = displacement + asConstant(index).asLong() * scale; - // only use the constant index if the resulting displacement fits into a 32 bit - // offset - if (NumUtil.isInt(newDisplacement)) { - displacement = (int) newDisplacement; - index = Value.ILLEGAL; - } else { - // create a temporary variable for the index, the pointer load cannot handle a - // constant index - Value newIndex = newVariable(Kind.Long); - emitMove(index, newIndex); - index = newIndex; - } - } - } - - return new Address(location.getValueKind(), base, index, Address.Scale.fromInt(scale), displacement); - } - - @Override public Variable emitMove(Value input) { Variable result = newVariable(input.getKind()); - emitMove(input, result); + emitMove(result, input); return result; } @Override - public void emitMove(Value src, Value dst) { + public void emitMove(Value dst, Value src) { if (isRegister(src) || isStackSlot(dst)) { append(new MoveFromRegOp(dst, src)); } else { @@ -203,27 +154,94 @@ } } + private AMD64Address prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { + Value baseRegister = base; + int finalDisp = displacement; + if (isConstant(base)) { + if (asConstant(base).isNull()) { + baseRegister = Value.ILLEGAL; + } else if (asConstant(base).getKind() != Kind.Object) { + long newDisplacement = displacement + asConstant(base).asLong(); + if (NumUtil.isInt(newDisplacement)) { + assert !runtime.needsDataPatch(asConstant(base)); + finalDisp = (int) newDisplacement; + baseRegister = Value.ILLEGAL; + } else { + Value newBase = newVariable(Kind.Long); + emitMove(newBase, base); + baseRegister = newBase; + } + } + } + + Value indexRegister = index; + AMD64Address.Scale scaleEnum; + if (index != Value.ILLEGAL && scale > 0) { + scaleEnum = AMD64Address.Scale.fromInt(scale); + if (isConstant(index)) { + long newDisplacement = finalDisp + asConstant(index).asLong() * scale; + // only use the constant index if the resulting displacement fits into a 32 bit + // offset + if (NumUtil.isInt(newDisplacement)) { + finalDisp = (int) newDisplacement; + indexRegister = Value.ILLEGAL; + } else { + // create a temporary variable for the index, the pointer load cannot handle a + // constant index + Value newIndex = newVariable(Kind.Long); + emitMove(newIndex, index); + indexRegister = newIndex; + } + } + } else { + indexRegister = Value.ILLEGAL; + scaleEnum = AMD64Address.Scale.Times1; + } + + return new AMD64Address(kind, baseRegister, indexRegister, scaleEnum, finalDisp); + } + @Override - public Variable emitLoad(Value loadAddress, boolean canTrap) { + public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) { + AMD64Address loadAddress = prepareAddress(kind, base, displacement, index, scale); Variable result = newVariable(loadAddress.getKind()); append(new LoadOp(result, loadAddress, canTrap ? state() : null)); return result; } @Override - public void emitStore(Value storeAddress, Value inputVal, boolean canTrap) { - Value input = loadForStore(inputVal, storeAddress.getKind()); - append(new StoreOp(storeAddress, input, canTrap ? state() : null)); + public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) { + AMD64Address storeAddress = prepareAddress(kind, base, displacement, index, scale); + LIRFrameState state = canTrap ? state() : null; + + if (isConstant(inputVal)) { + Constant c = asConstant(inputVal); + if (canStoreConstant(c)) { + append(new StoreConstantOp(storeAddress, c, state)); + return; + } + } + + Variable input = load(inputVal); + append(new StoreOp(storeAddress, input, state)); } @Override - public Variable emitLea(Value address) { + public Variable emitLea(Value base, int displacement, Value index, int scale) { Variable result = newVariable(target().wordKind); + AMD64Address address = prepareAddress(result.getKind(), base, displacement, index, scale); append(new LeaOp(result, address)); return result; } @Override + public Variable emitLea(StackSlot address) { + Variable result = newVariable(target().wordKind); + append(new StackLeaOp(result, address)); + return result; + } + + @Override public void emitJump(LabelRef label, LIRFrameState info) { append(new JumpOp(label, info)); } @@ -314,7 +332,6 @@ mirrored = false; } switch (left.getKind().getStackKind()) { - case Jsr: case Int: append(new CompareOp(ICMP, left, right)); break; @@ -337,14 +354,15 @@ } @Override - public Variable emitNegate(Value input) { + public Variable emitNegate(Value inputVal) { + AllocatableValue input = asAllocatable(inputVal); Variable result = newVariable(input.getKind()); switch (input.getKind()) { case Int: - append(new Op1Stack(INEG, result, input)); + append(new Unary1Op(INEG, result, input)); break; case Long: - append(new Op1Stack(LNEG, result, input)); + append(new Unary1Op(LNEG, result, input)); break; case Float: append(new Op2Reg(FXOR, result, input, Constant.forFloat(Float.intBitsToFloat(0x80000000)))); @@ -454,11 +472,11 @@ public Value[] emitIntegerDivRem(Value a, Value b) { switch (a.getKind()) { case Int: - emitMove(a, RAX_I); + emitMove(RAX_I, a); append(new DivRemOp(IDIVREM, RAX_I, load(b), state())); return new Value[]{emitMove(RAX_I), emitMove(RDX_I)}; case Long: - emitMove(a, RAX_L); + emitMove(RAX_L, a); append(new DivRemOp(LDIVREM, RAX_L, load(b), state())); return new Value[]{emitMove(RAX_L), emitMove(RDX_L)}; default: @@ -470,11 +488,11 @@ public Value emitDiv(Value a, Value b) { switch (a.getKind()) { case Int: - emitMove(a, RAX_I); + emitMove(RAX_I, a); append(new DivOp(IDIV, RAX_I, RAX_I, load(b), state())); return emitMove(RAX_I); case Long: - emitMove(a, RAX_L); + emitMove(RAX_L, a); append(new DivOp(LDIV, RAX_L, RAX_L, load(b), state())); return emitMove(RAX_L); case Float: { @@ -496,11 +514,11 @@ public Value emitRem(Value a, Value b) { switch (a.getKind()) { case Int: - emitMove(a, RAX_I); + emitMove(RAX_I, a); append(new DivOp(IREM, RDX_I, RAX_I, load(b), state())); return emitMove(RDX_I); case Long: - emitMove(a, RAX_L); + emitMove(RAX_L, a); append(new DivOp(LREM, RDX_L, RAX_L, load(b), state())); return emitMove(RDX_L); case Float: { @@ -520,11 +538,11 @@ public Variable emitUDiv(Value a, Value b) { switch (a.getKind()) { case Int: - emitMove(a, RAX_I); + emitMove(RAX_I, a); append(new DivOp(IUDIV, RAX_I, RAX_I, load(b), state())); return emitMove(RAX_I); case Long: - emitMove(a, RAX_L); + emitMove(RAX_L, a); append(new DivOp(LUDIV, RAX_L, RAX_L, load(b), state())); return emitMove(RAX_L); default: @@ -536,11 +554,11 @@ public Variable emitURem(Value a, Value b) { switch (a.getKind()) { case Int: - emitMove(a, RAX_I); + emitMove(RAX_I, a); append(new DivOp(IUREM, RDX_I, RAX_I, load(b), state())); return emitMove(RDX_I); case Long: - emitMove(a, RAX_L); + emitMove(RAX_L, a); append(new DivOp(LUREM, RDX_L, RAX_L, load(b), state())); return emitMove(RDX_L); default: @@ -649,7 +667,7 @@ return value; } // Non-constant shift count must be in RCX - emitMove(value, RCX_I); + emitMove(RCX_I, value); return RCX_I; } @@ -659,67 +677,67 @@ Variable result = newVariable(opcode.to); switch (opcode) { case I2L: - append(new Op1Reg(I2L, result, input)); + append(new Unary2Op(I2L, result, input)); break; case L2I: - append(new Op1Stack(L2I, result, input)); + append(new Unary1Op(L2I, result, input)); break; case I2B: - append(new Op1Stack(I2B, result, input)); + append(new Unary2Op(I2B, result, input)); break; case I2C: - append(new Op1Stack(I2C, result, input)); + append(new Unary1Op(I2C, result, input)); break; case I2S: - append(new Op1Stack(I2S, result, input)); + append(new Unary2Op(I2S, result, input)); break; case F2D: - append(new Op1Reg(F2D, result, input)); + append(new Unary2Op(F2D, result, input)); break; case D2F: - append(new Op1Reg(D2F, result, input)); + append(new Unary2Op(D2F, result, input)); break; case I2F: - append(new Op1Reg(I2F, result, input)); + append(new Unary2Op(I2F, result, input)); break; case I2D: - append(new Op1Reg(I2D, result, input)); + append(new Unary2Op(I2D, result, input)); break; case F2I: - append(new Op1Reg(F2I, result, input)); + append(new Unary2Op(F2I, result, input)); break; case D2I: - append(new Op1Reg(D2I, result, input)); + append(new Unary2Op(D2I, result, input)); break; case L2F: - append(new Op1Reg(L2F, result, input)); + append(new Unary2Op(L2F, result, input)); break; case L2D: - append(new Op1Reg(L2D, result, input)); + append(new Unary2Op(L2D, result, input)); break; case F2L: - append(new Op1Reg(F2L, result, input)); + append(new Unary2Op(F2L, result, input)); break; case D2L: - append(new Op1Reg(D2L, result, input)); + append(new Unary2Op(D2L, result, input)); break; case MOV_I2F: - append(new Op1Reg(MOV_I2F, result, input)); + append(new Unary2Op(MOV_I2F, result, input)); break; case MOV_L2D: - append(new Op1Reg(MOV_L2D, result, input)); + append(new Unary2Op(MOV_L2D, result, input)); break; case MOV_F2I: - append(new Op1Reg(MOV_F2I, result, input)); + append(new Unary2Op(MOV_F2I, result, input)); break; case MOV_D2L: - append(new Op1Reg(MOV_D2L, result, input)); + append(new Unary2Op(MOV_D2L, result, input)); break; case UNSIGNED_I2L: // Instructions that move or generate 32-bit register values also set the upper 32 // bits of the register to zero. // Consequently, there is no need for a special zero-extension move. - emitMove(input, result); + emitMove(result, input); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -731,7 +749,7 @@ public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { LIRFrameState info = state(); LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo); - append(new BranchOp(ConditionFlag.overflow, stubEntry, info)); + append(new BranchOp(ConditionFlag.Overflow, stubEntry, info)); } @Override @@ -759,7 +777,7 @@ // The current register allocator cannot handle variables at call sites, need a fixed // register. Value targetAddress = AMD64.rax.asValue(); - emitMove(operand(callTarget.computedAddress()), targetAddress); + emitMove(targetAddress, operand(callTarget.computedAddress())); append(new IndirectCallOp(callTarget.target(), result, parameters, temps, targetAddress, callState)); } @@ -775,23 +793,23 @@ @Override public void emitBitCount(Variable result, Value value) { if (value.getKind().getStackKind() == Kind.Int) { - append(new AMD64BitManipulationOp(IPOPCNT, result, value)); + append(new AMD64BitManipulationOp(IPOPCNT, result, asAllocatable(value))); } else { - append(new AMD64BitManipulationOp(LPOPCNT, result, value)); + append(new AMD64BitManipulationOp(LPOPCNT, result, asAllocatable(value))); } } @Override public void emitBitScanForward(Variable result, Value value) { - append(new AMD64BitManipulationOp(BSF, result, value)); + append(new AMD64BitManipulationOp(BSF, result, asAllocatable(value))); } @Override public void emitBitScanReverse(Variable result, Value value) { if (value.getKind().getStackKind() == Kind.Int) { - append(new AMD64BitManipulationOp(IBSR, result, value)); + append(new AMD64BitManipulationOp(IBSR, result, asAllocatable(value))); } else { - append(new AMD64BitManipulationOp(LBSR, result, value)); + append(new AMD64BitManipulationOp(LBSR, result, asAllocatable(value))); } } @@ -883,19 +901,19 @@ Value expected = loadNonConst(operand(node.expected())); Variable newValue = load(operand(node.newValue())); - Address address; + AMD64Address address; int displacement = node.displacement(); Value index = operand(node.offset()); if (isConstant(index) && NumUtil.isInt(asConstant(index).asLong() + displacement)) { assert !runtime.needsDataPatch(asConstant(index)); displacement += (int) asConstant(index).asLong(); - address = new Address(kind, load(operand(node.object())), displacement); + address = new AMD64Address(kind, load(operand(node.object())), displacement); } else { - address = new Address(kind, load(operand(node.object())), load(index), Address.Scale.Times1, displacement); + address = new AMD64Address(kind, load(operand(node.object())), load(index), AMD64Address.Scale.Times1, displacement); } RegisterValue rax = AMD64.rax.asValue(kind); - emitMove(expected, rax); + emitMove(rax, expected); append(new CompareAndSwapOp(rax, address, rax, newValue)); Variable result = newVariable(node.kind());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.ptx.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.PhasePlan.*; +import com.oracle.graal.ptx.*; + +/** + * Test class for small Java methods compiled to PTX kernels. + */ +public class BasicPTXTest extends GraalCompilerTest { + + @Test + public void test1() { + test("test1Snippet"); + } + + @SuppressWarnings("all") + public static int test1Snippet(int a) { + return a + 1; + } + + private void test(String snippet) { + StructuredGraph graph = parse(snippet); + Debug.dump(graph, "Graph"); + TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true); + PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(CodeCacheProvider.class), target); + PhasePlan phasePlan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + CompilationResult result = GraalCompiler.compileMethod(runtime, ptxBackend, target, graph.method(), graph, null, phasePlan, OptimisticOptimizations.NONE); + System.out.println("result=" + result); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.asm.ptx.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; + +/** + * PTX specific backend. + */ +public class PTXBackend extends Backend { + + public PTXBackend(CodeCacheProvider runtime, TargetDescription target) { + super(runtime, target); + } + + @Override + public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { + return new PTXLIRGenerator(graph, runtime(), target, frameMap, method, lir); + } + + class HotSpotFrameContext implements FrameContext { + + @Override + public void enter(TargetMethodAssembler tasm) { + Buffer codeBuffer = tasm.asm.codeBuffer; + codeBuffer.emitString(".version 1.4"); + codeBuffer.emitString(".target sm_10"); + // codeBuffer.emitString(".address_size 32"); // PTX ISA version 2.3 + } + + @Override + public void leave(TargetMethodAssembler tasm) { + } + } + + @Override + public TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir) { + // Omit the frame if the method: + // - has no spill slots or other slots allocated during register allocation + // - has no callee-saved registers + // - has no incoming arguments passed on the stack + // - has no instructions with debug info + boolean omitFrame = GraalOptions.CanOmitFrame && frameMap.frameSize() == frameMap.initialFrameSize && frameMap.registerConfig.getCalleeSaveLayout().registers.length == 0 && + !lir.hasArgInCallerFrame() && !lir.hasDebugInfo(); + + AbstractAssembler masm = new PTXAssembler(target, frameMap.registerConfig); + HotSpotFrameContext frameContext = omitFrame ? null : new HotSpotFrameContext(); + TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, lir.stubs); + tasm.setFrameSize(frameMap.frameSize()); + tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetToCustomArea()); + return tasm; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIR lir) { + // Emit the prologue + final String name = method.getName(); + Buffer codeBuffer = tasm.asm.codeBuffer; + codeBuffer.emitString0(".entry " + name + " ("); + codeBuffer.emitString(""); + + Signature signature = method.getSignature(); + for (int i = 0; i < signature.getParameterCount(false); i++) { + System.err.println(i + ": " + signature.getParameterKind(i)); + String param = ".param .u32 param" + i; + codeBuffer.emitString(param); + } + + codeBuffer.emitString0(") {"); + codeBuffer.emitString(""); + + // XXX For now declare one predicate and all registers + codeBuffer.emitString(" .reg .pred %p;"); + codeBuffer.emitString(" .reg .u32 %r<16>;"); + + // Emit code for the LIR + lir.emitCode(tasm); + + // Emit the epilogue + codeBuffer.emitString0("}"); + codeBuffer.emitString(""); + + byte[] data = codeBuffer.copyData(0, codeBuffer.position()); + System.err.println(new String(data)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXDeoptimizationStub.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.asm.ptx.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.ptx.*; +import com.oracle.graal.lir.asm.*; + +public class PTXDeoptimizationStub extends PTXCode { + + public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", true, void.class); + public static final Descriptor SET_DEOPT_INFO = new Descriptor("setDeoptInfo", true, void.class, Object.class); + + public final Label label = new Label(); + public final LIRFrameState info; + public final DeoptimizationAction action; + public final DeoptimizationReason reason; + public final Object deoptInfo; + + public PTXDeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { + this.action = action; + this.reason = reason; + this.info = info; + this.deoptInfo = deoptInfo; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + masm.exit(); + } + + @Override + public String description() { + return "deopt stub[reason=" + reason + ", action=" + action + "]"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,474 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.compiler.ptx; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.ptx.PTXArithmetic.*; +import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*; +import static com.oracle.graal.lir.ptx.PTXCompare.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.JumpOp; +import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack; +import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Reg; +import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Stack; +import com.oracle.graal.lir.ptx.PTXArithmetic.ShiftOp; +import com.oracle.graal.lir.ptx.*; +import com.oracle.graal.lir.ptx.PTXCompare.CompareOp; +import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp; +import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp; +import com.oracle.graal.lir.ptx.PTXMove.LoadOp; +import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp; +import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp; +import com.oracle.graal.lir.ptx.PTXMove.StoreOp; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.ptx.*; + +/** + * This class implements the PTX specific portion of the LIR generator. + */ +public class PTXLIRGenerator extends LIRGenerator { + + public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory { + + @Override + public LIRInstruction createMove(Value result, Value input) { + throw new InternalError("NYI"); + } + } + + public PTXLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { + super(graph, runtime, target, frameMap, method, lir); + lir.spillMoveFactory = new PTXSpillMoveFactory(); + } + + @Override + protected void emitNode(ValueNode node) { + if (node instanceof LIRGenLowerable) { + ((LIRGenLowerable) node).generate(this); + } else { + super.emitNode(node); + } + } + + @Override + public boolean canStoreConstant(Constant c) { + // Operand b must be in the .reg state space. + return false; + } + + @Override + public boolean canInlineConstant(Constant c) { + switch (c.getKind()) { + case Long: + return NumUtil.isInt(c.asLong()) && !runtime.needsDataPatch(c); + case Object: + return c.isNull(); + default: + return true; + } + } + + @Override + public Variable emitMove(Value input) { + Variable result = newVariable(input.getKind()); + emitMove(result, input); + return result; + } + + @Override + public void emitMove(Value dst, Value src) { + if (isRegister(src) || isStackSlot(dst)) { + append(new MoveFromRegOp(dst, src)); + } else { + append(new MoveToRegOp(dst, src)); + } + } + + private PTXAddress prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { + Value baseRegister = base; + long finalDisp = displacement; + if (isConstant(base)) { + if (asConstant(base).isNull()) { + baseRegister = Value.ILLEGAL; + } else if (asConstant(base).getKind() != Kind.Object) { + finalDisp += asConstant(base).asLong(); + baseRegister = Value.ILLEGAL; + } + } + + if (index != Value.ILLEGAL) { + if (isConstant(index)) { + finalDisp += asConstant(index).asLong() * scale; + } else { + Value indexRegister = index; + if (scale != 1) { + indexRegister = emitMul(index, Constant.forInt(scale)); + } + if (baseRegister == Value.ILLEGAL) { + baseRegister = indexRegister; + } else { + baseRegister = emitAdd(baseRegister, indexRegister); + } + } + } + + return new PTXAddress(kind, baseRegister, finalDisp); + } + + @Override + public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) { + PTXAddress loadAddress = prepareAddress(kind, base, displacement, index, scale); + Variable result = newVariable(loadAddress.getKind()); + append(new LoadOp(result, loadAddress, canTrap ? state() : null)); + return result; + } + + @Override + public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) { + PTXAddress storeAddress = prepareAddress(kind, base, displacement, index, scale); + Variable input = load(inputVal); + append(new StoreOp(storeAddress, input, canTrap ? state() : null)); + } + + @Override + public Variable emitLea(Value base, int displacement, Value index, int scale) { + throw new InternalError("NYI"); + } + + @Override + public Variable emitLea(StackSlot address) { + throw new InternalError("NYI"); + } + + @Override + public void emitJump(LabelRef label, LIRFrameState info) { + append(new JumpOp(label, info)); + } + + @Override + public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) { + switch (left.getKind().getStackKind()) { + case Int: + append(new CompareOp(ICMP, cond, left, right)); + append(new BranchOp(cond, label, info)); + break; + case Object: + append(new CompareOp(ACMP, cond, left, right)); + append(new BranchOp(cond, label, info)); + break; + default: + throw GraalInternalError.shouldNotReachHere("" + left.getKind()); + } + } + + @Override + public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) { + throw new InternalError("NYI"); + } + + @Override + public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { + throw new InternalError("NYI"); + } + + @Override + public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { + throw new InternalError("NYI"); + } + + @Override + public Variable emitNegate(Value input) { + Variable result = newVariable(input.getKind()); + switch (input.getKind()) { + case Int: + append(new Op1Stack(INEG, result, input)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + public Variable emitAdd(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Stack(IADD, result, a, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + public Variable emitSub(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Stack(ISUB, result, a, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + public Variable emitMul(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Reg(IMUL, result, a, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + protected boolean peephole(ValueNode valueNode) { + // No peephole optimizations for now + return false; + } + + @Override + public Value emitDiv(Value a, Value b) { + throw new InternalError("NYI"); + } + + @Override + public Value emitRem(Value a, Value b) { + throw new InternalError("NYI"); + } + + @Override + public Variable emitUDiv(Value a, Value b) { + throw new InternalError("NYI"); + } + + @Override + public Variable emitURem(Value a, Value b) { + throw new InternalError("NYI"); + } + + @Override + public Variable emitAnd(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Stack(IAND, result, a, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + public Variable emitOr(Value a, Value b) { + throw new InternalError("NYI"); + } + + @Override + public Variable emitXor(Value a, Value b) { + throw new InternalError("NYI"); + } + + @Override + public Variable emitShl(Value a, Value b) { + throw new InternalError("NYI"); + } + + @Override + public Variable emitShr(Value a, Value b) { + throw new InternalError("NYI"); + } + + @Override + public Variable emitUShr(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new ShiftOp(IUSHR, result, a, b)); + break; + default: + GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) { + throw new InternalError("NYI"); + } + + @Override + public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { + throw new InternalError("NYI"); + } + + @Override + public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { + throw new InternalError("NYI"); + } + + @Override + public void emitMembar(int barriers) { + throw new InternalError("NYI"); + } + + @Override + protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + throw new InternalError("NYI"); + } + + @Override + protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + throw new InternalError("NYI"); + } + + @Override + protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info) { + throw new InternalError("NYI"); + } + + @Override + public void emitBitCount(Variable result, Value value) { + if (value.getKind().getStackKind() == Kind.Int) { + append(new PTXBitManipulationOp(IPOPCNT, result, value)); + } else { + append(new PTXBitManipulationOp(LPOPCNT, result, value)); + } + } + + @Override + public void emitBitScanForward(Variable result, Value value) { + throw new InternalError("NYI"); + } + + @Override + public void emitBitScanReverse(Variable result, Value value) { + throw new InternalError("NYI"); + } + + @Override + public void emitMathAbs(Variable result, Variable input) { + throw new InternalError("NYI"); + } + + @Override + public void emitMathSqrt(Variable result, Variable input) { + throw new InternalError("NYI"); + } + + @Override + public void emitMathLog(Variable result, Variable input, boolean base10) { + throw new InternalError("NYI"); + } + + @Override + public void emitMathCos(Variable result, Variable input) { + throw new InternalError("NYI"); + } + + @Override + public void emitMathSin(Variable result, Variable input) { + throw new InternalError("NYI"); + } + + @Override + public void emitMathTan(Variable result, Variable input) { + throw new InternalError("NYI"); + } + + @Override + public void emitByteSwap(Variable result, Value input) { + throw new InternalError("NYI"); + } + + @Override + protected void emitReturn(Value input) { + append(new ReturnOp(input)); + } + + @Override + protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) { + throw new InternalError("NYI"); + } + + @Override + protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) { + throw new InternalError("NYI"); + } + + @Override + protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) { + throw new InternalError("NYI"); + } + + @Override + protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { + assert info.topFrame.getBCI() >= 0 : "invalid bci for deopt framestate"; + PTXDeoptimizationStub stub = new PTXDeoptimizationStub(action, reason, info, deoptInfo); + lir.stubs.add(stub); + return LabelRef.forLabel(stub.label); + } + + @Override + protected void emitNullCheckGuard(ValueNode object) { + throw new InternalError("NYI"); + } + + @Override + public void visitCompareAndSwap(CompareAndSwapNode node) { + throw new InternalError("NYI"); + } + + @Override + public void visitBreakpointNode(BreakpointNode node) { + throw new InternalError("NYI"); + } + + @Override + public void visitExceptionObject(ExceptionObjectNode i) { + throw new InternalError("NYI"); + } + + @Override + public void visitSafepointNode(SafepointNode i) { + throw new InternalError("NYI"); + } +}
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Mon Mar 04 10:00:49 2013 +0100 @@ -31,7 +31,6 @@ 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.*; /** @@ -215,31 +214,31 @@ } @Override - public Address makeAddress(LocationNode location, ValueNode object) { - // SPARC: Auto-generated method stub - return null; - } - - @Override - public void emitMove(Value src, Value dst) { + public void emitMove(Value dst, Value src) { // SPARC: Auto-generated method stub } @Override - public Value emitLoad(Value loadAddress, boolean canTrap) { + public Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) { // SPARC: Auto-generated method stub return null; } @Override - public void emitStore(Value storeAddress, Value input, boolean canTrap) { + public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, boolean canTrap) { // SPARC: Auto-generated method stub } @Override - public Value emitLea(Value address) { + public Value emitLea(Value base, int displacement, Value index, int scale) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitLea(StackSlot address) { // SPARC: Auto-generated method stub return null; }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -126,13 +126,13 @@ } Assumptions assumptions = new Assumptions(false); - new InliningPhase(null, runtime(), hints, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new InliningPhase(runtime(), hints, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); Debug.dump(graph, "Graph"); new BoxingEliminationPhase(runtime()).apply(graph); Debug.dump(graph, "Graph"); new ExpandBoxingNodesPhase(pool).apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -35,7 +35,7 @@ private StructuredGraph getCanonicalizedGraph(String name) { StructuredGraph graph = parse(name); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(runtime(), null).apply(graph); return graph; } @@ -53,7 +53,7 @@ assertEquals(referenceGraph, graph); } Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph); + new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph); for (int i = 1; i < 4; i++) { StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i); assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompiledMethodTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompiledMethodTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -56,7 +56,7 @@ public void test1() { Method method = getMethod("testMethod"); final StructuredGraph graph = parse(method); - new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); new DeadCodeEliminationPhase().apply(graph); for (Node node : graph.getNodes()) { @@ -112,8 +112,8 @@ Method method = CompilableObjectImpl.class.getDeclaredMethod("executeHelper", ObjectCompiler.class, String.class); ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph); - new CanonicalizerPhase(null, runtime, new Assumptions(false)).apply(graph); + new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.NONE).apply(graph); + new CanonicalizerPhase(runtime, new Assumptions(false)).apply(graph); new DeadCodeEliminationPhase().apply(graph); for (Node node : graph.getNodes()) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -84,7 +84,7 @@ for (Invoke invoke : graph.getInvokes()) { invoke.intrinsify(null); } - new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); Debug.dump(referenceGraph, "Graph"); assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Verbosity; @@ -68,11 +69,13 @@ protected final GraalCodeCacheProvider runtime; protected final GraalCompiler graalCompiler; + protected final Backend backend; public GraalCompilerTest() { DebugEnvironment.initialize(System.out); this.runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class); this.graalCompiler = Graal.getRequiredCapability(GraalCompiler.class); + this.backend = Graal.getRequiredCapability(Backend.class); } protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { @@ -305,8 +308,6 @@ Assert.assertTrue("expected " + expect.exception, actual.exception != null); Assert.assertEquals(expect.exception.getClass(), actual.exception.getClass()); } else { - // System.out.println(name + "(" + Arrays.toString(args) + "): expected=" + - // expect.returnValue + ", actual=" + actual.returnValue); assertEquals(expect.returnValue, actual.returnValue); } } @@ -342,8 +343,6 @@ if (cached != null) { if (cached.isValid()) { return cached; - } else { - // System.out.println(cached.getMethod() + " was invalidated"); } } @@ -363,7 +362,7 @@ GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); editPhasePlan(method, graph, phasePlan); - CompilationResult compResult = graalCompiler.compileMethod(method, graph, null, phasePlan, OptimisticOptimizations.ALL); + CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL); if (printCompilation) { TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); } @@ -408,7 +407,7 @@ protected StructuredGraph parse(Method m) { ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(m); StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.ALL).apply(graph); + new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); return graph; } @@ -424,7 +423,7 @@ protected PhasePlan getDefaultPhasePlan() { PhasePlan plan = new PhasePlan(); - plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.ALL)); + plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL)); return plan; } }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -89,19 +89,19 @@ } Assumptions assumptions = new Assumptions(false); - new InliningPhase(null, runtime(), hints, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new InliningPhase(runtime(), hints, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); new PhiStampPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); Debug.dump(graph, "Graph"); new BoxingEliminationPhase(runtime()).apply(graph); Debug.dump(graph, "Graph"); new ExpandBoxingNodesPhase(pool).apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); - new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph); + new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph); new DeadCodeEliminationPhase().apply(referenceGraph); assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -144,7 +144,7 @@ n.replaceFirstInput(local, constant); } Debug.dump(graph, "Graph"); - new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -65,8 +65,8 @@ hints.add(invoke); } Assumptions assumptions = new Assumptions(false); - new InliningPhase(null, runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new InliningPhase(runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); } }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -76,8 +76,8 @@ } Assumptions assumptions = new Assumptions(false); - new InliningPhase(null, runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new InliningPhase(runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -133,8 +133,8 @@ } Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph); Debug.scope("Test", new DebugDumpScope("Test:" + snippet), new Runnable() { @Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test; + +import static org.junit.Assert.*; + +import java.util.concurrent.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.schedule.*; + +/** + * In these test the FrameStates are explicitly cleared out, so that the scheduling of + * FloatingReadNodes depends solely on the scheduling algorithm. The FrameStates normally keep the + * FloatingReadNodes above a certain point, so that they (most of the time...) magically do the + * right thing. + * + * The scheduling shouldn't depend on FrameStates, which is tested by this class. + */ +public class MemoryScheduleTest extends GraphScheduleTest { + + private static enum TestMode { + WITH_FRAMESTATES, WITHOUT_FRAMESTATES, INLINED_WITHOUT_FRAMESTATES + } + + public static class Container { + + public int a; + public int b; + public int c; + } + + private static final Container container = new Container(); + + /** + * In this test the read should be scheduled before the write. + */ + public static int testSimpleSnippet() { + try { + return container.a; + } finally { + container.a = 15; + } + } + + @Test + public void testSimple() { + for (TestMode mode : TestMode.values()) { + SchedulePhase schedule = getFinalSchedule("testSimpleSnippet", mode); + assertReadAfterWrite(schedule, false); + } + } + + /** + * In this case the read should be scheduled in the first block. + */ + public static int testSplitSnippet1(int a) { + try { + return container.a; + } finally { + if (a < 0) { + container.a = 15; + } else { + container.b = 15; + } + } + } + + @Test + public void testSplit1() { + for (TestMode mode : TestMode.values()) { + SchedulePhase schedule = getFinalSchedule("testSplitSnippet1", mode); + assertReadWithinStartBlock(schedule, true); + } + } + + /** + * Here the read should float to the end. + */ + public static int testSplit2Snippet(int a) { + try { + return container.a; + } finally { + if (a < 0) { + container.c = 15; + } else { + container.b = 15; + } + } + } + + @Test + public void testSplit2() { + SchedulePhase schedule = getFinalSchedule("testSplit2Snippet", TestMode.WITHOUT_FRAMESTATES); + assertReadWithinStartBlock(schedule, false); + } + + /** + * Here the read should not float to the end. + */ + public static int testLoop1Snippet(int a, int b) { + try { + return container.a; + } finally { + for (int i = 0; i < a; i++) { + if (b < 0) { + container.b = 10; + } else { + container.a = 15; + } + } + } + } + + @Test + public void testLoop1() { + SchedulePhase schedule = getFinalSchedule("testLoop1Snippet", TestMode.WITHOUT_FRAMESTATES); + assertEquals(7, schedule.getCFG().getBlocks().length); + assertReadWithinStartBlock(schedule, true); + } + + /** + * Here the read should float to the end. + */ + public static int testLoop2Snippet(int a, int b) { + try { + return container.a; + } finally { + for (int i = 0; i < a; i++) { + if (b < 0) { + container.b = 10; + } else { + container.c = 15; + } + } + } + } + + @Test + public void testLoop2() { + SchedulePhase schedule = getFinalSchedule("testLoop2Snippet", TestMode.WITHOUT_FRAMESTATES); + assertEquals(7, schedule.getCFG().getBlocks().length); + assertReadWithinStartBlock(schedule, false); + } + + /** + * Here the read should float to the end (into the same block as the return). + */ + public static int testArrayCopySnippet(Integer intValue, char[] a, char[] b, int len) { + System.arraycopy(a, 0, b, 0, len); + return intValue.intValue(); + } + + @Test + public void testArrayCopy() { + SchedulePhase schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES); + StructuredGraph graph = (StructuredGraph) schedule.getCFG().getStartBlock().getBeginNode().graph(); + ReturnNode ret = graph.getNodes(ReturnNode.class).first(); + assertTrue(ret.result() instanceof FloatingReadNode); + assertEquals(schedule.getCFG().blockFor(ret), schedule.getCFG().blockFor(ret.result())); + } + + private void assertReadAfterWrite(SchedulePhase schedule, boolean readAfterWrite) { + boolean writeEncountered = false; + assertEquals(1, schedule.getCFG().getBlocks().length); + for (Node node : schedule.getBlockToNodesMap().get(schedule.getCFG().getStartBlock())) { + if (node instanceof WriteNode) { + writeEncountered = true; + } else if (node instanceof FloatingReadNode) { + assertEquals(readAfterWrite, writeEncountered); + } + } + } + + private void assertReadWithinStartBlock(SchedulePhase schedule, boolean withinStartBlock) { + boolean readEncountered = false; + for (Node node : schedule.getBlockToNodesMap().get(schedule.getCFG().getStartBlock())) { + if (node instanceof FloatingReadNode) { + readEncountered = true; + } + } + assertEquals(withinStartBlock, readEncountered); + } + + private SchedulePhase getFinalSchedule(final String snippet, final TestMode mode) { + return Debug.scope("FloatingReadTest", new DebugDumpScope(snippet), new Callable<SchedulePhase>() { + + @Override + public SchedulePhase call() throws Exception { + StructuredGraph graph = parse(snippet); + if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { + Assumptions assumptions = new Assumptions(false); + new InliningPhase(runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + } + new LoweringPhase(null, runtime(), new Assumptions(false)).apply(graph); + if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { + for (Node node : graph.getNodes()) { + if (node instanceof StateSplit) { + FrameState stateAfter = ((StateSplit) node).stateAfter(); + if (stateAfter != null) { + ((StateSplit) node).setStateAfter(null); + GraphUtil.killWithUnusedFloatingInputs(stateAfter); + } + } + } + } + new FloatingReadPhase().apply(graph); + + new RemoveValueProxyPhase().apply(graph); + + SchedulePhase schedule = new SchedulePhase(); + schedule.apply(graph); + return schedule; + } + }); + } +}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -93,8 +93,8 @@ hints.add(invoke); } Assumptions assumptions = new Assumptions(false); - new InliningPhase(null, runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new InliningPhase(runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); return graph; }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -244,9 +244,9 @@ private <T extends Node & Node.IterableNodeType> void test(String test, String ref) { StructuredGraph testGraph = parse(test); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(null, runtime(), assumptions).apply(testGraph); + new CanonicalizerPhase(runtime(), assumptions).apply(testGraph); StructuredGraph refGraph = parse(ref); - new CanonicalizerPhase(null, runtime(), assumptions).apply(refGraph); + new CanonicalizerPhase(runtime(), assumptions).apply(refGraph); assertEquals(testGraph, refGraph); } }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -165,11 +165,10 @@ // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); - // TypeSystemTest.outputGraph(graph); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); assertEquals(referenceGraph, graph); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -98,7 +98,7 @@ private void testZeroReturn(String methodName) { StructuredGraph graph = parse(methodName); - new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); new DeadCodeEliminationPhase().apply(graph); assertConstantReturn(graph, 0); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -89,7 +89,7 @@ // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); - new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -186,13 +186,13 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); // a second canonicalizer is needed to process nested MaterializeNodes - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); - new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph); + new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph); assertEquals(referenceGraph, graph); } @@ -242,9 +242,9 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); Debug.dump(graph, "Graph"); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext()); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -205,9 +205,9 @@ } Assumptions assumptions = new Assumptions(false); - new InliningPhase(null, runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new InliningPhase(runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); new DeadCodeEliminationPhase().apply(graph); - new PartialEscapeAnalysisPhase(null, runtime(), assumptions, iterativeEscapeAnalysis).apply(graph); + new PartialEscapeAnalysisPhase(runtime(), assumptions, iterativeEscapeAnalysis).apply(graph); Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count()); ReturnNode returnNode = graph.getNodes(ReturnNode.class).first(); if (expectedConstantResult != null) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -150,14 +150,14 @@ n.node().setProbability(100000); } Assumptions assumptions = new Assumptions(false); - new InliningPhase(null, runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new InliningPhase(runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); - new PartialEscapeAnalysisPhase(null, runtime(), assumptions, false).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new PartialEscapeAnalysisPhase(runtime(), assumptions, false).apply(graph); new CullFrameStatesPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); return graph; } catch (AssertionFailedError t) { throw new RuntimeException(t.getMessage() + "\n" + getCanonicalGraphString(graph), t);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -136,9 +136,9 @@ Assumptions assumptions = new Assumptions(true); new ComputeProbabilityPhase().apply(graph); Debug.dump(graph, "Graph"); - new InliningPhase(null, runtime(), null, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); + new InliningPhase(runtime(), null, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); Debug.dump(graph, "Graph"); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); return graph; }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Mar 04 10:00:49 2013 +0100 @@ -47,50 +47,30 @@ public class GraalCompiler { - /** - * The target that this compiler has been configured for. - */ - public final TargetDescription target; - - /** - * The runtime that this compiler has been configured for. - */ - public final GraalCodeCacheProvider runtime; - - /** - * The backend that this compiler has been configured for. - */ - public final Backend backend; - - public GraalCompiler(GraalCodeCacheProvider runtime, TargetDescription target, Backend backend) { - this.runtime = runtime; - this.target = target; - this.backend = backend; - } - - public CompilationResult compileMethod(final ResolvedJavaMethod method, final StructuredGraph graph, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts) { + public static CompilationResult compileMethod(final GraalCodeCacheProvider runtime, final Backend backend, final TargetDescription target, final ResolvedJavaMethod method, + final StructuredGraph graph, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts) { assert (method.getModifiers() & Modifier.NATIVE) == 0 : "compiling native methods is not supported"; - return Debug.scope("GraalCompiler", new Object[]{graph, method, this}, new Callable<CompilationResult>() { + return Debug.scope("GraalCompiler", new Object[]{graph, method}, new Callable<CompilationResult>() { public CompilationResult call() { final Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions); final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() { public LIR call() { - return emitHIR(graph, assumptions, cache, plan, optimisticOpts); + return emitHIR(runtime, target, graph, assumptions, cache, plan, optimisticOpts); } }); final FrameMap frameMap = Debug.scope("BackEnd", lir, new Callable<FrameMap>() { public FrameMap call() { - return emitLIR(lir, graph, method); + return emitLIR(backend, target, lir, graph, method); } }); return Debug.scope("CodeGen", frameMap, new Callable<CompilationResult>() { public CompilationResult call() { - return emitCode(getLeafGraphIdArray(graph), assumptions, method, lir, frameMap); + return emitCode(backend, getLeafGraphIdArray(graph), assumptions, method, lir, frameMap); } }); @@ -110,8 +90,13 @@ /** * Builds the graph, optimizes it. + * + * @param runtime + * + * @param target */ - public LIR emitHIR(StructuredGraph graph, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) { + public static LIR emitHIR(GraalCodeCacheProvider runtime, TargetDescription target, StructuredGraph graph, Assumptions assumptions, GraphCache cache, PhasePlan plan, + OptimisticOptimizations optimisticOpts) { if (graph.start().next() == null) { plan.runPhases(PhasePosition.AFTER_PARSING, graph); @@ -125,16 +110,16 @@ } if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + new CanonicalizerPhase(runtime, assumptions).apply(graph); } if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) { - new InliningPhase(target, runtime, null, assumptions, cache, plan, optimisticOpts).apply(graph); + new InliningPhase(runtime, null, assumptions, cache, plan, optimisticOpts).apply(graph); new DeadCodeEliminationPhase().apply(graph); - if (GraalOptions.CheckCastElimination && GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); - new IterativeConditionalEliminationPhase(target, runtime, assumptions).apply(graph); + if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(runtime, assumptions).apply(graph); + new IterativeConditionalEliminationPhase(runtime, assumptions).apply(graph); } } @@ -145,19 +130,19 @@ if (GraalOptions.FullUnroll) { new LoopFullUnrollPhase(runtime, assumptions).apply(graph); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + new CanonicalizerPhase(runtime, assumptions).apply(graph); } } if (GraalOptions.OptTailDuplication) { new TailDuplicationPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + new CanonicalizerPhase(runtime, assumptions).apply(graph); } } if (GraalOptions.PartialEscapeAnalysis && !plan.isPhaseDisabled(PartialEscapeAnalysisPhase.class)) { - new PartialEscapeAnalysisPhase(target, runtime, assumptions, true).apply(graph); + new PartialEscapeAnalysisPhase(runtime, assumptions, true).apply(graph); } new LockEliminationPhase().apply(graph); @@ -169,7 +154,7 @@ new RemoveValueProxyPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + new CanonicalizerPhase(runtime, assumptions).apply(graph); } new LoweringPhase(target, runtime, assumptions).apply(graph); @@ -181,7 +166,7 @@ if (GraalOptions.OptFloatingReads) { int mark = graph.getMark(); new FloatingReadPhase().apply(graph); - new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph); + new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph); if (GraalOptions.OptReadElimination) { new ReadEliminationPhase().apply(graph); } @@ -189,15 +174,15 @@ new RemoveValueProxyPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + new CanonicalizerPhase(runtime, assumptions).apply(graph); } if (GraalOptions.OptEliminatePartiallyRedundantGuards) { new EliminatePartiallyRedundantGuardsPhase(false, true).apply(graph); } - if (GraalOptions.CheckCastElimination && GraalOptions.OptCanonicalizer) { - new IterativeConditionalEliminationPhase(target, runtime, assumptions).apply(graph); + if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) { + new IterativeConditionalEliminationPhase(runtime, assumptions).apply(graph); } if (GraalOptions.OptEliminatePartiallyRedundantGuards) { @@ -240,8 +225,8 @@ } - public FrameMap emitLIR(final LIR lir, StructuredGraph graph, final ResolvedJavaMethod method) { - final FrameMap frameMap = backend.newFrameMap(runtime.lookupRegisterConfig(method)); + public static FrameMap emitLIR(Backend backend, final TargetDescription target, final LIR lir, StructuredGraph graph, final ResolvedJavaMethod method) { + final FrameMap frameMap = backend.newFrameMap(); final LIRGenerator lirGenerator = backend.newLIRGenerator(graph, frameMap, method, lir); Debug.scope("LIRGen", lirGenerator, new Runnable() { @@ -275,7 +260,7 @@ return frameMap; } - public CompilationResult emitCode(long[] leafGraphIds, Assumptions assumptions, ResolvedJavaMethod method, LIR lir, FrameMap frameMap) { + public static CompilationResult emitCode(Backend backend, long[] leafGraphIds, Assumptions assumptions, ResolvedJavaMethod method, LIR lir, FrameMap frameMap) { TargetMethodAssembler tasm = backend.newAssembler(frameMap, lir); backend.emitCode(tasm, method, lir); CompilationResult result = tasm.finishTargetMethod(method, false);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Mar 04 10:00:49 2013 +0100 @@ -90,6 +90,16 @@ */ private final ArrayList<StackSlot> lockDataSlots; + /** + * Checks whether the supplied constant can be used without loading it into a register for store + * operations, i.e., on the right hand side of a memory access. + * + * @param c The constant to check. + * @return True if the constant can be used directly, false if the constant needs to be in a + * register. + */ + public abstract boolean canStoreConstant(Constant c); + public LIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { this.graph = graph; this.runtime = runtime; @@ -151,7 +161,6 @@ public Variable newVariable(Kind kind) { Kind stackKind = kind.getStackKind(); switch (stackKind) { - case Jsr: case Int: case Long: case Object: @@ -184,6 +193,14 @@ @Override public abstract Variable emitMove(Value input); + public AllocatableValue asAllocatable(Value value) { + if (isAllocatableValue(value)) { + return asAllocatableValue(value); + } else { + return emitMove(value); + } + } + public Variable load(Value value) { if (!isVariable(value)) { return emitMove(value); @@ -198,18 +215,6 @@ return value; } - public Value loadForStore(Value value, Kind storeKind) { - if (isConstant(value) && canStoreConstant((Constant) value)) { - return value; - } - if (storeKind == Kind.Byte || storeKind == Kind.Boolean) { - Variable tempVar = new Variable(value.getKind(), lir.nextVariable(), Register.RegisterFlag.Byte); - emitMove(value, tempVar); - return tempVar; - } - return load(value); - } - protected LabelRef getLIRBlock(FixedNode b) { Block result = lir.cfg.blockFor(b); int suxIndex = currentBlock.getSuccessors().indexOf(result); @@ -354,7 +359,6 @@ if (nextInstr instanceof Access) { Access access = (Access) nextInstr; if (isNullNode.object() == access.object() && canBeNullCheck(access.location())) { - // TTY.println("implicit null check"); access.setNullCheck(true); continue; } @@ -527,7 +531,7 @@ Value operand = Value.ILLEGAL; if (x.result() != null) { operand = resultOperandFor(x.result().kind()); - emitMove(operand(x.result()), operand); + emitMove(operand, operand(x.result())); } emitReturn(operand); } @@ -749,7 +753,7 @@ for (ValueNode arg : arguments) { if (arg != null) { Value operand = toStackKind(cc.getArgument(j)); - emitMove(operand(arg), operand); + emitMove(operand, operand(arg)); result[j] = operand; j++; } else { @@ -772,7 +776,7 @@ for (int i = 0; i < args.length; i++) { Value arg = args[i]; Value loc = cc.getArgument(i); - emitMove(arg, loc); + emitMove(loc, arg); argLocations[i] = loc; } emitCall(callTarget, cc.getReturn(), argLocations, cc.getTemporaries(), Constant.forLong(0), info);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java Mon Mar 04 10:00:49 2013 +0100 @@ -187,7 +187,7 @@ private void emitMove(Value src, Value dest) { assert isLegal(src); assert isLegal(dest); - gen.emitMove(src, dest); + gen.emitMove(dest, src); } // Traverse assignment graph in depth first order and generate moves in post order
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Mon Mar 04 10:00:49 2013 +0100 @@ -28,7 +28,6 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; /** * The {@code Backend} class represents a compiler backend for Graal. @@ -47,8 +46,8 @@ return runtime; } - public FrameMap newFrameMap(RegisterConfig registerConfig) { - return new FrameMap(runtime, target, registerConfig); + public FrameMap newFrameMap() { + return new FrameMap(runtime, target, runtime.lookupRegisterConfig()); } public abstract LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir); @@ -56,30 +55,6 @@ public abstract TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir); /** - * Emits code to do stack overflow checking. - * - * @param afterFrameInit specifies if the stack pointer has already been adjusted to allocate - * the current frame - */ - protected static void emitStackOverflowCheck(TargetMethodAssembler tasm, boolean afterFrameInit) { - if (GraalOptions.StackShadowPages > 0) { - int frameSize = tasm.frameMap.frameSize(); - if (frameSize > 0) { - int lastFramePage = frameSize / tasm.target.pageSize; - // emit multiple stack bangs for methods with frames larger than a page - for (int i = 0; i <= lastFramePage; i++) { - int disp = (i + GraalOptions.StackShadowPages) * tasm.target.pageSize; - if (afterFrameInit) { - disp -= frameSize; - } - tasm.blockComment("[stack overflow check]"); - tasm.asm.bangStack(disp); - } - } - } - } - - /** * Emits the code for a given method. This includes any architecture/runtime specific * prefix/suffix. A prefix typically contains the code for setting up the frame, spilling * callee-save registers, stack overflow checking, handling multiple entry points etc. A suffix
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Mon Mar 04 10:00:49 2013 +0100 @@ -72,6 +72,10 @@ assert !isNew(node) : "this node was added to the graph after creating the node map : " + node; } + public void clear() { + Arrays.fill(values, null); + } + public Iterable<Entry<Node, T>> entries() { return new Iterable<Entry<Node, T>>() {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java Mon Mar 04 10:00:49 2013 +0100 @@ -72,7 +72,7 @@ private final InvokeKind invokeKind; - AMD64DirectCallOp(Object target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, LIR lir) { + AMD64DirectCallOp(InvokeTarget target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, LIR lir) { super(target, result, parameters, temps, state); this.invokeKind = invokeKind;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Mon Mar 04 10:00:49 2013 +0100 @@ -29,8 +29,11 @@ import java.lang.reflect.*; +import sun.misc.*; + import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; @@ -55,6 +58,11 @@ */ public class AMD64HotSpotBackend extends HotSpotBackend { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + public static final Descriptor EXCEPTION_HANDLER = new Descriptor("exceptionHandler", true, void.class); + public static final Descriptor DEOPT_HANDLER = new Descriptor("deoptHandler", true, void.class); + public static final Descriptor IC_MISS_HANDLER = new Descriptor("icMissHandler", true, void.class); + public AMD64HotSpotBackend(HotSpotRuntime runtime, TargetDescription target) { super(runtime, target); } @@ -104,11 +112,9 @@ public void visitExceptionObject(ExceptionObjectNode x) { HotSpotVMConfig config = runtime().config; RegisterValue thread = runtime().threadRegister().asValue(); - Address exceptionAddress = new Address(Kind.Object, thread, config.threadExceptionOopOffset); - Address pcAddress = new Address(Kind.Long, thread, config.threadExceptionPcOffset); - Value exception = emitLoad(exceptionAddress, false); - emitStore(exceptionAddress, Constant.NULL_OBJECT, false); - emitStore(pcAddress, Constant.LONG_0, false); + Value exception = emitLoad(Kind.Object, thread, config.threadExceptionOopOffset, Value.ILLEGAL, 0, false); + emitStore(Kind.Object, thread, config.threadExceptionOopOffset, Value.ILLEGAL, 0, Constant.NULL_OBJECT, false); + emitStore(Kind.Long, thread, config.threadExceptionPcOffset, Value.ILLEGAL, 0, Constant.LONG_0, false); setResult(x, exception); } @@ -122,22 +128,22 @@ Variable newVal = load(operand(x.newValue())); int disp = 0; - Address address; + AMD64Address address; Value index = operand(x.offset()); if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) { assert !runtime.needsDataPatch(asConstant(index)); disp += (int) ValueUtil.asConstant(index).asLong(); - address = new Address(kind, load(operand(x.object())), disp); + address = new AMD64Address(kind, load(operand(x.object())), disp); } else { - address = new Address(kind, load(operand(x.object())), load(index), Address.Scale.Times1, disp); + address = new AMD64Address(kind, load(operand(x.object())), load(index), AMD64Address.Scale.Times1, disp); } RegisterValue rax = AMD64.rax.asValue(kind); - emitMove(expected, rax); + emitMove(rax, expected); append(new CompareAndSwapOp(rax, address, rax, newVal)); Variable result = newVariable(x.kind()); - emitMove(rax, result); + emitMove(result, rax); setResult(x, result); } @@ -155,13 +161,39 @@ @Override protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { Value metaspaceMethod = AMD64.rbx.asValue(); - emitMove(operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()), metaspaceMethod); + emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod())); Value targetAddress = AMD64.rax.asValue(); - emitMove(operand(callTarget.computedAddress()), targetAddress); + emitMove(targetAddress, operand(callTarget.computedAddress())); append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState)); } } + /** + * Emits code to do stack overflow checking. + * + * @param afterFrameInit specifies if the stack pointer has already been adjusted to allocate + * the current frame + */ + protected static void emitStackOverflowCheck(TargetMethodAssembler tasm, boolean afterFrameInit) { + if (GraalOptions.StackShadowPages > 0) { + + AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm; + int frameSize = tasm.frameMap.frameSize(); + if (frameSize > 0) { + int lastFramePage = frameSize / unsafe.pageSize(); + // emit multiple stack bangs for methods with frames larger than a page + for (int i = 0; i <= lastFramePage; i++) { + int disp = (i + GraalOptions.StackShadowPages) * unsafe.pageSize(); + if (afterFrameInit) { + disp -= frameSize; + } + tasm.blockComment("[stack overflow check]"); + asm.movq(new AMD64Address(asm.target.wordKind, AMD64.RSP, -disp), AMD64.rax); + } + } + } + } + class HotSpotFrameContext implements FrameContext { @Override @@ -177,7 +209,7 @@ if (GraalOptions.ZapStackOnMethodEntry) { final int intSize = 4; for (int i = 0; i < frameSize / intSize; ++i) { - asm.movl(new Address(Kind.Int, rsp.asValue(), i * intSize), 0xC1C1C1C1); + asm.movl(new AMD64Address(Kind.Int, rsp.asValue(), i * intSize), 0xC1C1C1C1); } } CalleeSaveLayout csl = frameMap.registerConfig.getCalleeSaveLayout(); @@ -196,7 +228,7 @@ RegisterConfig regConfig = tasm.frameMap.registerConfig; if (csl != null && csl.size != 0) { - tasm.targetMethod.setRegisterRestoreEpilogueOffset(asm.codeBuffer.position()); + tasm.compilationResult.setRegisterRestoreEpilogueOffset(asm.codeBuffer.position()); // saved all registers, restore all registers int frameToCSA = tasm.frameMap.offsetToCalleeSaveArea(); asm.restore(csl, frameToCSA); @@ -213,16 +245,16 @@ // detects this case - see the definition of frame::should_be_deoptimized() Register scratch = regConfig.getScratchRegister(); - int offset = SafepointPollOffset % target.pageSize; + int offset = SafepointPollOffset % unsafe.pageSize(); if (config.isPollingPageFar) { asm.movq(scratch, config.safepointPollingAddress + offset); tasm.recordMark(Marks.MARK_POLL_RETURN_FAR); - asm.movq(scratch, new Address(tasm.target.wordKind, scratch.asValue())); + asm.movq(scratch, new AMD64Address(tasm.target.wordKind, scratch.asValue())); } else { tasm.recordMark(Marks.MARK_POLL_RETURN_NEAR); // The C++ code transforms the polling page offset into an RIP displacement // to the real address at that offset in the polling page. - asm.movq(scratch, new Address(tasm.target.wordKind, rip.asValue(), offset)); + asm.movq(scratch, new AMD64Address(tasm.target.wordKind, rip.asValue(), offset)); } } } @@ -242,7 +274,7 @@ HotSpotFrameContext frameContext = omitFrame ? null : new HotSpotFrameContext(); TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, lir.stubs); tasm.setFrameSize(frameMap.frameSize()); - tasm.targetMethod.setCustomStackAreaOffset(frameMap.offsetToCustomArea()); + tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetToCustomArea()); return tasm; } @@ -263,10 +295,10 @@ Register inlineCacheKlass = rax; // see definition of IC_Klass in // c1_LIRAssembler_x86.cpp Register receiver = asRegister(cc.getArgument(0)); - Address src = new Address(target.wordKind, receiver.asValue(), config.hubOffset); + AMD64Address src = new AMD64Address(target.wordKind, receiver.asValue(), config.hubOffset); asm.cmpq(inlineCacheKlass, src); - asm.jcc(ConditionFlag.notEqual, unverifiedStub); + asm.jcc(ConditionFlag.NotEqual, unverifiedStub); } asm.align(config.codeEntryAlignment); @@ -279,11 +311,11 @@ boolean frameOmitted = tasm.frameContext == null; if (!frameOmitted) { tasm.recordMark(Marks.MARK_EXCEPTION_HANDLER_ENTRY); - AMD64Call.directCall(tasm, asm, config.handleExceptionStub, null); + AMD64Call.directCall(tasm, asm, runtime().lookupRuntimeCall(EXCEPTION_HANDLER), null); AMD64Call.shouldNotReachHere(tasm, asm); tasm.recordMark(Marks.MARK_DEOPT_HANDLER_ENTRY); - AMD64Call.directCall(tasm, asm, config.handleDeoptStub, null); + AMD64Call.directCall(tasm, asm, runtime().lookupRuntimeCall(DEOPT_HANDLER), null); AMD64Call.shouldNotReachHere(tasm, asm); } else { // No need to emit the stubs for entries back into the method since @@ -293,7 +325,7 @@ if (unverifiedStub != null) { asm.bind(unverifiedStub); - AMD64Call.directJmp(tasm, asm, config.inlineCacheMissStub); + AMD64Call.directJmp(tasm, asm, runtime().lookupRuntimeCall(IC_MISS_HANDLER)); } for (int i = 0; i < GraalOptions.MethodEndBreakpointGuards; ++i) { @@ -301,4 +333,5 @@ } } + }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java Mon Mar 04 10:00:49 2013 +0100 @@ -47,11 +47,9 @@ @Override protected TargetDescription createTarget() { - final int wordSize = 8; final int stackFrameAlignment = 16; - final int stackBias = 0; final int implicitNullCheckLimit = 4096; - return new TargetDescription(new AMD64(), true, stackFrameAlignment, stackBias, implicitNullCheckLimit, config.vmPageSize, wordSize, true, true); + return new TargetDescription(new AMD64(), true, stackFrameAlignment, implicitNullCheckLimit, true); } @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Mon Mar 04 10:00:49 2013 +0100 @@ -177,6 +177,17 @@ /* arg3: r */ word, /* arg4: inLength */ Kind.Int)); + addRuntimeCall(AMD64HotSpotBackend.EXCEPTION_HANDLER, config.handleExceptionStub, + /* temps */ null, + /* ret */ ret(Kind.Void)); + + addRuntimeCall(AMD64HotSpotBackend.DEOPT_HANDLER, config.handleDeoptStub, + /* temps */ null, + /* ret */ ret(Kind.Void)); + + addRuntimeCall(AMD64HotSpotBackend.IC_MISS_HANDLER, config.inlineCacheMissStub, + /* temps */ null, + /* ret */ ret(Kind.Void)); // @formatter:on }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Mon Mar 04 10:00:49 2013 +0100 @@ -52,7 +52,7 @@ @Use({REG}) protected Value metaspaceMethod; - AMD64IndirectCallOp(Object targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state) { + AMD64IndirectCallOp(InvokeTarget targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state) { super(targetMethod, result, parameters, temps, targetAddress, state); this.metaspaceMethod = metaspaceMethod; }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java Mon Mar 04 10:00:49 2013 +0100 @@ -24,7 +24,9 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.phases.GraalOptions.*; +import sun.misc.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.*; @@ -40,6 +42,8 @@ @Opcode("SAFEPOINT") public class AMD64SafepointOp extends AMD64LIRInstruction { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + @State protected LIRFrameState state; private final HotSpotVMConfig config; @@ -53,18 +57,18 @@ public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler asm) { Register scratch = tasm.frameMap.registerConfig.getScratchRegister(); int pos = asm.codeBuffer.position(); - int offset = SafepointPollOffset % tasm.target.pageSize; + int offset = SafepointPollOffset % unsafe.pageSize(); if (config.isPollingPageFar) { asm.movq(scratch, config.safepointPollingAddress + offset); tasm.recordMark(Marks.MARK_POLL_FAR); tasm.recordSafepoint(pos, state); - asm.movq(scratch, new Address(tasm.target.wordKind, scratch.asValue())); + asm.movq(scratch, new AMD64Address(tasm.target.wordKind, scratch.asValue())); } else { tasm.recordMark(Marks.MARK_POLL_NEAR); tasm.recordSafepoint(pos, state); // The C++ code transforms the polling page offset into an RIP displacement // to the real address at that offset in the polling page. - asm.movq(scratch, new Address(tasm.target.wordKind, rip.asValue(), offset)); + asm.movq(scratch, new AMD64Address(tasm.target.wordKind, rip.asValue(), offset)); } } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Mar 04 10:00:49 2013 +0100 @@ -29,6 +29,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; import com.oracle.graal.graph.*; @@ -143,10 +144,9 @@ } else { // Compiling an intrinsic graph - must clone the graph graph = graph.copy(); - // System.out.println("compiling intrinsic " + method); } InlinedBytecodes.add(method.getCodeSize()); - return graalRuntime.getCompiler().compileMethod(method, graph, graalRuntime.getCache(), plan, optimisticOpts); + return GraalCompiler.compileMethod(graalRuntime.getRuntime(), graalRuntime.getBackend(), graalRuntime.getTarget(), method, graph, graalRuntime.getCache(), plan, optimisticOpts); } }); } finally {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon Mar 04 10:00:49 2013 +0100 @@ -31,6 +31,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.logging.*; import com.oracle.graal.hotspot.meta.*; @@ -116,6 +117,7 @@ private volatile HotSpotGraphCache cache; protected final HotSpotVMConfig config; + private final HotSpotBackend backend; protected HotSpotGraalRuntime() { CompilerToVM toVM = new CompilerToVMImpl(); @@ -139,9 +141,9 @@ runtime = createRuntime(); - HotSpotBackend backend = createBackend(); + backend = createBackend(); GraalOptions.StackShadowPages = config.stackShadowPages; - compiler = new GraalCompiler(getRuntime(), getTarget(), backend); + compiler = new GraalCompiler(); if (GraalOptions.CacheGraphs) { cache = new HotSpotGraphCache(); } @@ -211,8 +213,6 @@ break; case Int: return impl.typeInt; - case Jsr: - break; case Long: return impl.typeLong; case Object: @@ -264,9 +264,19 @@ if (clazz == DisassemblerProvider.class || clazz == BytecodeDisassemblerProvider.class) { return (T) getRuntime(); } + if (clazz == HotSpotRuntime.class) { + return (T) runtime; + } if (clazz == GraalCompiler.class) { return (T) getCompiler(); } + if (clazz == Backend.class) { + return (T) getBackend(); + } return null; } + + public HotSpotBackend getBackend() { + return backend; + } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java Mon Mar 04 10:00:49 2013 +0100 @@ -30,7 +30,7 @@ /** * The details required to link a HotSpot runtime or stub call. */ -public class HotSpotRuntimeCallTarget implements RuntimeCallTarget { +public class HotSpotRuntimeCallTarget implements RuntimeCallTarget, InvokeTarget { /** * The descriptor of the stub. This is for informational purposes only.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Mar 04 10:00:49 2013 +0100 @@ -44,7 +44,6 @@ public boolean useAESIntrinsics; // offsets, ... - public int vmPageSize; public int stackShadowPages; /** @@ -362,7 +361,6 @@ public int deoptActionMakeNotCompilable; public void check() { - assert vmPageSize >= 16; assert codeEntryAlignment > 0; assert stackShadowPages > 0; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon Mar 04 10:00:49 2013 +0100 @@ -36,7 +36,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; import com.oracle.graal.hotspot.*; @@ -143,10 +142,9 @@ } // Install intrinsics. - GraalCompiler compiler = graalRuntime.getCompiler(); - final HotSpotRuntime runtime = (HotSpotRuntime) compiler.runtime; + final HotSpotRuntime runtime = graalRuntime.getCapability(HotSpotRuntime.class); if (GraalOptions.Intrinsify) { - Debug.scope("InstallSnippets", new Object[]{new DebugDumpScope("InstallSnippets"), compiler}, new Runnable() { + Debug.scope("InstallSnippets", new Object[]{new DebugDumpScope("InstallSnippets")}, new Runnable() { @Override public void run() { @@ -155,7 +153,7 @@ Assumptions assumptions = new Assumptions(false); SnippetInstaller installer = new HotSpotSnippetInstaller(runtime, assumptions, runtime.getGraalRuntime().getTarget()); GraalIntrinsics.installIntrinsics(installer); - runtime.installSnippets(installer, assumptions); + runtime.installSnippets(graalRuntime.getBackend(), installer, assumptions); } });
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Mon Mar 04 10:00:49 2013 +0100 @@ -86,6 +86,9 @@ @Override public byte[] getCode() { + if (codeSize == 0) { + return null; + } if (code == null) { code = HotSpotGraalRuntime.getInstance().getCompilerToVM().initializeBytecode(metaspaceMethod, new byte[codeSize]); assert code.length == codeSize : "expected: " + codeSize + ", actual: " + code.length;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Mon Mar 04 10:00:49 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.lang.annotation.*; import java.lang.reflect.*; +import java.net.*; import java.util.*; import com.oracle.graal.api.meta.*; @@ -497,4 +498,26 @@ } return null; } + + @Override + public URL getClassFilePath() { + Class<?> cls = mirror(); + return cls.getResource(MetaUtil.getSimpleName(cls, true).replace('.', '$') + ".class"); + } + + @Override + public boolean isLocal() { + return mirror().isLocalClass(); + } + + @Override + public boolean isMember() { + return mirror().isMemberClass(); + } + + @Override + public ResolvedJavaType getEnclosingType() { + final Class<?> encl = mirror().getEnclosingClass(); + return encl == null ? null : fromClass(encl); + } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Mon Mar 04 10:00:49 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ import java.lang.annotation.*; import java.lang.reflect.*; +import java.net.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; @@ -189,4 +190,24 @@ public Class<?> mirror() { return javaMirror; } + + @Override + public URL getClassFilePath() { + return null; + } + + @Override + public boolean isLocal() { + return false; + } + + @Override + public boolean isMember() { + return false; + } + + @Override + public ResolvedJavaType getEnclosingType() { + return null; + } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Mar 04 10:00:49 2013 +0100 @@ -51,6 +51,7 @@ import com.oracle.graal.api.code.Register.RegisterFlag; import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; @@ -328,7 +329,7 @@ protected abstract RegisterConfig createRegisterConfig(boolean globalStubConfig); - public void installSnippets(SnippetInstaller installer, Assumptions assumptions) { + public void installSnippets(Backend backend, SnippetInstaller installer, Assumptions assumptions) { if (GraalOptions.IntrinsifyObjectMethods) { installer.installSubstitutions(ObjectSubstitutions.class); } @@ -370,8 +371,8 @@ newInstanceStub = new NewInstanceStub(this, assumptions, graalRuntime.getTarget()); newArrayStub = new NewArrayStub(this, assumptions, graalRuntime.getTarget()); - newInstanceStub.install(graalRuntime.getCompiler()); - newArrayStub.install(graalRuntime.getCompiler()); + newInstanceStub.install(backend, graalRuntime.getCompiler()); + newArrayStub.install(backend, graalRuntime.getCompiler()); } public HotSpotGraalRuntime getGraalRuntime() { @@ -504,7 +505,7 @@ } @Override - public RegisterConfig lookupRegisterConfig(ResolvedJavaMethod method) { + public RegisterConfig lookupRegisterConfig() { return regConfig; } @@ -627,7 +628,7 @@ graph.addAfterFixed(cas, writeBarrier); } else { // This may be an array store so use an array write barrier - LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, false); + LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1); graph.addAfterFixed(cas, graph.add(new ArrayWriteBarrier(cas.object(), location))); } } @@ -679,7 +680,7 @@ } else if (n instanceof UnsafeLoadNode) { UnsafeLoadNode load = (UnsafeLoadNode) n; assert load.kind() != Kind.Illegal; - IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, false); + IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1); ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp())); // An unsafe read must not floating outside its block as may float above an explicit // null check on its object. @@ -687,7 +688,7 @@ graph.replaceFixedWithFixed(load, memoryRead); } else if (n instanceof UnsafeStoreNode) { UnsafeStoreNode store = (UnsafeStoreNode) n; - IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, false); + IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.accessKind(), store.displacement(), store.offset(), graph, 1); ValueNode object = store.object(); WriteNode write = graph.add(new WriteNode(object, store.value(), location)); write.setStateAfter(store.stateAfter()); @@ -751,8 +752,9 @@ } } - private static IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) { - return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, true); + private IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) { + int scale = this.graalRuntime.getTarget().sizeInBytes(elementKind); + return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, getArrayBaseOffset(elementKind), index, graph, scale); } private SafeReadNode safeReadArrayLength(ValueNode array) { @@ -776,13 +778,6 @@ return HotSpotResolvedObjectType.fromClass(clazz); } - public Object lookupCallTarget(Object callTarget) { - if (callTarget instanceof HotSpotRuntimeCallTarget) { - return ((HotSpotRuntimeCallTarget) callTarget).getAddress(); - } - return callTarget; - } - /** * Gets the stub corresponding to a given method. * @@ -958,7 +953,7 @@ long nmethod = ((HotSpotInstalledCode) code).nmethod; return graalRuntime.getCompilerToVM().disassembleNMethod(nmethod); } - return ""; + return null; } public String disassemble(ResolvedJavaMethod method) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayWriteBarrier.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayWriteBarrier.java Mon Mar 04 10:00:49 2013 +0100 @@ -47,7 +47,7 @@ @Override public void generate(LIRGeneratorTool gen) { - Value addr = gen.emitLea(gen.makeAddress(location(), object())); + Value addr = location().generateLea(gen, object()); generateBarrier(addr, gen); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -52,6 +52,11 @@ } @Override + public Object getLocationIdentity() { + return LocationNode.ANY_LOCATION; + } + + @Override public void generate(LIRGenerator gen) { gen.lock(); StackSlot lockData = gen.peekLock();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentThread.java Mon Mar 04 10:00:49 2013 +0100 @@ -42,7 +42,7 @@ public void generate(LIRGeneratorTool gen) { HotSpotGraalRuntime runtime = HotSpotGraalRuntime.getInstance(); Register thread = runtime.getRuntime().threadRegister(); - gen.setResult(this, gen.emitLoad(new Address(Kind.Object, thread.asValue(gen.target().wordKind), runtime.getConfig().threadObjectOffset), false)); + gen.setResult(this, gen.emitLoad(Kind.Object, thread.asValue(gen.target().wordKind), runtime.getConfig().threadObjectOffset, Value.ILLEGAL, 0, false)); } @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -32,8 +32,8 @@ /** * A special purpose store node that differs from {@link CompareAndSwapNode} in that it is not a - * {@link StateSplit} and it {@linkplain #compareAndSwap(Object, long, Word, Word) returns} either - * the expected value or the compared against value instead of a boolean. + * {@link StateSplit} and it {@linkplain #compareAndSwap(Object, long, Word, Word, Object)} returns + * either the expected value or the compared against value instead of a boolean. */ public class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRGenLowerable, MemoryCheckpoint { @@ -42,17 +42,15 @@ @Input private ValueNode expectedValue; @Input private ValueNode newValue; - public DirectCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue) { + private final Object locationIdentity; + + public DirectCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, Object locationIdentity) { super(expected.stamp()); this.object = object; this.offset = offset; this.expectedValue = expected; this.newValue = newValue; - } - - @Override - public void generate(LIRGenerator gen) { - ((HotSpotLIRGenerator) gen).visitDirectCompareAndSwap(this); + this.locationIdentity = locationIdentity; } public ValueNode object() { @@ -71,6 +69,16 @@ return newValue; } + @Override + public Object getLocationIdentity() { + return locationIdentity; + } + + @Override + public void generate(LIRGenerator gen) { + ((HotSpotLIRGenerator) gen).visitDirectCompareAndSwap(this); + } + /** * Compares an expected value with the actual value in a location denoted by an object and a * given offset. Iff they are same, {@code newValue} is placed into the location and the @@ -84,5 +92,5 @@ * @return either {@code expectedValue} or the actual value */ @NodeIntrinsic - public static native Word compareAndSwap(Object object, long offset, Word expectedValue, Word newValue); + public static native Word compareAndSwap(Object object, long offset, Word expectedValue, Word newValue, @ConstantNodeParameter Object locationIdentity); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -44,6 +44,11 @@ } @Override + public Object getLocationIdentity() { + return LocationNode.ANY_LOCATION; + } + + @Override public void generate(LIRGenerator gen) { gen.unlock(); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/FieldWriteBarrier.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/FieldWriteBarrier.java Mon Mar 04 10:00:49 2013 +0100 @@ -41,7 +41,7 @@ @Override public void generate(LIRGeneratorTool generator) { Value obj = generator.newVariable(generator.target().wordKind); - generator.emitMove(generator.operand(object()), obj); + generator.emitMove(obj, generator.operand(object())); generateBarrier(obj, generator); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -47,7 +47,7 @@ @Override public void generate(LIRGeneratorTool gen) { Value obj = gen.newVariable(gen.target().wordKind); - gen.emitMove(gen.operand(object), obj); + gen.emitMove(obj, gen.operand(object)); gen.setResult(this, obj); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotDirectCallTargetNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -34,7 +34,7 @@ private final InvokeKind invokeKind; - public HotSpotDirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, Type callType, InvokeKind invokeKind) { + public HotSpotDirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, InvokeTarget target, Type callType, InvokeKind invokeKind) { super(arguments, returnStamp, signature, target, callType); this.invokeKind = invokeKind; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotIndirectCallTargetNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -33,7 +33,7 @@ @Input private ValueNode metaspaceMethod; - public HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, Type callType) { + public HotSpotIndirectCallTargetNode(ValueNode metaspaceMethod, ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, InvokeTarget target, Type callType) { super(computedAddress, arguments, returnStamp, signature, target, callType); this.metaspaceMethod = metaspaceMethod; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/RegisterNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/RegisterNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -54,7 +54,7 @@ // The register allocator would prefer us not to tie up an allocatable // register for the complete lifetime of this node. result = generator.newVariable(kind()); - generator.emitMove(register.asValue(kind()), result); + generator.emitMove(result, register.asValue(kind())); } else { result = register.asValue(kind()); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -69,7 +69,7 @@ parameters.add(frameState.localAt(slot)); } Value[] args = gen.visitInvokeArguments(cc, parameters); - Value entry = gen.emitLoad(new Address(Kind.Long, gen.operand(target), config.nmethodEntryOffset), false); + Value entry = gen.emitLoad(Kind.Long, gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0, false); HotSpotLIRGenerator hsgen = (HotSpotLIRGenerator) gen; hsgen.emitTailcall(args, entry); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Mon Mar 04 10:00:49 2013 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.nodes; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; @@ -46,6 +45,6 @@ } else { base = gen.emitAdd(base, Constant.forLong(config.cardtableStartAddress)); } - gen.emitStore(new Address(Kind.Boolean, base, displacement), Constant.FALSE, false); + gen.emitStore(Kind.Boolean, base, displacement, Value.ILLEGAL, 0, Constant.FALSE, false); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -26,14 +26,16 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.RuntimeCallTarget.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.*; import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.java.*; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; @@ -43,6 +45,27 @@ public static final Descriptor OSR_MIGRATION_END = new Descriptor("OSR_migration_end", true, void.class, long.class); + public class OSREntryProxyNode extends FloatingNode implements LIRLowerable { + + @Input private ValueNode object; + @Input(notDataflow = true) private final RuntimeCallNode anchor; + + public OSREntryProxyNode(ValueNode object, RuntimeCallNode anchor) { + super(object.stamp()); + this.object = object; + this.anchor = anchor; + } + + public RuntimeCallNode getAnchor() { + return anchor; + } + + @Override + public void generate(LIRGeneratorTool generator) { + generator.setResult(this, generator.operand(object)); + } + } + @Override protected void run(StructuredGraph graph) { if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) { @@ -81,7 +104,7 @@ LoopTransformations.peel(osrLoop); for (Node usage : osr.usages().snapshot()) { - ValueProxyNode proxy = (ValueProxyNode) usage; + ProxyNode proxy = (ProxyNode) usage; proxy.replaceAndDelete(proxy.value()); } FixedNode next = osr.next(); @@ -108,15 +131,17 @@ start.setStateAfter(null); GraphUtil.killWithUnusedFloatingInputs(oldStartState); + // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block) int localsOffset = (graph.method().getMaxLocals() - 1) * 8; for (int i = 0; i < osrState.localsSize(); i++) { ValueNode value = osrState.localAt(i); if (value != null) { - ValueProxyNode proxy = (ValueProxyNode) value; - int size = (value.kind() == Kind.Long || value.kind() == Kind.Double) ? 2 : 1; + ProxyNode proxy = (ProxyNode) value; + int size = FrameStateBuilder.stackSlots(value.kind()); int offset = localsOffset - (i + size - 1) * 8; UnsafeLoadNode load = graph.add(new UnsafeLoadNode(buffer, offset, ConstantNode.forInt(0, graph), value.kind())); - proxy.replaceAndDelete(load); + OSREntryProxyNode newProxy = graph.add(new OSREntryProxyNode(load, migrationEnd)); + proxy.replaceAndDelete(newProxy); graph.addBeforeFixed(migrationEnd, load); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java Mon Mar 04 10:00:49 2013 +0100 @@ -70,7 +70,7 @@ } private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) { - Word kAddr = Word.fromObject(rcvr).readWord(Word.unsigned(kOffset)).add(arrayBaseOffset(Kind.Byte)); + Word kAddr = Word.fromObject(rcvr).readWord(Word.unsigned(kOffset), UNKNOWN_LOCATION).add(arrayBaseOffset(Kind.Byte)); Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); if (encrypt) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopyNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopyNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.snippets.nodes.*; @@ -59,21 +60,19 @@ return arguments.get(4); } - private ResolvedJavaMethod selectSnippet(LoweringTool tool) { + private StructuredGraph selectSnippet(LoweringTool tool) { ResolvedJavaType srcType = getSource().objectStamp().type(); ResolvedJavaType destType = getDestination().objectStamp().type(); - if (srcType != null && srcType.isArray() && destType != null && destType.isArray()) { - Kind componentKind = srcType.getComponentType().getKind(); - if (componentKind != Kind.Object) { - if (srcType.getComponentType() == destType.getComponentType()) { - return tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind)); - } - } else if (destType.getComponentType().isAssignableFrom(srcType.getComponentType()) && getDestination().objectStamp().isExactType()) { - return tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(Kind.Object)); - } + if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) { + return null; } - return null; + if (!destType.getComponentType().isAssignableFrom(srcType.getComponentType()) || !getDestination().objectStamp().isExactType()) { + return null; + } + Kind componentKind = srcType.getComponentType().getKind(); + ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind)); + return (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class); } private static void unrollFixedLengthLoop(StructuredGraph snippetGraph, int length, LoweringTool tool) { @@ -83,32 +82,48 @@ } // the canonicalization before loop unrolling is needed to propagate the length into // additions, etc. - new CanonicalizerPhase(tool.getTarget(), tool.getRuntime(), tool.assumptions()).apply(snippetGraph); + new CanonicalizerPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph); new LoopFullUnrollPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph); - new CanonicalizerPhase(tool.getTarget(), tool.getRuntime(), tool.assumptions()).apply(snippetGraph); + new CanonicalizerPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph); + } + + private static void replaceSnippetInvokes(StructuredGraph snippetGraph, ResolvedJavaMethod targetMethod, int bci) { + for (InvokeNode invoke : snippetGraph.getNodes(InvokeNode.class)) { + if (invoke.methodCallTarget().targetMethod() != targetMethod) { + throw new GraalInternalError("unexpected invoke in arraycopy snippet"); + } + if (invoke.stateAfter().bci == FrameState.INVALID_FRAMESTATE_BCI) { + InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.methodCallTarget(), bci)); + newInvoke.setStateAfter(snippetGraph.add(new FrameState(FrameState.AFTER_BCI))); + snippetGraph.replaceFixedWithFixed(invoke, newInvoke); + } else { + assert invoke.stateAfter().bci == FrameState.AFTER_BCI : invoke; + } + } } @Override - public void lower(LoweringTool tool) { - ResolvedJavaMethod snippetMethod = selectSnippet(tool); - if (snippetMethod == null) { - snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.increaseGenericCallCounterMethod); - // we will call the generic method. the generic snippet will only increase the counter, - // not call the actual method. therefore we create a second invoke here. - ((StructuredGraph) graph()).addAfterFixed(this, createInvoke()); - } - if (Debug.isLogEnabled()) { - Debug.log("%s > Intrinsify (%s)", Debug.currentScope(), snippetMethod.getSignature().getParameterType(0, snippetMethod.getDeclaringClass()).getComponentType()); + protected StructuredGraph getSnippetGraph(LoweringTool tool) { + if (!GraalOptions.IntrinsifyArrayCopy) { + return null; } - StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class); - assert snippetGraph != null : "ArrayCopySnippets should be installed"; - if (getLength().isConstant()) { - snippetGraph = snippetGraph.copy(); - unrollFixedLengthLoop(snippetGraph, getLength().asConstant().asInt(), tool); + StructuredGraph snippetGraph = selectSnippet(tool); + if (snippetGraph == null) { + ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.genericArraycopySnippet); + snippetGraph = ((StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class)).copy(); + assert snippetGraph != null : "ArrayCopySnippets should be installed"; + + replaceSnippetInvokes(snippetGraph, getTargetMethod(), getBci()); + } else { + assert snippetGraph != null : "ArrayCopySnippets should be installed"; + + if (getLength().isConstant()) { + snippetGraph = snippetGraph.copy(); + unrollFixedLengthLoop(snippetGraph, getLength().asConstant().asInt(), tool); + } } - InvokeNode invoke = replaceWithInvoke(); - InliningUtil.inline(invoke, snippetGraph, false); + return snippetGraph; } private static boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java Mon Mar 04 10:00:49 2013 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.hotspot.snippets; -import static com.oracle.graal.api.code.DeoptimizationAction.*; -import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*; @@ -33,24 +31,21 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.snippets.*; import com.oracle.graal.snippets.Snippet.ConstantParameter; -import com.oracle.graal.snippets.Snippet.Fold; import com.oracle.graal.snippets.nodes.*; +import com.oracle.graal.word.*; @SuppressWarnings("unused") public class ArrayCopySnippets implements SnippetsInterface { private static final EnumMap<Kind, Method> arraycopyMethods = new EnumMap<>(Kind.class); - public static final Method increaseGenericCallCounterMethod; + public static final Method genericArraycopySnippet; private static void addArraycopySnippetMethod(Kind kind, Class<?> arrayClass) throws NoSuchMethodException { arraycopyMethods.put(kind, ArrayCopySnippets.class.getDeclaredMethod("arraycopy", arrayClass, int.class, arrayClass, int.class, int.class)); @@ -67,7 +62,7 @@ addArraycopySnippetMethod(Kind.Float, float[].class); addArraycopySnippetMethod(Kind.Double, double[].class); addArraycopySnippetMethod(Kind.Object, Object[].class); - increaseGenericCallCounterMethod = ArrayCopySnippets.class.getDeclaredMethod("increaseGenericCallCounter", Object.class, int.class, Object.class, int.class, int.class); + genericArraycopySnippet = ArrayCopySnippets.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class); } catch (SecurityException | NoSuchMethodException e) { throw new GraalInternalError(e); } @@ -81,7 +76,9 @@ private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long); public static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter("baseKind") Kind baseKind) { - checkInputs(src, srcPos, dest, destPos, length); + checkNonNull(src); + checkNonNull(dest); + checkLimits(src, srcPos, dest, destPos, length); int header = arrayBaseOffset(baseKind); int elementSize = arrayIndexScale(baseKind); long byteLength = (long) length * elementSize; @@ -109,17 +106,24 @@ } } - public static void checkInputs(Object src, int srcPos, Object dest, int destPos, int length) { - if (src == null) { + public static void checkNonNull(Object obj) { + if (obj == null) { probability(DEOPT_PATH_PROBABILITY); checkNPECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - if (dest == null) { + } + + public static int checkArrayType(Word hub) { + int layoutHelper = readLayoutHelper(hub); + if (layoutHelper >= 0) { probability(DEOPT_PATH_PROBABILITY); - checkNPECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } + return layoutHelper; + } + + public static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length) { if (srcPos < 0) { probability(DEOPT_PATH_PROBABILITY); checkAIOOBECounter.inc(); @@ -187,7 +191,9 @@ @Snippet public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) { longCounter.inc(); - checkInputs(src, srcPos, dest, destPos, length); + checkNonNull(src); + checkNonNull(dest); + checkLimits(src, srcPos, dest, destPos, length); Kind baseKind = Kind.Long; int header = arrayBaseOffset(baseKind); long byteLength = (long) length * arrayIndexScale(baseKind); @@ -209,7 +215,9 @@ @Snippet public static void arraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) { doubleCounter.inc(); - checkInputs(src, srcPos, dest, destPos, length); + checkNonNull(src); + checkNonNull(dest); + checkLimits(src, srcPos, dest, destPos, length); Kind baseKind = Kind.Double; int header = arrayBaseOffset(baseKind); long byteLength = (long) length * arrayIndexScale(baseKind); @@ -232,7 +240,9 @@ @Snippet public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) { objectCounter.inc(); - checkInputs(src, srcPos, dest, destPos, length); + checkNonNull(src); + checkNonNull(dest); + checkLimits(src, srcPos, dest, destPos, length); final int scale = arrayIndexScale(Kind.Object); int header = arrayBaseOffset(Kind.Object); if (src == dest && srcPos < destPos) { // bad aliased case @@ -262,12 +272,67 @@ } @Snippet - public static void increaseGenericCallCounter(Object src, int srcPos, Object dest, int destPos, int length) { - if (GraalOptions.SnippetCounters) { - if (src.getClass().getComponentType().isPrimitive()) { - genericPrimitiveCallCounter.inc(); - } else { - genericObjectCallCounter.inc(); + public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) { + + // loading the hubs also checks for nullness + Word srcHub = loadHub(src); + Word destHub = loadHub(dest); + + int layoutHelper = checkArrayType(srcHub); + if (srcHub.equal(destHub) && src != dest) { + probability(FAST_PATH_PROBABILITY); + + checkLimits(src, srcPos, dest, destPos, length); + + arraycopyInnerloop(src, srcPos, dest, destPos, length, layoutHelper); + } else { + genericObjectCallCounter.inc(); + System.arraycopy(src, srcPos, dest, destPos, length); + } + } + + public static void arraycopyInnerloop(Object src, int srcPos, Object dest, int destPos, int length, int layoutHelper) { + int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); + int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); + + Word memory = (Word) Word.fromObject(src); + + Word srcOffset = (Word) Word.fromObject(src).add(headerSize).add(srcPos << log2ElementSize); + Word destOffset = (Word) Word.fromObject(dest).add(headerSize).add(destPos << log2ElementSize); + Word destStart = destOffset; + long sizeInBytes = ((long) length) << log2ElementSize; + Word destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize)); + + int nonVectorBytes = (int) (sizeInBytes % VECTOR_SIZE); + Word destNonVectorEnd = destStart.add(nonVectorBytes); + + while (destOffset.belowThan(destNonVectorEnd)) { + destOffset.writeByte(0, srcOffset.readByte(0, UNKNOWN_LOCATION), ANY_LOCATION); + destOffset = destOffset.add(1); + srcOffset = srcOffset.add(1); + } + while (destOffset.belowThan(destEnd)) { + destOffset.writeWord(0, srcOffset.readWord(0, UNKNOWN_LOCATION), ANY_LOCATION); + destOffset = destOffset.add(wordSize()); + srcOffset = srcOffset.add(wordSize()); + } + + if ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) != 0) { + genericPrimitiveCallCounter.inc(); + + } else { + probability(LIKELY_PROBABILITY); + genericObjectExactCallCounter.inc(); + + if (length > 0) { + int cardShift = cardTableShift(); + long cardStart = cardTableStart(); + Word destCardOffset = destStart.unsignedShiftRight(cardShift).add(Word.unsigned(cardStart)); + Word destCardEnd = destEnd.subtract(1).unsignedShiftRight(cardShift).add(Word.unsigned(cardStart)); + while (destCardOffset.belowOrEqual(destCardEnd)) { + DirectStoreNode.store(destCardOffset.rawValue(), false, Kind.Boolean); + destCardOffset = destCardOffset.add(1); + } } } } @@ -287,7 +352,8 @@ private static final SnippetCounter objectCounter = new SnippetCounter(counters, "Object[]", "arraycopy for Object[] arrays"); private static final SnippetCounter floatCounter = new SnippetCounter(counters, "float[]", "arraycopy for float[] arrays"); private static final SnippetCounter doubleCounter = new SnippetCounter(counters, "double[]", "arraycopy for double[] arrays"); - private static final SnippetCounter genericPrimitiveCallCounter = new SnippetCounter(counters, "genericPrimitive", "call to the generic, native arraycopy method"); + private static final SnippetCounter genericPrimitiveCallCounter = new SnippetCounter(counters, "genericPrimitive", "generic arraycopy snippet for primitive arrays"); + private static final SnippetCounter genericObjectExactCallCounter = new SnippetCounter(counters, "genericObjectExact", "generic arraycopy snippet for special object arrays"); private static final SnippetCounter genericObjectCallCounter = new SnippetCounter(counters, "genericObject", "call to the generic, native arraycopy method"); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Mon Mar 04 10:00:49 2013 +0100 @@ -108,7 +108,7 @@ isNull.inc(); } else { Word objectHub = loadHub(object); - if (objectHub.readWord(superCheckOffset).notEqual(hub)) { + if (objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub)) { probability(DEOPT_PATH_PROBABILITY); displayMiss.inc(); DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java Mon Mar 04 10:00:49 2013 +0100 @@ -66,7 +66,7 @@ @MethodSubstitution(isStatic = false) static void encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { - Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset)); + Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), UNKNOWN_LOCATION); if (getAESCryptClass().isInstance(embeddedCipher)) { crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, true); } else { @@ -75,8 +75,8 @@ } private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) { - Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset)).add(arrayBaseOffset(Kind.Byte)); - Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset)).add(arrayBaseOffset(Kind.Byte)); + Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset), UNKNOWN_LOCATION).add(arrayBaseOffset(Kind.Byte)); + Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset), UNKNOWN_LOCATION).add(arrayBaseOffset(Kind.Byte)); Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); if (encrypt) { @@ -89,7 +89,7 @@ @MethodSubstitution(isStatic = false) static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { - Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset)); + Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset), UNKNOWN_LOCATION); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { crypt(rcvr, in, inOffset, inLength, out, outOffset, embeddedCipher, false); } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java Mon Mar 04 10:00:49 2013 +0100 @@ -45,7 +45,7 @@ // Class for primitive type return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC; } else { - return klass.readInt(klassModifierFlagsOffset()); + return klass.readInt(klassModifierFlagsOffset(), FINAL_LOCATION); } } @@ -55,7 +55,7 @@ if (klass.equal(0)) { return false; } else { - int accessFlags = klass.readInt(klassAccessFlagsOffset()); + int accessFlags = klass.readInt(klassAccessFlagsOffset(), FINAL_LOCATION); return (accessFlags & Modifier.INTERFACE) != 0; } } @@ -66,8 +66,7 @@ if (klass.equal(0)) { return false; } else { - int layoutHelper = klass.readInt(klassLayoutHelperOffset()); - return (layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0; + return (readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0; } } @@ -81,17 +80,16 @@ public static Class<?> getSuperclass(final Class<?> thisObj) { Word klass = loadWordFromObject(thisObj, klassOffset()); if (klass.notEqual(0)) { - int accessFlags = klass.readInt(klassAccessFlagsOffset()); + int accessFlags = klass.readInt(klassAccessFlagsOffset(), FINAL_LOCATION); if ((accessFlags & Modifier.INTERFACE) == 0) { - int layoutHelper = klass.readInt(klassLayoutHelperOffset()); - if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) { + if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) { return Object.class; } else { - Word superKlass = klass.readWord(klassSuperKlassOffset()); + Word superKlass = klass.readWord(klassSuperKlassOffset(), FINAL_LOCATION); if (superKlass.equal(0)) { return null; } else { - return unsafeCast(superKlass.readObject(classMirrorOffset()), Class.class, true, true); + return unsafeCast(superKlass.readObject(classMirrorOffset(), FINAL_LOCATION), Class.class, true, true); } } } @@ -103,9 +101,8 @@ public static Class<?> getComponentType(final Class<?> thisObj) { Word klass = loadWordFromObject(thisObj, klassOffset()); if (klass.notEqual(0)) { - int layoutHelper = klass.readInt(klassLayoutHelperOffset()); - if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) { - return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset()), Class.class, true, true); + if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) { + return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset(), FINAL_LOCATION), Class.class, true, true); } } return null; @@ -113,6 +110,6 @@ @MethodSubstitution(isStatic = false) public static boolean isInstance(final Class<?> thisObj, Object obj) { - return !thisObj.isPrimitive() && ConditionalNode.materializeIsInstance(thisObj, obj); + return !isPrimitive(thisObj) && ConditionalNode.materializeIsInstance(thisObj, obj); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Mon Mar 04 10:00:49 2013 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.snippets; import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*; +import sun.misc.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -42,6 +43,10 @@ */ public class HotSpotSnippetUtils { + public static final Object ANY_LOCATION = LocationNode.ANY_LOCATION; + public static final Object UNKNOWN_LOCATION = LocationNode.UNKNOWN_LOCATION; + public static final Object FINAL_LOCATION = LocationNode.FINAL_LOCATION; + public static HotSpotVMConfig config() { return HotSpotGraalRuntime.getInstance().getConfig(); } @@ -51,16 +56,49 @@ return config().verifyOops; } + public static final Object TLAB_TOP_LOCATION = LocationNode.createLocation("TlabTop"); + @Fold public static int threadTlabTopOffset() { return config().threadTlabTopOffset; } + public static final Object TLAB_END_LOCATION = LocationNode.createLocation("TlabEnd"); + @Fold - public static int threadTlabEndOffset() { + private static int threadTlabEndOffset() { return config().threadTlabEndOffset; } + public static final Object TLAB_START_LOCATION = LocationNode.createLocation("TlabStart"); + + @Fold + private static int threadTlabStartOffset() { + return config().threadTlabStartOffset; + } + + public static Word readTlabTop(Word thread) { + return thread.readWord(threadTlabTopOffset(), TLAB_TOP_LOCATION); + } + + public static Word readTlabEnd(Word thread) { + return thread.readWord(threadTlabEndOffset(), TLAB_END_LOCATION); + } + + public static Word readTlabStart(Word thread) { + return thread.readWord(threadTlabStartOffset(), TLAB_START_LOCATION); + } + + public static void writeTlabTop(Word thread, Word top) { + thread.writeWord(threadTlabTopOffset(), top, TLAB_TOP_LOCATION); + } + + public static void initializeTlab(Word thread, Word start, Word end) { + thread.writeWord(threadTlabStartOffset(), start, TLAB_START_LOCATION); + thread.writeWord(threadTlabTopOffset(), start, TLAB_TOP_LOCATION); + thread.writeWord(threadTlabEndOffset(), end, TLAB_END_LOCATION); + } + @Fold public static int threadObjectOffset() { return config().threadObjectOffset; @@ -98,9 +136,11 @@ @Fold public static int pageSize() { - return HotSpotGraalRuntime.getInstance().getTarget().pageSize; + return Unsafe.getUnsafe().pageSize(); } + public static final Object PROTOTYPE_MARK_WORD_LOCATION = LocationNode.createLocation("PrototypeMarkWord"); + @Fold public static int prototypeMarkWordOffset() { return config().prototypeMarkWordOffset; @@ -117,10 +157,14 @@ } @Fold - public static int klassLayoutHelperOffset() { + private static int klassLayoutHelperOffset() { return config().klassLayoutHelperOffset; } + public static int readLayoutHelper(Word hub) { + return hub.readInt(klassLayoutHelperOffset(), FINAL_LOCATION); + } + @Fold public static int arrayKlassLayoutHelperIdentifier() { return config().arrayKlassLayoutHelperIdentifier; @@ -136,11 +180,25 @@ return config().klassSuperKlassOffset; } + public static final Object MARK_WORD_LOCATION = LocationNode.createLocation("MarkWord"); + @Fold public static int markOffset() { return config().markOffset; } + public static final Object HUB_LOCATION = LocationNode.createLocation("Hub"); + + @Fold + private static int hubOffset() { + return config().hubOffset; + } + + public static void initializeObjectHeader(Word memory, Word markWord, Word hub) { + memory.writeWord(markOffset(), markWord, MARK_WORD_LOCATION); + memory.writeWord(hubOffset(), hub, HUB_LOCATION); + } + @Fold public static int unlockedMask() { return config().unlockedMask; @@ -187,11 +245,6 @@ } @Fold - public static int hubOffset() { - return config().hubOffset; - } - - @Fold public static int metaspaceArrayLengthOffset() { return config().metaspaceArrayLengthOffset; } @@ -231,16 +284,22 @@ return config().superCheckOffsetOffset; } + public static final Object SECONDARY_SUPER_CACHE_LOCATION = LocationNode.createLocation("SecondarySuperCache"); + @Fold public static int secondarySuperCacheOffset() { return config().secondarySuperCacheOffset; } + public static final Object SECONDARY_SUPERS_LOCATION = LocationNode.createLocation("SecondarySupers"); + @Fold public static int secondarySupersOffset() { return config().secondarySupersOffset; } + public static final Object DISPLACED_MARK_WORD_LOCATION = LocationNode.createLocation("DisplacedMarkWord"); + @Fold public static int lockDisplacedMarkOffset() { return config().basicLockDisplacedHeaderOffset; @@ -307,12 +366,19 @@ return CodeUtil.log2(wordSize()); } + public static final Object CLASS_STATE_LOCATION = LocationNode.createLocation("ClassState"); + @Fold public static int klassStateOffset() { return config().klassStateOffset; } @Fold + public static int klassStateFullyInitialized() { + return config().klassStateFullyInitialized; + } + + @Fold public static int klassModifierFlagsOffset() { return config().klassModifierFlagsOffset; } @@ -332,22 +398,21 @@ return config().klassInstanceSizeOffset; } + public static final Object HEAP_TOP_LOCATION = LocationNode.createLocation("HeapTop"); + @Fold public static long heapTopAddress() { return config().heapTopAddress; } + public static final Object HEAP_END_LOCATION = LocationNode.createLocation("HeapEnd"); + @Fold public static long heapEndAddress() { return config().heapEndAddress; } @Fold - public static int threadTlabStartOffset() { - return config().threadTlabStartOffset; - } - - @Fold public static long tlabIntArrayMarkWord() { return config().tlabIntArrayMarkWord; } @@ -362,36 +427,43 @@ return config().tlabAlignmentReserve; } + public static final Object TLAB_SIZE_LOCATION = LocationNode.createLocation("TlabSize"); + @Fold public static int threadTlabSizeOffset() { return config().threadTlabSizeOffset; } + public static final Object TLAB_THREAD_ALLOCATED_BYTES_LOCATION = LocationNode.createLocation("TlabThreadAllocatedBytes"); + @Fold public static int threadAllocatedBytesOffset() { return config().threadAllocatedBytesOffset; } - @Fold - public static int klassStateFullyInitialized() { - return config().klassStateFullyInitialized; - } + public static final Object TLAB_REFILL_WASTE_LIMIT_LOCATION = LocationNode.createLocation("RefillWasteLimit"); @Fold public static int tlabRefillWasteLimitOffset() { return config().tlabRefillWasteLimitOffset; } + public static final Object TLAB_NOF_REFILLS_LOCATION = LocationNode.createLocation("TlabNOfRefills"); + @Fold public static int tlabNumberOfRefillsOffset() { return config().tlabNumberOfRefillsOffset; } + public static final Object TLAB_FAST_REFILL_WASTE_LOCATION = LocationNode.createLocation("TlabFastRefillWaste"); + @Fold public static int tlabFastRefillWasteOffset() { return config().tlabFastRefillWasteOffset; } + public static final Object TLAB_SLOW_ALLOCATIONS_LOCATION = LocationNode.createLocation("TlabSlowAllocations"); + @Fold public static int tlabSlowAllocationsOffset() { return config().tlabSlowAllocationsOffset; @@ -444,7 +516,6 @@ @Fold public static int layoutHelperElementTypePrimitiveInPlace() { - System.out.println(String.format("%x", config().layoutHelperElementTypePrimitiveInPlace)); return config().layoutHelperElementTypePrimitiveInPlace; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Mon Mar 04 10:00:49 2013 +0100 @@ -99,7 +99,7 @@ return falseValue; } Word objectHub = loadHub(object); - if (objectHub.readWord(superCheckOffset).notEqual(hub)) { + if (objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub)) { probability(NOT_LIKELY_PROBABILITY); displayMiss.inc(); return falseValue;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Mon Mar 04 10:00:49 2013 +0100 @@ -40,6 +40,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; @@ -109,7 +110,7 @@ // The bias pattern is present in the object's mark word. Need to check // whether the bias owner and the epoch are both still current. Word hub = loadHub(object); - final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset()); + final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); final Word thread = thread(); final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace()); trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord); @@ -154,7 +155,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).equal(unbiasedMark)) { + if (compareAndSwap(object, markOffset(), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark)) { // Object is now biased to current thread -> done traceObject(trace, "+lock{bias:acquired}", object); return; @@ -175,7 +176,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).equal(mark)) { + if (compareAndSwap(object, markOffset(), mark, biasedMark, MARK_WORD_LOCATION).equal(mark)) { // Object is now biased to current thread -> done traceObject(trace, "+lock{bias:transfer}", object); return; @@ -197,7 +198,7 @@ // that another thread raced us for the privilege of revoking the // bias of this particular object, so it's okay to continue in the // normal locking code. - Word result = compareAndSwap(object, markOffset(), mark, prototypeMarkWord); + Word result = compareAndSwap(object, markOffset(), mark, prototypeMarkWord, MARK_WORD_LOCATION); // Fall through to the normal CAS-based lock, because no matter what // the result of the above CAS, some thread must have succeeded in @@ -215,11 +216,11 @@ trace(trace, " unlockedMark: 0x%016lx\n", unlockedMark); // Copy this unlocked mark word into the lock slot on the stack - lock.writeWord(lockDisplacedMarkOffset(), unlockedMark); + lock.writeWord(lockDisplacedMarkOffset(), unlockedMark, DISPLACED_MARK_WORD_LOCATION); // 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); + Word currentMark = compareAndSwap(object, markOffset(), unlockedMark, lock, MARK_WORD_LOCATION); if (currentMark.notEqual(unlockedMark)) { trace(trace, " currentMark: 0x%016lx\n", currentMark); // The mark word in the object header was not the same. @@ -247,7 +248,7 @@ return; } else { // Recursively locked => write 0 to the lock slot - lock.writeWord(lockDisplacedMarkOffset(), Word.zero()); + lock.writeWord(lockDisplacedMarkOffset(), Word.zero(), DISPLACED_MARK_WORD_LOCATION); traceObject(trace, "+lock{recursive}", object); } } else { @@ -302,7 +303,7 @@ final Word lock = CurrentLockNode.currentLock(); // Load displaced mark - final Word displacedMark = lock.readWord(lockDisplacedMarkOffset()); + final Word displacedMark = lock.readWord(lockDisplacedMarkOffset(), DISPLACED_MARK_WORD_LOCATION); trace(trace, " displacedMark: 0x%016lx\n", displacedMark); if (displacedMark.equal(0)) { @@ -313,7 +314,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).notEqual(lock)) { + if (DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark, MARK_WORD_LOCATION).notEqual(lock)) { // The object's mark word was not pointing to the displaced header, // we do unlocking via runtime call. probability(DEOPT_PATH_PROBABILITY); @@ -365,35 +366,37 @@ */ private static final boolean ENABLE_BREAKPOINT = false; + private static final Object MONITOR_COUNTER_LOCATION = LocationNode.createLocation("MonitorCounter"); + @NodeIntrinsic(BreakpointNode.class) static native void bkpt(Object object, Word mark, Word tmp, Word value); private static void incCounter() { if (CHECK_BALANCED_MONITORS) { final Word counter = MonitorCounterNode.counter(); - final int count = counter.readInt(0); - counter.writeInt(0, count + 1); + final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION); + counter.writeInt(0, count + 1, MONITOR_COUNTER_LOCATION); } } private static void decCounter() { if (CHECK_BALANCED_MONITORS) { final Word counter = MonitorCounterNode.counter(); - final int count = counter.readInt(0); - counter.writeInt(0, count - 1); + final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION); + counter.writeInt(0, count - 1, MONITOR_COUNTER_LOCATION); } } @Snippet private static void initCounter() { final Word counter = MonitorCounterNode.counter(); - counter.writeInt(0, 0); + counter.writeInt(0, 0, MONITOR_COUNTER_LOCATION); } @Snippet private static void checkCounter(String errMsg) { final Word counter = MonitorCounterNode.counter(); - final int count = counter.readInt(0); + final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION); if (count != 0) { vmError(errMsg, count); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Mon Mar 04 10:00:49 2013 +0100 @@ -29,8 +29,8 @@ import static com.oracle.graal.snippets.Snippet.Varargs.*; import static com.oracle.graal.snippets.SnippetTemplate.*; import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; +import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*; import static com.oracle.graal.snippets.nodes.ExplodeLoopNode.*; -import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -62,13 +62,13 @@ @Snippet public static Word allocate(@Parameter("size") int size) { Word thread = thread(); - Word top = thread.readWord(threadTlabTopOffset()); - Word end = thread.readWord(threadTlabEndOffset()); + Word top = readTlabTop(thread); + Word end = readTlabEnd(thread); Word newTop = top.add(size); // this check might lead to problems if the TLAB is within 16GB of the address space end (checked in c++ code) if (newTop.belowOrEqual(end)) { probability(FAST_PATH_PROBABILITY); - thread.writeWord(threadTlabTopOffset(), newTop); + writeTlabTop(thread, newTop); return top; } return Word.zero(); @@ -178,7 +178,7 @@ Word dims = DimensionsNode.allocaDimsArray(rank); ExplodeLoopNode.explodeLoop(); for (int i = 0; i < rank; i++) { - dims.writeInt(i * 4, dimensions[i]); + dims.writeInt(i * 4, dimensions[i], ANY_LOCATION); } return NewMultiArrayStubCall.call(hub, rank, dims); } @@ -194,20 +194,19 @@ * Formats some allocated memory with an object header zeroes out the rest. */ private static void formatObject(Word hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents) { - Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset()) : compileTimePrototypeMarkWord; - memory.writeWord(markOffset(), prototypeMarkWord); - memory.writeWord(hubOffset(), hub); + Word prototypeMarkWord = useBiasedLocking() ? hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord; + initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { if (size <= MAX_UNROLLED_OBJECT_ZEROING_SIZE) { new_seqInit.inc(); explodeLoop(); for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { - memory.writeWord(offset, Word.zero()); + memory.writeWord(offset, Word.zero(), ANY_LOCATION); } } else { new_loopInit.inc(); for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { - memory.writeWord(offset, Word.zero()); + memory.writeWord(offset, Word.zero(), ANY_LOCATION); } } } @@ -217,13 +216,12 @@ * Formats some allocated memory with an object header zeroes out the rest. */ public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) { - memory.writeWord(markOffset(), prototypeMarkWord); - memory.writeInt(arrayLengthOffset(), length); + memory.writeInt(arrayLengthOffset(), length, ANY_LOCATION); // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null - memory.writeWord(hubOffset(), hub); + initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { for (int offset = headerSize; offset < allocationSize; offset += wordSize()) { - memory.writeWord(offset, Word.zero()); + memory.writeWord(offset, Word.zero(), ANY_LOCATION); } } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; @@ -34,7 +33,6 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.common.*; import com.oracle.graal.snippets.nodes.*; public class ObjectCloneNode extends MacroNode implements VirtualizableAllocation, ArrayLengthProvider { @@ -52,33 +50,30 @@ return arguments.get(0); } - private Method selectSnippetMethod(LoweringTool tool) { - ResolvedJavaType type = getObject().objectStamp().type(); - if (type.isArray()) { - return ObjectCloneSnippets.arrayCloneMethod; - } else if (type.isAssignableFrom(tool.getRuntime().lookupJavaType(Object[].class))) { - // arrays are assignable to Object, Cloneable and Serializable - return ObjectCloneSnippets.genericCloneMethod; - } else { - return ObjectCloneSnippets.instanceCloneMethod; - } - } - @Override - public void lower(LoweringTool tool) { + protected StructuredGraph getSnippetGraph(LoweringTool tool) { if (!GraalOptions.IntrinsifyObjectClone) { - super.lower(tool); - return; - } - ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(selectSnippetMethod(tool)); - if (Debug.isLogEnabled()) { - Debug.log("%s > Intrinsify (%s)", Debug.currentScope(), snippetMethod.getSignature().getParameterType(0, snippetMethod.getDeclaringClass()).getComponentType()); + return null; } + ResolvedJavaType type = getObject().objectStamp().type(); + Method method; + /* + * The first condition tests if the parameter is an array, the second condition tests if the + * parameter can be an array. Otherwise, the parameter is known to be a non-array object. + */ + if (type.isArray()) { + method = ObjectCloneSnippets.arrayCloneMethod; + } else if (type == null || type.isAssignableFrom(tool.getRuntime().lookupJavaType(Object[].class))) { + method = ObjectCloneSnippets.genericCloneMethod; + } else { + method = ObjectCloneSnippets.instanceCloneMethod; + } + ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(method); StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.getCompilerStorage().get(Graph.class); + assert snippetGraph != null : "ObjectCloneSnippets should be installed"; - InvokeNode invoke = replaceWithInvoke(); - InliningUtil.inline(invoke, snippetGraph, false); + return snippetGraph; } private static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) { @@ -86,7 +81,7 @@ } private static ResolvedJavaType getConcreteType(ObjectStamp stamp, Assumptions assumptions) { - if (stamp.isExactType()) { + if (stamp.isExactType() || stamp.type() == null) { return stamp.type(); } else { ResolvedJavaType type = stamp.type().findUniqueConcreteSubtype();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneSnippets.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectCloneSnippets.java Mon Mar 04 10:00:49 2013 +0100 @@ -53,12 +53,12 @@ private static Object instanceClone(Object src, Word hub, int layoutHelper) { int instanceSize = layoutHelper; Pointer memory = NewObjectSnippets.allocate(instanceSize); - Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset()); + Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); Object result = NewObjectSnippets.initializeObject((Word) memory, hub, prototypeMarkWord, instanceSize, false, false); memory = Word.fromObject(result); for (int offset = 2 * wordSize(); offset < instanceSize; offset += wordSize()) { - memory.writeWord(offset, Word.fromObject(src).readWord(offset)); + memory.writeWord(offset, Word.fromObject(src).readWord(offset, UNKNOWN_LOCATION), ANY_LOCATION); } return result; @@ -71,12 +71,12 @@ int sizeInBytes = NewObjectSnippets.computeArrayAllocationSize(arrayLength, wordSize(), headerSize, log2ElementSize); Pointer memory = NewObjectSnippets.allocate(sizeInBytes); - Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset()); + Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); Object result = NewObjectSnippets.initializeArray((Word) memory, hub, arrayLength, sizeInBytes, prototypeMarkWord, headerSize, false, false); memory = Word.fromObject(result); for (int offset = headerSize; offset < sizeInBytes; offset += wordSize()) { - memory.writeWord(offset, Word.fromObject(src).readWord(offset)); + memory.writeWord(offset, Word.fromObject(src).readWord(offset, UNKNOWN_LOCATION), ANY_LOCATION); } return result; } @@ -94,14 +94,14 @@ public static Object instanceClone(Object src) { instanceCloneCounter.inc(); Word hub = getAndCheckHub(src); - return instanceClone(src, hub, hub.readInt(layoutHelperOffset())); + return instanceClone(src, hub, hub.readInt(layoutHelperOffset(), FINAL_LOCATION)); } @Snippet public static Object arrayClone(Object src) { arrayCloneCounter.inc(); Word hub = getAndCheckHub(src); - int layoutHelper = hub.readInt(layoutHelperOffset()); + int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION); return arrayClone(src, hub, layoutHelper); } @@ -109,7 +109,7 @@ public static Object genericClone(Object src) { genericCloneCounter.inc(); Word hub = getAndCheckHub(src); - int layoutHelper = hub.readInt(layoutHelperOffset()); + int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION); if (layoutHelper < 0) { probability(LIKELY_PROBABILITY); genericArrayCloneCounter.inc();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSubstitutions.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ObjectSubstitutions.java Mon Mar 04 10:00:49 2013 +0100 @@ -25,8 +25,10 @@ import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.snippets.*; -import com.oracle.graal.snippets.ClassSubstitution.*; +import com.oracle.graal.snippets.ClassSubstitution.MacroSubstitution; +import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; import com.oracle.graal.word.*; /** @@ -38,7 +40,7 @@ @MethodSubstitution(isStatic = false) public static Class<?> getClass(final Object thisObj) { Word hub = loadHub(thisObj); - return unsafeCast(hub.readFinalObject(Word.signed(classMirrorOffset())), Class.class, true, true); + return unsafeCast(hub.readObject(Word.signed(classMirrorOffset()), LocationNode.FINAL_LOCATION), Class.class, true, true); } @MethodSubstitution(isStatic = false)
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSubstitutions.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ThreadSubstitutions.java Mon Mar 04 10:00:49 2013 +0100 @@ -43,10 +43,10 @@ @MethodSubstitution(isStatic = false) private static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) { Word rawThread = HotSpotCurrentRawThreadNode.get(); - Thread thread = (Thread) rawThread.readObject(threadObjectOffset()); + Thread thread = (Thread) rawThread.readObject(threadObjectOffset(), FINAL_LOCATION); if (thisObject == thread) { - Word osThread = rawThread.readWord(osThreadOffset()); - boolean interrupted = osThread.readInt(osThreadInterruptedOffset()) != 0; + Word osThread = rawThread.readWord(osThreadOffset(), FINAL_LOCATION); + boolean interrupted = osThread.readInt(osThreadInterruptedOffset(), UNKNOWN_LOCATION) != 0; if (!interrupted || !clearInterrupted) { return interrupted; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/TypeCheckSnippetUtils.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/TypeCheckSnippetUtils.java Mon Mar 04 10:00:49 2013 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.phases.*; import com.oracle.graal.snippets.*; import com.oracle.graal.word.*; @@ -39,9 +40,11 @@ */ public class TypeCheckSnippetUtils { + public static final Object TYPE_DISPLAY_LOCATION = LocationNode.createLocation("TypeDisplay"); + static boolean checkSecondarySubType(Word t, Word s) { // if (S.cache == T) return true - if (s.readWord(secondarySuperCacheOffset()).equal(t)) { + if (s.readWord(secondarySuperCacheOffset(), SECONDARY_SUPER_CACHE_LOCATION).equal(t)) { cacheHit.inc(); return true; } @@ -51,11 +54,11 @@ static boolean checkUnknownSubType(Word t, Word s) { // int off = T.offset - int superCheckOffset = t.readInt(superCheckOffsetOffset()); + int superCheckOffset = t.readInt(superCheckOffsetOffset(), FINAL_LOCATION); boolean primary = superCheckOffset != secondarySuperCacheOffset(); // if (T = S[off]) return true - if (s.readWord(superCheckOffset).equal(t)) { + if (s.readWord(superCheckOffset, TYPE_DISPLAY_LOCATION).equal(t)) { if (primary) { cacheHit.inc(); } else { @@ -81,12 +84,12 @@ } // if (S.scan_s_s_array(T)) { S.cache = T; return true; } - Word secondarySupers = s.readWord(secondarySupersOffset()); - int length = secondarySupers.readInt(metaspaceArrayLengthOffset()); + Word secondarySupers = s.readWord(secondarySupersOffset(), SECONDARY_SUPERS_LOCATION); + int length = secondarySupers.readInt(metaspaceArrayLengthOffset(), FINAL_LOCATION); for (int i = 0; i < length; i++) { - if (t.equal(loadWordElement(secondarySupers, i))) { + if (t.equal(loadSecondarySupersElement(secondarySupers, i))) { probability(NOT_LIKELY_PROBABILITY); - s.writeWord(secondarySuperCacheOffset(), t); + s.writeWord(secondarySuperCacheOffset(), t, SECONDARY_SUPER_CACHE_LOCATION); secondariesHit.inc(); return true; } @@ -103,8 +106,8 @@ return hintHubs; } - static Word loadWordElement(Word metaspaceArray, int index) { - return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize()); + static Word loadSecondarySupersElement(Word metaspaceArray, int index) { + return metaspaceArray.readWord(metaspaceArrayBaseOffset() + index * wordSize(), FINAL_LOCATION); } private static final SnippetCounter.Group counters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("TypeCheck") : null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Mon Mar 04 10:00:49 2013 +0100 @@ -67,7 +67,7 @@ */ @Snippet private static Object newArray(@Parameter("hub") Word hub, @Parameter("length") int length, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) { - int layoutHelper = hub.readInt(layoutHelperOffset()); + int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); int elementKind = (layoutHelper >> layoutHelperElementTypeShift()) & layoutHelperElementTypeMask();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Mar 04 10:00:49 2013 +0100 @@ -67,16 +67,15 @@ */ @Snippet private static Object newInstance(@Parameter("hub") Word hub, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) { - int sizeInBytes = hub.readInt(klassInstanceSizeOffset()); + int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), FINAL_LOCATION); if (!forceSlowPath() && inlineContiguousAllocationSupported()) { - if (hub.readInt(klassStateOffset()) == klassStateFullyInitialized()) { + if (hub.readInt(klassStateOffset(), CLASS_STATE_LOCATION) == klassStateFullyInitialized()) { Word memory = refillAllocate(intArrayHub, sizeInBytes, log); if (memory.notEqual(0)) { - Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset()); - memory.writeWord(markOffset(), prototypeMarkWord); - memory.writeWord(hubOffset(), hub); + Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); + initializeObjectHeader(memory, prototypeMarkWord, hub); for (int offset = 2 * wordSize(); offset < sizeInBytes; offset += wordSize()) { - memory.writeWord(offset, Word.zero()); + memory.writeWord(offset, Word.zero(), ANY_LOCATION); } return verifyOop(memory.toObject()); } @@ -100,8 +99,8 @@ int alignmentReserveInBytes = tlabAlignmentReserveInHeapWords() * wordSize(); Word thread = thread(); - Word top = thread.readWord(threadTlabTopOffset()); - Word end = thread.readWord(threadTlabEndOffset()); + Word top = readTlabTop(thread); + Word end = readTlabEnd(thread); // calculate amount of free space Word tlabFreeSpaceInBytes = end.subtract(top); @@ -115,16 +114,16 @@ // Retain TLAB and allocate object in shared space if // the amount free in the TLAB is too large to discard. - Word refillWasteLimit = thread.readWord(tlabRefillWasteLimitOffset()); + Word refillWasteLimit = thread.readWord(tlabRefillWasteLimitOffset(), TLAB_REFILL_WASTE_LIMIT_LOCATION); if (tlabFreeSpaceInWords.belowOrEqual(refillWasteLimit)) { if (tlabStats()) { // increment number of refills - thread.writeInt(tlabNumberOfRefillsOffset(), thread.readInt(tlabNumberOfRefillsOffset()) + 1); - log(log, "thread: %p -- number_of_refills %d\n", thread, thread.readInt(tlabNumberOfRefillsOffset())); + thread.writeInt(tlabNumberOfRefillsOffset(), thread.readInt(tlabNumberOfRefillsOffset(), TLAB_NOF_REFILLS_LOCATION) + 1, TLAB_NOF_REFILLS_LOCATION); + log(log, "thread: %p -- number_of_refills %d\n", thread, thread.readInt(tlabNumberOfRefillsOffset(), TLAB_NOF_REFILLS_LOCATION)); // accumulate wastage - Word wastage = thread.readWord(tlabFastRefillWasteOffset()).add(tlabFreeSpaceInWords); + Word wastage = thread.readWord(tlabFastRefillWasteOffset(), TLAB_FAST_REFILL_WASTE_LOCATION).add(tlabFreeSpaceInWords); log(log, "thread: %p -- accumulated wastage %d\n", thread, wastage); - thread.writeWord(tlabFastRefillWasteOffset(), wastage); + thread.writeWord(tlabFastRefillWasteOffset(), wastage, TLAB_FAST_REFILL_WASTE_LOCATION); } // if TLAB is currently allocated (top or end != null) then @@ -137,22 +136,19 @@ int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts; NewObjectSnippets.formatArray(intArrayHub, -1, length, headerSize, top, intArrayMarkWord, false); - Word allocated = thread.readWord(threadAllocatedBytesOffset()); - allocated = allocated.add(top.subtract(thread.readWord(threadTlabStartOffset()))); - thread.writeWord(threadAllocatedBytesOffset(), allocated); + Word allocated = thread.readWord(threadAllocatedBytesOffset(), TLAB_THREAD_ALLOCATED_BYTES_LOCATION); + allocated = allocated.add(top.subtract(readTlabStart(thread))); + thread.writeWord(threadAllocatedBytesOffset(), allocated, TLAB_THREAD_ALLOCATED_BYTES_LOCATION); } // refill the TLAB with an eden allocation - Word tlabRefillSizeInWords = thread.readWord(threadTlabSizeOffset()); + Word tlabRefillSizeInWords = thread.readWord(threadTlabSizeOffset(), TLAB_SIZE_LOCATION); Word tlabRefillSizeInBytes = tlabRefillSizeInWords.multiply(wordSize()); // allocate new TLAB, address returned in top top = edenAllocate(tlabRefillSizeInBytes, log); if (top.notEqual(0)) { - thread.writeWord(threadTlabStartOffset(), top); - thread.writeWord(threadTlabTopOffset(), top); - end = top.add(tlabRefillSizeInBytes.subtract(alignmentReserveInBytes)); - thread.writeWord(threadTlabEndOffset(), end); + initializeTlab(thread, top, end); return allocate(sizeInBytes); } else { @@ -161,11 +157,11 @@ } else { // Retain TLAB Word newRefillWasteLimit = refillWasteLimit.add(tlabRefillWasteIncrement()); - thread.writeWord(tlabRefillWasteLimitOffset(), newRefillWasteLimit); + thread.writeWord(tlabRefillWasteLimitOffset(), newRefillWasteLimit, TLAB_REFILL_WASTE_LIMIT_LOCATION); log(log, "refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit); if (tlabStats()) { - thread.writeInt(tlabSlowAllocationsOffset(), thread.readInt(tlabSlowAllocationsOffset()) + 1); + thread.writeInt(tlabSlowAllocationsOffset(), thread.readInt(tlabSlowAllocationsOffset(), TLAB_SLOW_ALLOCATIONS_LOCATION) + 1, TLAB_SLOW_ALLOCATIONS_LOCATION); } return edenAllocate(Word.unsigned(sizeInBytes), log); @@ -184,18 +180,18 @@ Word heapEndAddress = Word.unsigned(heapEndAddress()); while (true) { - Word heapTop = heapTopAddress.readWord(0); + Word heapTop = heapTopAddress.readWord(0, HEAP_TOP_LOCATION); Word newHeapTop = heapTop.add(sizeInBytes); if (newHeapTop.belowOrEqual(heapTop)) { return Word.zero(); } - Word heapEnd = heapEndAddress.readWord(0); + Word heapEnd = heapEndAddress.readWord(0, HEAP_END_LOCATION); if (newHeapTop.aboveThan(heapEnd)) { return Word.zero(); } - if (compareAndSwap(heapTopAddress, 0, heapTop, newHeapTop).equal(heapTop)) { + if (compareAndSwap(heapTopAddress, 0, heapTop, newHeapTop, HEAP_TOP_LOCATION).equal(heapTop)) { return heapTop; } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Mon Mar 04 10:00:49 2013 +0100 @@ -31,6 +31,7 @@ import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; @@ -70,7 +71,7 @@ /** * Creates a new stub container. The new stub still needs to be - * {@linkplain #install(GraalCompiler) installed}. + * {@linkplain #install(Backend, GraalCompiler) installed}. * * @param descriptor linkage details for a call to the stub */ @@ -106,7 +107,7 @@ * Compiles the code for this stub, installs it and initializes the address used for calls to * it. */ - public void install(GraalCompiler compiler) { + public void install(Backend backend, GraalCompiler compiler) { StructuredGraph graph = (StructuredGraph) stubMethod.getCompilerStorage().get(Graph.class); Key key = new Key(stubMethod); @@ -117,7 +118,7 @@ PhasePlan phasePlan = new PhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - final CompilationResult compResult = compiler.compileMethod(stubMethod, graph, null, phasePlan, OptimisticOptimizations.ALL); + final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), stubMethod, graph, null, phasePlan, OptimisticOptimizations.ALL); final CodeInfo[] info = new CodeInfo[1]; stubCode = Debug.scope("CodeInstall", new Object[]{compiler, stubMethod}, new Callable<InstalledCode>() {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Mon Mar 04 10:00:49 2013 +0100 @@ -345,7 +345,8 @@ case INVOKEINTERFACE: case INVOKESPECIAL: case INVOKESTATIC: - case INVOKEVIRTUAL: { + case INVOKEVIRTUAL: + case INVOKEDYNAMIC: { current = null; addSuccessor(bci, makeBlock(stream.nextBCI())); ExceptionDispatchBlock handler = handleExceptions(bci); @@ -757,7 +758,7 @@ if (blockChanged) { block.localsLiveIn.clear(); block.localsLiveIn.or(block.localsLiveOut); - block.localsLiveIn.xor(block.localsLiveKill); + block.localsLiveIn.andNot(block.localsLiveKill); block.localsLiveIn.or(block.localsLiveGen); Debug.log(" end B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.blockID, block.startBci, block.endBci, block.localsLiveIn, block.localsLiveOut, block.localsLiveGen, block.localsLiveKill);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Mon Mar 04 10:00:49 2013 +0100 @@ -203,16 +203,16 @@ } private void propagateDelete(FloatingNode node) { - assert node instanceof PhiNode || node instanceof ValueProxyNode; + assert node instanceof PhiNode || node instanceof ProxyNode; if (node.isDeleted()) { return; } // Collect all phi functions that use this phi so that we can delete them recursively (after // we delete ourselves to avoid circles). - List<FloatingNode> propagateUsages = node.usages().filter(FloatingNode.class).filter(isA(PhiNode.class).or(ValueProxyNode.class)).snapshot(); + List<FloatingNode> propagateUsages = node.usages().filter(FloatingNode.class).filter(isA(PhiNode.class).or(ProxyNode.class)).snapshot(); // Remove the phi function from all FrameStates where it is used and then delete it. - assert node.usages().filter(isNotA(FrameState.class).nor(PhiNode.class).nor(ValueProxyNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states"; + assert node.usages().filter(isNotA(FrameState.class).nor(PhiNode.class).nor(ProxyNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states"; node.replaceAtUsages(null); node.safeDelete(); @@ -235,21 +235,21 @@ ValueNode value = localAt(i); if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { Debug.log(" inserting proxy for %s", value); - storeLocal(i, graph.unique(new ValueProxyNode(value, loopExit, PhiType.Value))); + storeLocal(i, graph.unique(new ProxyNode(value, loopExit, PhiType.Value))); } } for (int i = 0; i < stackSize(); i++) { ValueNode value = stackAt(i); if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { Debug.log(" inserting proxy for %s", value); - storeStack(i, graph.unique(new ValueProxyNode(value, loopExit, PhiType.Value))); + storeStack(i, graph.unique(new ProxyNode(value, loopExit, PhiType.Value))); } } for (int i = 0; i < locks.length; i++) { ValueNode value = locks[i]; if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { Debug.log(" inserting proxy for %s", value); - locks[i] = graph.unique(new ValueProxyNode(value, loopExit, PhiType.Value)); + locks[i] = graph.unique(new ProxyNode(value, loopExit, PhiType.Value)); } } } @@ -259,21 +259,21 @@ ValueNode value = localAt(i); if (value != null) { Debug.log(" inserting proxy for %s", value); - storeLocal(i, graph.unique(new ValueProxyNode(value, begin, PhiType.Value))); + storeLocal(i, graph.unique(new ProxyNode(value, begin, PhiType.Value))); } } for (int i = 0; i < stackSize(); i++) { ValueNode value = stackAt(i); if (value != null) { Debug.log(" inserting proxy for %s", value); - storeStack(i, graph.unique(new ValueProxyNode(value, begin, PhiType.Value))); + storeStack(i, graph.unique(new ProxyNode(value, begin, PhiType.Value))); } } for (int i = 0; i < locks.length; i++) { ValueNode value = locks[i]; if (value != null) { Debug.log(" inserting proxy for %s", value); - locks[i] = graph.unique(new ValueProxyNode(value, begin, PhiType.Value)); + locks[i] = graph.unique(new ProxyNode(value, begin, PhiType.Value)); } } } @@ -292,7 +292,7 @@ public void cleanupDeletedPhis() { for (int i = 0; i < localsSize(); i++) { if (localAt(i) != null && localAt(i).isDeleted()) { - assert localAt(i) instanceof PhiNode || localAt(i) instanceof ValueProxyNode : "Only phi and value proxies can be deleted during parsing: " + localAt(i); + assert localAt(i) instanceof PhiNode || localAt(i) instanceof ProxyNode : "Only phi and value proxies can be deleted during parsing: " + localAt(i); storeLocal(i, null); } } @@ -479,15 +479,6 @@ } /** - * Pushes a value onto the stack and checks that it is a JSR return address. - * - * @param x the instruction to push onto the stack - */ - public void jpush(ValueNode x) { - xpush(assertJsr(x)); - } - - /** * Pushes a value onto the stack and checks that it is a long. * * @param x the instruction to push onto the stack @@ -566,15 +557,6 @@ } /** - * Pops a value off of the stack and checks that it is a JSR return address. - * - * @return x the instruction popped off the stack - */ - public ValueNode jpop() { - return assertJsr(xpop()); - } - - /** * Pops a value off of the stack and checks that it is a long. * * @return x the instruction popped off the stack
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Mon Mar 04 10:00:49 2013 +0100 @@ -23,21 +23,16 @@ package com.oracle.graal.java; import com.oracle.graal.api.meta.*; -import com.oracle.graal.phases.*; public class GraphBuilderConfiguration { - public static enum ResolvePolicy { - Default, EagerForSnippets, Eager, - } - - private final ResolvePolicy resolving; - private final PhasePlan plan; + private final boolean eagerResolving; + private final boolean omitAllExceptionEdges; private ResolvedJavaType[] skippedExceptionTypes; - public GraphBuilderConfiguration(ResolvePolicy resolving, PhasePlan plan) { - this.resolving = resolving; - this.plan = plan; + protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges) { + this.eagerResolving = eagerResolving; + this.omitAllExceptionEdges = omitAllExceptionEdges; } public void setSkippedExceptionTypes(ResolvedJavaType[] skippedExceptionTypes) { @@ -48,31 +43,23 @@ return skippedExceptionTypes; } - public boolean eagerResolvingForSnippets() { - return (resolving == ResolvePolicy.EagerForSnippets || resolving == ResolvePolicy.Eager); + public boolean eagerResolving() { + return eagerResolving; } - public boolean eagerResolving() { - return (resolving == ResolvePolicy.Eager); - } - - public PhasePlan plan() { - return plan; + public boolean omitAllExceptionEdges() { + return omitAllExceptionEdges; } public static GraphBuilderConfiguration getDefault() { - return getDefault(null); + return new GraphBuilderConfiguration(false, false); } - public static GraphBuilderConfiguration getDefault(PhasePlan plan) { - return new GraphBuilderConfiguration(ResolvePolicy.Default, plan); + public static GraphBuilderConfiguration getEagerDefault() { + return new GraphBuilderConfiguration(true, false); } public static GraphBuilderConfiguration getSnippetDefault() { - return getSnippetDefault(null); - } - - public static GraphBuilderConfiguration getSnippetDefault(PhasePlan plan) { - return new GraphBuilderConfiguration(ResolvePolicy.EagerForSnippets, plan); + return new GraphBuilderConfiguration(true, true); } }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -182,11 +182,12 @@ currentBlock = blockMap.startBlock; blockMap.startBlock.entryState = frameState; if (blockMap.startBlock.isLoopHeader) { - // TODO(lstadler,gduboscq) createTarget might not be safe at this position, since it - // expects currentBlock, - // etc. to be set up correctly. A better solution to this problem of start blocks that - // are loop headers - // would be to create a dummy block in BciBlockMapping. + /* + * TODO(lstadler,gduboscq) createTarget might not be safe at this position, since it + * expects currentBlock, etc. to be set up correctly. A better solution to this problem + * of start blocks that are loop headers would be to create a dummy block in + * BciBlockMapping. + */ appendGoto(createTarget(blockMap.startBlock, frameState)); } else { blockMap.startBlock.firstInstruction = lastInstr; @@ -635,21 +636,21 @@ private JavaType lookupType(int cpi, int bytecode) { eagerResolvingForSnippets(cpi, bytecode); JavaType result = constantPool.lookupType(cpi, bytecode); - assert !graphBuilderConfig.eagerResolvingForSnippets() || result instanceof ResolvedJavaType; + assert !graphBuilderConfig.eagerResolving() || result instanceof ResolvedJavaType; return result; } private JavaMethod lookupMethod(int cpi, int opcode) { eagerResolvingForSnippets(cpi, opcode); JavaMethod result = constantPool.lookupMethod(cpi, opcode); - assert !graphBuilderConfig.eagerResolvingForSnippets() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result; + assert !graphBuilderConfig.eagerResolving() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result; return result; } private JavaField lookupField(int cpi, int opcode) { eagerResolvingForSnippets(cpi, opcode); JavaField result = constantPool.lookupField(cpi, opcode); - assert !graphBuilderConfig.eagerResolvingForSnippets() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; + assert !graphBuilderConfig.eagerResolving() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; return result; } @@ -660,14 +661,8 @@ return result; } - // private void eagerResolving(int cpi, int bytecode) { - // if (graphBuilderConfig.eagerResolving()) { - // constantPool.loadReferencedType(cpi, bytecode); - // } - // } - private void eagerResolvingForSnippets(int cpi, int bytecode) { - if (graphBuilderConfig.eagerResolvingForSnippets()) { + if (graphBuilderConfig.eagerResolving()) { constantPool.loadReferencedType(cpi, bytecode); } } @@ -1038,13 +1033,13 @@ } JavaType returnType = targetMethod.getSignature().getReturnType(method.getDeclaringClass()); - if (graphBuilderConfig.eagerResolvingForSnippets()) { + if (graphBuilderConfig.eagerResolving()) { returnType = returnType.resolve(targetMethod.getDeclaringClass()); } MethodCallTargetNode callTarget = currentGraph.add(new MethodCallTargetNode(invokeKind, targetMethod, args, returnType)); // be conservative if information was not recorded (could result in endless recompiles // otherwise) - if (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == ExceptionSeen.FALSE) { + if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == ExceptionSeen.FALSE)) { ValueNode result = appendWithBCI(currentGraph.add(new InvokeNode(callTarget, bci()))); frameState.pushReturn(resultType, result); @@ -1103,7 +1098,7 @@ if (successor.jsrScope.nextReturnAddress() != stream().nextBCI()) { throw new JsrNotSupportedBailout("unstructured control flow (internal limitation)"); } - frameState.push(Kind.Jsr, ConstantNode.forJsr(stream().nextBCI(), currentGraph)); + frameState.push(Kind.Int, ConstantNode.forInt(stream().nextBCI(), currentGraph)); appendGoto(createTarget(successor, frameState)); } @@ -1112,7 +1107,7 @@ ValueNode local = frameState.loadLocal(localIndex); JsrScope scope = currentBlock.jsrScope; int retAddress = scope.nextReturnAddress(); - append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IntegerEqualsNode(local, ConstantNode.forJsr(retAddress, currentGraph))), DeoptimizationReason.JavaSubroutineMismatch, + append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IntegerEqualsNode(local, ConstantNode.forInt(retAddress, currentGraph))), DeoptimizationReason.JavaSubroutineMismatch, DeoptimizationAction.InvalidateReprofile))); if (!successor.jsrScope.equals(scope.pop())) { throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)");
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Mon Mar 04 10:00:49 2013 +0100 @@ -26,10 +26,11 @@ import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.amd64.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; +import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.asm.amd64.AMD64Assembler.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; @@ -48,12 +49,12 @@ MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L; - public static class Op1Reg extends AMD64LIRInstruction { + public static class Unary2Op extends AMD64LIRInstruction { @Opcode private final AMD64Arithmetic opcode; - @Def({REG, HINT}) protected Value result; - @Use({REG}) protected Value x; + @Def({REG}) protected AllocatableValue result; + @Use({REG}) protected AllocatableValue x; - public Op1Reg(AMD64Arithmetic opcode, Value result, Value x) { + public Unary2Op(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x) { this.opcode = opcode; this.result = result; this.x = x; @@ -65,12 +66,12 @@ } } - public static class Op1Stack extends AMD64LIRInstruction { + public static class Unary1Op extends AMD64LIRInstruction { @Opcode private final AMD64Arithmetic opcode; - @Def({REG, HINT}) protected Value result; - @Use({REG, STACK, CONST}) protected Value x; + @Def({REG, HINT}) protected AllocatableValue result; + @Use({REG, STACK}) protected AllocatableValue x; - public Op1Stack(AMD64Arithmetic opcode, Value result, Value x) { + public Unary1Op(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x) { this.opcode = opcode; this.result = result; this.x = x; @@ -264,14 +265,12 @@ @SuppressWarnings("unused") - protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, Value result) { + protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, AllocatableValue result) { switch (opcode) { case INEG: masm.negl(asIntReg(result)); break; case LNEG: masm.negq(asLongReg(result)); break; case L2I: masm.andl(asIntReg(result), 0xFFFFFFFF); break; - case I2B: masm.signExtendByte(asIntReg(result)); break; case I2C: masm.andl(asIntReg(result), 0xFFFF); break; - case I2S: masm.signExtendShort(asIntReg(result)); break; default: throw GraalInternalError.shouldNotReachHere(); } } @@ -286,9 +285,9 @@ case IMUL: masm.imull(asIntReg(dst), asIntReg(src)); break; case IOR: masm.orl(asIntReg(dst), asIntReg(src)); break; case IXOR: masm.xorl(asIntReg(dst), asIntReg(src)); break; - case ISHL: masm.shll(asIntReg(dst)); break; - case ISHR: masm.sarl(asIntReg(dst)); break; - case IUSHR:masm.shrl(asIntReg(dst)); break; + case ISHL: assert asIntReg(src) == AMD64.rcx; masm.shll(asIntReg(dst)); break; + case ISHR: assert asIntReg(src) == AMD64.rcx; masm.sarl(asIntReg(dst)); break; + case IUSHR: assert asIntReg(src) == AMD64.rcx; masm.shrl(asIntReg(dst)); break; case LADD: masm.addq(asLongReg(dst), asLongReg(src)); break; case LSUB: masm.subq(asLongReg(dst), asLongReg(src)); break; @@ -296,9 +295,9 @@ case LAND: masm.andq(asLongReg(dst), asLongReg(src)); break; case LOR: masm.orq(asLongReg(dst), asLongReg(src)); break; case LXOR: masm.xorq(asLongReg(dst), asLongReg(src)); break; - case LSHL: masm.shlq(asLongReg(dst)); break; - case LSHR: masm.sarq(asLongReg(dst)); break; - case LUSHR:masm.shrq(asLongReg(dst)); break; + case LSHL: assert asIntReg(src) == AMD64.rcx; masm.shlq(asLongReg(dst)); break; + case LSHR: assert asIntReg(src) == AMD64.rcx; masm.sarq(asLongReg(dst)); break; + case LUSHR: assert asIntReg(src) == AMD64.rcx; masm.shrq(asLongReg(dst)); break; case FADD: masm.addss(asFloatReg(dst), asFloatReg(src)); break; case FSUB: masm.subss(asFloatReg(dst), asFloatReg(src)); break; @@ -316,6 +315,8 @@ case DOR: masm.orpd(asDoubleReg(dst), asDoubleReg(src)); break; case DXOR: masm.xorpd(asDoubleReg(dst), asDoubleReg(src)); break; + case I2B: masm.movsxb(asIntReg(dst), asIntReg(src)); break; + case I2S: masm.movsxw(asIntReg(dst), asIntReg(src)); break; case I2L: masm.movslq(asLongReg(dst), asIntReg(src)); break; case F2D: masm.cvtss2sd(asDoubleReg(dst), asFloatReg(src)); break; case D2F: masm.cvtsd2ss(asFloatReg(dst), asDoubleReg(src)); break; @@ -400,46 +401,46 @@ case LSHR: masm.sarq(asLongReg(dst), tasm.asIntConst(src) & 63); break; case LUSHR:masm.shrq(asLongReg(dst), tasm.asIntConst(src) & 63); break; - case FADD: masm.addss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; - case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; - case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; - case FAND: masm.andps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break; - case FOR: masm.orps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break; - case FXOR: masm.xorps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break; - case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; + case FADD: masm.addss(asFloatReg(dst), (AMD64Address) tasm.asFloatConstRef(src)); break; + case FSUB: masm.subss(asFloatReg(dst), (AMD64Address) tasm.asFloatConstRef(src)); break; + case FMUL: masm.mulss(asFloatReg(dst), (AMD64Address) tasm.asFloatConstRef(src)); break; + case FAND: masm.andps(asFloatReg(dst), (AMD64Address) tasm.asFloatConstRef(src, 16)); break; + case FOR: masm.orps(asFloatReg(dst), (AMD64Address) tasm.asFloatConstRef(src, 16)); break; + case FXOR: masm.xorps(asFloatReg(dst), (AMD64Address) tasm.asFloatConstRef(src, 16)); break; + case FDIV: masm.divss(asFloatReg(dst), (AMD64Address) tasm.asFloatConstRef(src)); break; - case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; - case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; - case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; - case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; - case DAND: masm.andpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break; - case DOR: masm.orpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break; - case DXOR: masm.xorpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break; + case DADD: masm.addsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleConstRef(src)); break; + case DSUB: masm.subsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleConstRef(src)); break; + case DMUL: masm.mulsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleConstRef(src)); break; + case DDIV: masm.divsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleConstRef(src)); break; + case DAND: masm.andpd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleConstRef(src, 16)); break; + case DOR: masm.orpd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleConstRef(src, 16)); break; + case DXOR: masm.xorpd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleConstRef(src, 16)); break; default: throw GraalInternalError.shouldNotReachHere(); } } else { switch (opcode) { - case IADD: masm.addl(asIntReg(dst), tasm.asIntAddr(src)); break; - case ISUB: masm.subl(asIntReg(dst), tasm.asIntAddr(src)); break; - case IAND: masm.andl(asIntReg(dst), tasm.asIntAddr(src)); break; - case IOR: masm.orl(asIntReg(dst), tasm.asIntAddr(src)); break; - case IXOR: masm.xorl(asIntReg(dst), tasm.asIntAddr(src)); break; + case IADD: masm.addl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case ISUB: masm.subl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case IAND: masm.andl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case IOR: masm.orl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case IXOR: masm.xorl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; - case LADD: masm.addq(asLongReg(dst), tasm.asLongAddr(src)); break; - case LSUB: masm.subq(asLongReg(dst), tasm.asLongAddr(src)); break; - case LAND: masm.andq(asLongReg(dst), tasm.asLongAddr(src)); break; - case LOR: masm.orq(asLongReg(dst), tasm.asLongAddr(src)); break; - case LXOR: masm.xorq(asLongReg(dst), tasm.asLongAddr(src)); break; + case LADD: masm.addq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; + case LSUB: masm.subq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; + case LAND: masm.andq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; + case LOR: masm.orq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; + case LXOR: masm.xorq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; - case FADD: masm.addss(asFloatReg(dst), tasm.asFloatAddr(src)); break; - case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatAddr(src)); break; - case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatAddr(src)); break; - case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatAddr(src)); break; + case FADD: masm.addss(asFloatReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break; + case FSUB: masm.subss(asFloatReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break; + case FMUL: masm.mulss(asFloatReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break; + case FDIV: masm.divss(asFloatReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break; - case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; - case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; - case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; - case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; + case DADD: masm.addsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; + case DSUB: masm.subsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; + case DMUL: masm.mulsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; + case DDIV: masm.divsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; default: throw GraalInternalError.shouldNotReachHere(); } } @@ -455,10 +456,10 @@ tasm.stubs.add(slowPath); switch (result.getKind()) { case Int: masm.cmpl(asIntReg(result), Integer.MIN_VALUE); break; - case Long: masm.cmpq(asLongReg(result), tasm.asLongConstRef(Constant.forLong(java.lang.Long.MIN_VALUE))); break; + case Long: masm.cmpq(asLongReg(result), (AMD64Address) tasm.asLongConstRef(Constant.forLong(java.lang.Long.MIN_VALUE))); break; default: throw GraalInternalError.shouldNotReachHere(); } - masm.jcc(ConditionFlag.equal, slowPath.start); + masm.jcc(ConditionFlag.Equal, slowPath.start); masm.bind(slowPath.continuation); } @@ -477,13 +478,13 @@ public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { masm.bind(start); switch (x.getKind()) { - case Float: masm.ucomiss(asFloatReg(x), tasm.asFloatConstRef(Constant.FLOAT_0)); break; - case Double: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(Constant.DOUBLE_0)); break; + case Float: masm.ucomiss(asFloatReg(x), (AMD64Address) tasm.asFloatConstRef(Constant.FLOAT_0)); break; + case Double: masm.ucomisd(asDoubleReg(x), (AMD64Address) tasm.asDoubleConstRef(Constant.DOUBLE_0)); break; default: throw GraalInternalError.shouldNotReachHere(); } Label nan = new Label(); - masm.jcc(ConditionFlag.parity, nan); - masm.jcc(ConditionFlag.below, continuation); + masm.jcc(ConditionFlag.Parity, nan); + masm.jcc(ConditionFlag.Below, continuation); // input is > 0 -> return maxInt // result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java Mon Mar 04 10:00:49 2013 +0100 @@ -22,8 +22,8 @@ */ package com.oracle.graal.lir.amd64; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.lir.asm.*; @@ -34,10 +34,10 @@ } @Opcode private final IntrinsicOpcode opcode; - @Def protected Value result; - @Use({OperandFlag.REG, OperandFlag.ADDR}) protected Value input; + @Def protected AllocatableValue result; + @Use({OperandFlag.REG, OperandFlag.STACK}) protected AllocatableValue input; - public AMD64BitManipulationOp(IntrinsicOpcode opcode, Value result, Value input) { + public AMD64BitManipulationOp(IntrinsicOpcode opcode, AllocatableValue result, AllocatableValue input) { this.opcode = opcode; this.result = result; this.input = input; @@ -46,8 +46,8 @@ @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { Register dst = ValueUtil.asIntReg(result); - if (ValueUtil.isAddress(input)) { - Address src = ValueUtil.asAddress(input); + if (ValueUtil.isRegister(input)) { + Register src = ValueUtil.asRegister(input); switch (opcode) { case IPOPCNT: masm.popcntl(dst, src); @@ -66,7 +66,7 @@ break; } } else { - Register src = ValueUtil.asRegister(input); + AMD64Address src = (AMD64Address) tasm.asAddress(input); switch (opcode) { case IPOPCNT: masm.popcntl(dst, src);
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Mar 04 10:00:49 2013 +0100 @@ -45,9 +45,9 @@ @Temp protected Value[] temps; @State protected LIRFrameState state; - protected final Object callTarget; + protected final InvokeTarget callTarget; - public DirectCallOp(Object callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + public DirectCallOp(InvokeTarget callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { this.callTarget = callTarget; this.result = result; this.parameters = parameters; @@ -79,9 +79,9 @@ @Temp protected Value[] temps; @State protected LIRFrameState state; - protected final Object callTarget; + protected final InvokeTarget callTarget; - public IndirectCallOp(Object callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) { + public IndirectCallOp(InvokeTarget callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) { this.callTarget = callTarget; this.result = result; this.parameters = parameters; @@ -103,7 +103,7 @@ } } - public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object callTarget, LIRFrameState info) { + public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, InvokeTarget callTarget, LIRFrameState info) { int before = masm.codeBuffer.position(); if (callTarget instanceof RuntimeCallTarget) { long maxOffset = ((RuntimeCallTarget) callTarget).getMaxCallTargetOffset(); @@ -121,24 +121,24 @@ masm.call(); } int after = masm.codeBuffer.position(); - tasm.recordDirectCall(before, after, tasm.runtime.lookupCallTarget(callTarget), info); + tasm.recordDirectCall(before, after, callTarget, info); tasm.recordExceptionHandlers(after, info); masm.ensureUniquePC(); } - public static void directJmp(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target) { + public static void directJmp(TargetMethodAssembler tasm, AMD64MacroAssembler masm, InvokeTarget target) { int before = masm.codeBuffer.position(); masm.jmp(0, true); int after = masm.codeBuffer.position(); - tasm.recordDirectCall(before, after, tasm.runtime.lookupCallTarget(target), null); + tasm.recordDirectCall(before, after, target, null); masm.ensureUniquePC(); } - public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, Object callTarget, LIRFrameState info) { + public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) { int before = masm.codeBuffer.position(); masm.call(dst); int after = masm.codeBuffer.position(); - tasm.recordIndirectCall(before, after, tasm.runtime.lookupCallTarget(callTarget), info); + tasm.recordIndirectCall(before, after, callTarget, info); tasm.recordExceptionHandlers(after, info); masm.ensureUniquePC(); }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Mon Mar 04 10:00:49 2013 +0100 @@ -25,6 +25,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.graph.*; @@ -54,7 +55,6 @@ protected void verify() { super.verify(); assert (name().startsWith("I") && x.getKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) - || (name().startsWith("I") && x.getKind() == Kind.Jsr && y.getKind() == Kind.Jsr) || (name().startsWith("L") && x.getKind() == Kind.Long && y.getKind() == Kind.Long) || (name().startsWith("A") && x.getKind() == Kind.Object && y.getKind() == Kind.Object) || (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float) @@ -82,17 +82,17 @@ } else { throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons"); } - case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatConstRef(y)); break; - case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(y)); break; + case FCMP: masm.ucomiss(asFloatReg(x), (AMD64Address) tasm.asFloatConstRef(y)); break; + case DCMP: masm.ucomisd(asDoubleReg(x), (AMD64Address) tasm.asDoubleConstRef(y)); break; default: throw GraalInternalError.shouldNotReachHere(); } } else { switch (opcode) { - case ICMP: masm.cmpl(asIntReg(x), tasm.asIntAddr(y)); break; - case LCMP: masm.cmpq(asLongReg(x), tasm.asLongAddr(y)); break; - case ACMP: masm.cmpptr(asObjectReg(x), tasm.asObjectAddr(y)); break; - case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatAddr(y)); break; - case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleAddr(y)); break; + case ICMP: masm.cmpl(asIntReg(x), (AMD64Address) tasm.asIntAddr(y)); break; + case LCMP: masm.cmpq(asLongReg(x), (AMD64Address) tasm.asLongAddr(y)); break; + case ACMP: masm.cmpptr(asObjectReg(x), (AMD64Address) tasm.asObjectAddr(y)); break; + case FCMP: masm.ucomiss(asFloatReg(x), (AMD64Address) tasm.asFloatAddr(y)); break; + case DCMP: masm.ucomisd(asDoubleReg(x), (AMD64Address) tasm.asDoubleAddr(y)); break; default: throw GraalInternalError.shouldNotReachHere(); } }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Mon Mar 04 10:00:49 2013 +0100 @@ -26,8 +26,8 @@ import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.amd64.*; +import com.oracle.graal.amd64.AMD64Address.Scale; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Address.Scale; import com.oracle.graal.api.code.CompilationResult.JumpTable; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; @@ -162,13 +162,13 @@ long lc = keyConstants[i].asLong(); assert NumUtil.isInt(lc); masm.cmpl(intKey, (int) lc); - masm.jcc(ConditionFlag.equal, keyTargets[i].label()); + masm.jcc(ConditionFlag.Equal, keyTargets[i].label()); } } else if (key.getKind() == Kind.Long) { Register longKey = asLongReg(key); for (int i = 0; i < keyConstants.length; i++) { - masm.cmpq(longKey, tasm.asLongConstRef(keyConstants[i])); - masm.jcc(ConditionFlag.equal, keyTargets[i].label()); + masm.cmpq(longKey, (AMD64Address) tasm.asLongConstRef(keyConstants[i])); + masm.jcc(ConditionFlag.Equal, keyTargets[i].label()); } } else if (key.getKind() == Kind.Object) { Register intKey = asObjectReg(key); @@ -176,7 +176,7 @@ for (int i = 0; i < keyConstants.length; i++) { AMD64Move.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]); masm.cmpptr(intKey, temp); - masm.jcc(ConditionFlag.equal, keyTargets[i].label()); + masm.jcc(ConditionFlag.Equal, keyTargets[i].label()); } } else { throw new GraalInternalError("sequential switch only supported for int, long and object"); @@ -226,15 +226,15 @@ int highKey = highKeys[i]; if (lowKey == highKey) { masm.cmpl(asIntReg(key), lowKey); - masm.jcc(ConditionFlag.equal, keyTargets[i].label()); + masm.jcc(ConditionFlag.Equal, keyTargets[i].label()); skipLowCheck = false; } else { if (!skipLowCheck || (prevHighKey + 1) != lowKey) { masm.cmpl(asIntReg(key), lowKey); - masm.jcc(ConditionFlag.less, actualDefaultTarget); + masm.jcc(ConditionFlag.Less, actualDefaultTarget); } masm.cmpl(asIntReg(key), highKey); - masm.jcc(ConditionFlag.lessEqual, keyTargets[i].label()); + masm.jcc(ConditionFlag.LessEqual, keyTargets[i].label()); skipLowCheck = true; } prevHighKey = highKey; @@ -333,16 +333,16 @@ // Jump to default target if index is not within the jump table if (defaultTarget != null) { - masm.jcc(ConditionFlag.above, defaultTarget.label()); + masm.jcc(ConditionFlag.Above, defaultTarget.label()); } // Set scratch to address of jump table int leaPos = buf.position(); - masm.leaq(scratch, new Address(tasm.target.wordKind, AMD64.rip.asValue(), 0)); + masm.leaq(scratch, new AMD64Address(tasm.target.wordKind, AMD64.rip.asValue(), 0)); int afterLea = buf.position(); // Load jump table entry into scratch and jump to it - masm.movslq(value, new Address(Kind.Int, scratch.asValue(), value.asValue(), Scale.Times4, 0)); + masm.movslq(value, new AMD64Address(Kind.Int, scratch.asValue(), value.asValue(), Scale.Times4, 0)); masm.addq(scratch, value); masm.jmp(scratch); @@ -354,7 +354,7 @@ // Patch LEA instruction above now that we know the position of the jump table int jumpTablePos = buf.position(); buf.setPosition(leaPos); - masm.leaq(scratch, new Address(tasm.target.wordKind, AMD64.rip.asValue(), jumpTablePos - afterLea)); + masm.leaq(scratch, new AMD64Address(tasm.target.wordKind, AMD64.rip.asValue(), jumpTablePos - afterLea)); buf.setPosition(jumpTablePos); // Emit jump table entries @@ -374,15 +374,15 @@ } JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4); - tasm.targetMethod.addAnnotation(jt); + tasm.compilationResult.addAnnotation(jt); } private static void floatJcc(AMD64MacroAssembler masm, ConditionFlag condition, boolean unorderedIsTrue, Label label) { Label endLabel = new Label(); if (unorderedIsTrue && !trueOnUnordered(condition)) { - masm.jcc(ConditionFlag.parity, label); + masm.jcc(ConditionFlag.Parity, label); } else if (!unorderedIsTrue && trueOnUnordered(condition)) { - masm.jcc(ConditionFlag.parity, endLabel); + masm.jccb(ConditionFlag.Parity, endLabel); } masm.jcc(condition, label); masm.bind(endLabel); @@ -397,9 +397,9 @@ if (isFloat) { if (unorderedIsTrue && !trueOnUnordered(condition)) { - cmove(tasm, masm, result, ConditionFlag.parity, trueValue); + cmove(tasm, masm, result, ConditionFlag.Parity, trueValue); } else if (!unorderedIsTrue && trueOnUnordered(condition)) { - cmove(tasm, masm, result, ConditionFlag.parity, falseValue); + cmove(tasm, masm, result, ConditionFlag.Parity, falseValue); } } } @@ -413,9 +413,10 @@ default: throw GraalInternalError.shouldNotReachHere(); } } else { + AMD64Address addr = (AMD64Address) tasm.asAddress(other); switch (other.getKind()) { - case Int: masm.cmovl(cond, asRegister(result), tasm.asAddress(other)); break; - case Long: masm.cmovq(cond, asRegister(result), tasm.asAddress(other)); break; + case Int: masm.cmovl(cond, asRegister(result), addr); break; + case Long: masm.cmovq(cond, asRegister(result), addr); break; default: throw GraalInternalError.shouldNotReachHere(); } } @@ -423,45 +424,45 @@ private static ConditionFlag intCond(Condition cond) { switch (cond) { - case EQ: return ConditionFlag.equal; - case NE: return ConditionFlag.notEqual; - case LT: return ConditionFlag.less; - case LE: return ConditionFlag.lessEqual; - case GE: return ConditionFlag.greaterEqual; - case GT: return ConditionFlag.greater; - case BE: return ConditionFlag.belowEqual; - case AE: return ConditionFlag.aboveEqual; - case AT: return ConditionFlag.above; - case BT: return ConditionFlag.below; + case EQ: return ConditionFlag.Equal; + case NE: return ConditionFlag.NotEqual; + case LT: return ConditionFlag.Less; + case LE: return ConditionFlag.LessEqual; + case GE: return ConditionFlag.GreaterEqual; + case GT: return ConditionFlag.Greater; + case BE: return ConditionFlag.BelowEqual; + case AE: return ConditionFlag.AboveEqual; + case AT: return ConditionFlag.Above; + case BT: return ConditionFlag.Below; default: throw GraalInternalError.shouldNotReachHere(); } } private static ConditionFlag floatCond(Condition cond) { switch (cond) { - case EQ: return ConditionFlag.equal; - case NE: return ConditionFlag.notEqual; - case LT: return ConditionFlag.below; - case LE: return ConditionFlag.belowEqual; - case GE: return ConditionFlag.aboveEqual; - case GT: return ConditionFlag.above; + case EQ: return ConditionFlag.Equal; + case NE: return ConditionFlag.NotEqual; + case LT: return ConditionFlag.Below; + case LE: return ConditionFlag.BelowEqual; + case GE: return ConditionFlag.AboveEqual; + case GT: return ConditionFlag.Above; default: throw GraalInternalError.shouldNotReachHere(); } } private static boolean trueOnUnordered(ConditionFlag condition) { switch(condition) { - case aboveEqual: - case notEqual: - case above: - case less: - case overflow: + case AboveEqual: + case NotEqual: + case Above: + case Less: + case Overflow: return false; - case equal: - case belowEqual: - case below: - case greaterEqual: - case noOverflow: + case Equal: + case BelowEqual: + case Below: + case GreaterEqual: + case NoOverflow: return true; default: throw GraalInternalError.shouldNotReachHere();
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Mon Mar 04 10:00:49 2013 +0100 @@ -24,6 +24,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + import static java.lang.Double.*; import static java.lang.Float.*; @@ -38,11 +39,11 @@ import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.lir.asm.*; -// @formatter:off public class AMD64Move { @Opcode("MOVE") public static class SpillMoveOp extends AMD64LIRInstruction implements MoveOp { + @Def({REG, STACK}) protected Value result; @Use({REG, STACK, CONST}) protected Value input; @@ -60,15 +61,16 @@ public Value getInput() { return input; } + @Override public Value getResult() { return result; } } - @Opcode("MOVE") public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp { + @Def({REG, HINT}) protected Value result; @Use({REG, STACK, CONST}) protected Value input; @@ -86,15 +88,16 @@ public Value getInput() { return input; } + @Override public Value getResult() { return result; } } - @Opcode("MOVE") public static class MoveFromRegOp extends AMD64LIRInstruction implements MoveOp { + @Def({REG, STACK}) protected Value result; @Use({REG, CONST, HINT}) protected Value input; @@ -112,66 +115,201 @@ public Value getInput() { return input; } + @Override public Value getResult() { return result; } } + public abstract static class MemOp extends AMD64LIRInstruction { - public static class LoadOp extends AMD64LIRInstruction { - @Def({REG}) protected Value result; - @Use({ADDR}) protected Value address; + @Use({ADDR}) protected AMD64Address address; @State protected LIRFrameState state; - public LoadOp(Value result, Value address, LIRFrameState state) { - this.result = result; + public MemOp(AMD64Address address, LIRFrameState state) { this.address = address; this.state = state; } + protected abstract void emitMemAccess(AMD64MacroAssembler masm); + @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - load(tasm, masm, result, (Address) address, state); + if (state != null) { + tasm.recordImplicitException(masm.codeBuffer.position(), state); + } + emitMemAccess(masm); + } + } + + public static class LoadOp extends MemOp { + + @Def({REG}) protected AllocatableValue result; + + public LoadOp(AllocatableValue result, AMD64Address address, LIRFrameState state) { + super(address, state); + this.result = result; + } + + @Override + public void emitMemAccess(AMD64MacroAssembler masm) { + switch (address.getKind()) { + case Boolean: + case Byte: + masm.movsxb(asRegister(result), address); + break; + case Char: + masm.movzxl(asRegister(result), address); + break; + case Short: + masm.movswl(asRegister(result), address); + break; + case Int: + masm.movslq(asRegister(result), address); + break; + case Long: + masm.movq(asRegister(result), address); + break; + case Float: + masm.movflt(asFloatReg(result), address); + break; + case Double: + masm.movdbl(asDoubleReg(result), address); + break; + case Object: + masm.movq(asRegister(result), address); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } } } + public static class StoreOp extends MemOp { - public static class StoreOp extends AMD64LIRInstruction { - @Use({ADDR}) protected Value address; - @Use({REG, CONST}) protected Value input; - @State protected LIRFrameState state; + @Use({REG}) protected AllocatableValue input; - public StoreOp(Value address, Value input, LIRFrameState state) { - this.address = address; + public StoreOp(AMD64Address address, AllocatableValue input, LIRFrameState state) { + super(address, state); this.input = input; - this.state = state; } @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - store(tasm, masm, (Address) address, input, state); + public void emitMemAccess(AMD64MacroAssembler masm) { + assert isRegister(input); + switch (address.getKind()) { + case Boolean: + case Byte: + masm.movb(address, asRegister(input)); + break; + case Char: + case Short: + masm.movw(address, asRegister(input)); + break; + case Int: + masm.movl(address, asRegister(input)); + break; + case Long: + masm.movq(address, asRegister(input)); + break; + case Float: + masm.movflt(address, asFloatReg(input)); + break; + case Double: + masm.movsd(address, asDoubleReg(input)); + break; + case Object: + masm.movq(address, asRegister(input)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } } } + public static class StoreConstantOp extends MemOp { + + @Use({CONST}) protected Constant input; + + public StoreConstantOp(AMD64Address address, Constant input, LIRFrameState state) { + super(address, state); + this.input = input; + } + + @Override + public void emitMemAccess(AMD64MacroAssembler masm) { + switch (address.getKind()) { + case Boolean: + case Byte: + masm.movb(address, input.asInt() & 0xFF); + break; + case Char: + case Short: + masm.movw(address, input.asInt() & 0xFFFF); + break; + case Int: + masm.movl(address, input.asInt()); + break; + case Long: + if (NumUtil.isInt(input.asLong())) { + masm.movslq(address, (int) input.asLong()); + } else { + throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); + } + break; + case Float: + masm.movl(address, floatToRawIntBits(input.asFloat())); + break; + case Double: + throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); + case Object: + if (input.isNull()) { + masm.movptr(address, 0); + } else { + throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); + } + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + } public static class LeaOp extends AMD64LIRInstruction { - @Def({REG}) protected Value result; - @Use({ADDR, STACK, UNINITIALIZED}) protected Value address; - public LeaOp(Value result, Value address) { + @Def({REG}) protected AllocatableValue result; + @Use({ADDR, UNINITIALIZED}) protected AMD64Address address; + + public LeaOp(AllocatableValue result, AMD64Address address) { this.result = result; this.address = address; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.leaq(asLongReg(result), tasm.asAddress(address)); + masm.leaq(asLongReg(result), address); } } + public static class StackLeaOp extends AMD64LIRInstruction { + + @Def({REG}) protected AllocatableValue result; + @Use({STACK, UNINITIALIZED}) protected StackSlot slot; + + public StackLeaOp(AllocatableValue result, StackSlot slot) { + this.result = result; + this.slot = slot; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + masm.leaq(asLongReg(result), (AMD64Address) tasm.asAddress(slot)); + } + } public static class MembarOp extends AMD64LIRInstruction { + private final int barriers; public MembarOp(final int barriers) { @@ -184,9 +322,9 @@ } } + public static class NullCheckOp extends AMD64LIRInstruction { - public static class NullCheckOp extends AMD64LIRInstruction { - @Use protected Value input; + @Use protected AllocatableValue input; @State protected LIRFrameState state; public NullCheckOp(Variable input, LIRFrameState state) { @@ -201,15 +339,15 @@ } } - @Opcode("CAS") public static class CompareAndSwapOp extends AMD64LIRInstruction { - @Def protected Value result; - @Use({ADDR}) protected Value address; - @Use protected Value cmpValue; - @Use protected Value newValue; - public CompareAndSwapOp(Value result, Address address, Value cmpValue, Value newValue) { + @Def protected AllocatableValue result; + @Use({ADDR}) protected AMD64Address address; + @Use protected AllocatableValue cmpValue; + @Use protected AllocatableValue newValue; + + public CompareAndSwapOp(AllocatableValue result, AMD64Address address, AllocatableValue cmpValue, AllocatableValue newValue) { this.result = result; this.address = address; this.cmpValue = cmpValue; @@ -218,11 +356,10 @@ @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - compareAndSwap(tasm, masm, result, (Address) address, cmpValue, newValue); + compareAndSwap(tasm, masm, result, address, cmpValue, newValue); } } - public static void move(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Value input) { if (isRegister(input)) { if (isRegister(result)) { @@ -256,46 +393,80 @@ return; } switch (input.getKind()) { - case Jsr: - case Int: masm.movl(asRegister(result), asRegister(input)); break; - case Long: masm.movq(asRegister(result), asRegister(input)); break; - case Float: masm.movflt(asFloatReg(result), asFloatReg(input)); break; - case Double: masm.movdbl(asDoubleReg(result), asDoubleReg(input)); break; - case Object: masm.movq(asRegister(result), asRegister(input)); break; - default: throw GraalInternalError.shouldNotReachHere("kind=" + result.getKind()); + case Int: + masm.movl(asRegister(result), asRegister(input)); + break; + case Long: + masm.movq(asRegister(result), asRegister(input)); + break; + case Float: + masm.movflt(asFloatReg(result), asFloatReg(input)); + break; + case Double: + masm.movdbl(asDoubleReg(result), asDoubleReg(input)); + break; + case Object: + masm.movq(asRegister(result), asRegister(input)); + break; + default: + throw GraalInternalError.shouldNotReachHere("kind=" + result.getKind()); } } private static void reg2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Value input) { + AMD64Address dest = (AMD64Address) tasm.asAddress(result); switch (input.getKind()) { - case Jsr: - case Int: masm.movl(tasm.asAddress(result), asRegister(input)); break; - case Long: masm.movq(tasm.asAddress(result), asRegister(input)); break; - case Float: masm.movflt(tasm.asAddress(result), asFloatReg(input)); break; - case Double: masm.movsd(tasm.asAddress(result), asDoubleReg(input)); break; - case Object: masm.movq(tasm.asAddress(result), asRegister(input)); break; - default: throw GraalInternalError.shouldNotReachHere(); + case Int: + masm.movl(dest, asRegister(input)); + break; + case Long: + masm.movq(dest, asRegister(input)); + break; + case Float: + masm.movflt(dest, asFloatReg(input)); + break; + case Double: + masm.movsd(dest, asDoubleReg(input)); + break; + case Object: + masm.movq(dest, asRegister(input)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); } } private static void stack2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Value input) { + AMD64Address src = (AMD64Address) tasm.asAddress(input); switch (input.getKind()) { - case Jsr: - case Int: masm.movl(asRegister(result), tasm.asAddress(input)); break; - case Long: masm.movq(asRegister(result), tasm.asAddress(input)); break; - case Float: masm.movflt(asFloatReg(result), tasm.asAddress(input)); break; - case Double: masm.movdbl(asDoubleReg(result), tasm.asAddress(input)); break; - case Object: masm.movq(asRegister(result), tasm.asAddress(input)); break; - default: throw GraalInternalError.shouldNotReachHere(); + case Int: + masm.movl(asRegister(result), src); + break; + case Long: + masm.movq(asRegister(result), src); + break; + case Float: + masm.movflt(asFloatReg(result), src); + break; + case Double: + masm.movdbl(asDoubleReg(result), src); + break; + case Object: + masm.movq(asRegister(result), src); + break; + default: + throw GraalInternalError.shouldNotReachHere(); } } private static void const2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Constant input) { - // Note: we use the kind of the input operand (and not the kind of the result operand) because they don't match - // in all cases. For example, an object constant can be loaded to a long register when unsafe casts occurred (e.g., - // for a write barrier where arithmetic operations are then performed on the pointer). + /* + * Note: we use the kind of the input operand (and not the kind of the result operand) + * because they don't match in all cases. For example, an object constant can be loaded to a + * long register when unsafe casts occurred (e.g., for a write barrier where arithmetic + * operations are then performed on the pointer). + */ switch (input.getKind().getStackKind()) { - case Jsr: case Int: if (tasm.runtime.needsDataPatch(input)) { tasm.recordDataReferenceInCode(input, 0, true); @@ -321,7 +492,7 @@ assert !tasm.runtime.needsDataPatch(input); masm.xorps(asFloatReg(result), asFloatReg(result)); } else { - masm.movflt(asFloatReg(result), tasm.asFloatConstRef(input)); + masm.movflt(asFloatReg(result), (AMD64Address) tasm.asFloatConstRef(input)); } break; case Double: @@ -330,7 +501,7 @@ assert !tasm.runtime.needsDataPatch(input); masm.xorpd(asDoubleReg(result), asDoubleReg(result)); } else { - masm.movdbl(asDoubleReg(result), tasm.asDoubleConstRef(input)); + masm.movdbl(asDoubleReg(result), (AMD64Address) tasm.asDoubleConstRef(input)); } break; case Object: @@ -343,7 +514,7 @@ tasm.recordDataReferenceInCode(input, 0, true); masm.movq(asRegister(result), 0xDEADDEADDEADDEADL); } else { - masm.movq(asRegister(result), tasm.recordDataReferenceInCode(input, 0, false)); + masm.movq(asRegister(result), (AMD64Address) tasm.recordDataReferenceInCode(input, 0, false)); } break; default: @@ -353,15 +524,23 @@ private static void const2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Constant input) { assert !tasm.runtime.needsDataPatch(input); + AMD64Address dest = (AMD64Address) tasm.asAddress(result); switch (input.getKind().getStackKind()) { - case Jsr: - case Int: masm.movl(tasm.asAddress(result), input.asInt()); break; - case Long: masm.movlong(tasm.asAddress(result), input.asLong()); break; - case Float: masm.movl(tasm.asAddress(result), floatToRawIntBits(input.asFloat())); break; - case Double: masm.movlong(tasm.asAddress(result), doubleToRawLongBits(input.asDouble())); break; + case Int: + masm.movl(dest, input.asInt()); + break; + case Long: + masm.movlong(dest, input.asLong()); + break; + case Float: + masm.movl(dest, floatToRawIntBits(input.asFloat())); + break; + case Double: + masm.movlong(dest, doubleToRawLongBits(input.asDouble())); + break; case Object: if (input.isNull()) { - masm.movlong(tasm.asAddress(result), 0L); + masm.movlong(dest, 0L); } else { throw GraalInternalError.shouldNotReachHere("Non-null object constants must be in register"); } @@ -371,88 +550,22 @@ } } - - public static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Address loadAddr, LIRFrameState info) { - if (info != null) { - tasm.recordImplicitException(masm.codeBuffer.position(), info); - } - switch (loadAddr.getKind()) { - case Boolean: - case Byte: masm.movsxb(asRegister(result), loadAddr); break; - case Char: masm.movzxl(asRegister(result), loadAddr); break; - case Short: masm.movswl(asRegister(result), loadAddr); break; - case Int: masm.movslq(asRegister(result), loadAddr); break; - case Long: masm.movq(asRegister(result), loadAddr); break; - case Float: masm.movflt(asFloatReg(result), loadAddr); break; - case Double: masm.movdbl(asDoubleReg(result), loadAddr); break; - case Object: masm.movq(asRegister(result), loadAddr); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - } - - public static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Address storeAddr, Value input, LIRFrameState info) { - if (info != null) { - tasm.recordImplicitException(masm.codeBuffer.position(), info); - } - - if (isRegister(input)) { - switch (storeAddr.getKind()) { - case Boolean: - case Byte: masm.movb(storeAddr, asRegister(input)); break; - case Char: - case Short: masm.movw(storeAddr, asRegister(input)); break; - case Int: masm.movl(storeAddr, asRegister(input)); break; - case Long: masm.movq(storeAddr, asRegister(input)); break; - case Float: masm.movflt(storeAddr, asFloatReg(input)); break; - case Double: masm.movsd(storeAddr, asDoubleReg(input)); break; - case Object: masm.movq(storeAddr, asRegister(input)); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - } else if (isConstant(input)) { - Constant c = (Constant) input; - switch (storeAddr.getKind()) { - case Boolean: - case Byte: masm.movb(storeAddr, c.asInt() & 0xFF); break; - case Char: - case Short: masm.movw(storeAddr, c.asInt() & 0xFFFF); break; - case Jsr: - case Int: masm.movl(storeAddr, c.asInt()); break; - case Long: - if (NumUtil.isInt(c.asLong())) { - masm.movslq(storeAddr, (int) c.asLong()); - } else { - throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); - } - break; - case Float: masm.movl(storeAddr, floatToRawIntBits(c.asFloat())); break; - case Double: throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); - case Object: - if (c.isNull()) { - masm.movptr(storeAddr, 0); - } else { - throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); - } - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - - } else { - throw GraalInternalError.shouldNotReachHere(); - } - } - - protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Address address, Value cmpValue, Value newValue) { + protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64Address address, AllocatableValue cmpValue, AllocatableValue newValue) { assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax; if (tasm.target.isMP) { masm.lock(); } switch (cmpValue.getKind()) { - case Int: masm.cmpxchgl(asRegister(newValue), address); break; + case Int: + masm.cmpxchgl(asRegister(newValue), address); + break; case Long: - case Object: masm.cmpxchgq(asRegister(newValue), address); break; - default: throw GraalInternalError.shouldNotReachHere(); + case Object: + masm.cmpxchgq(asRegister(newValue), address); + break; + default: + throw GraalInternalError.shouldNotReachHere(); } } }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java Mon Mar 04 10:00:49 2013 +0100 @@ -25,6 +25,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.graph.*; @@ -77,10 +78,10 @@ } else { switch (x.getKind()) { case Int: - masm.testl(asIntReg(x), tasm.asIntAddr(y)); + masm.testl(asIntReg(x), (AMD64Address) tasm.asIntAddr(y)); break; case Long: - masm.testq(asLongReg(x), tasm.asLongAddr(y)); + masm.testq(asLongReg(x), (AMD64Address) tasm.asLongAddr(y)); break; default: throw GraalInternalError.shouldNotReachHere();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,297 @@ +/* + * 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.lir.ptx; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.ptx.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +// @formatter:off +public enum PTXArithmetic { + IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, + LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR, + FADD, FSUB, FMUL, FDIV, FAND, FOR, FXOR, + DADD, DSUB, DMUL, DDIV, DAND, DOR, DXOR, + INEG, LNEG, + I2L, L2I, I2B, I2C, I2S, + F2D, D2F, + I2F, I2D, F2I, D2I, + L2F, L2D, F2L, D2L, + MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L; + + + public static class Op1Reg extends PTXLIRInstruction { + @Opcode private final PTXArithmetic opcode; + @Def({REG, HINT}) protected Value result; + @Use({REG}) protected Value x; + + public Op1Reg(PTXArithmetic opcode, Value result, Value x) { + this.opcode = opcode; + this.result = result; + this.x = x; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + emit(tasm, masm, opcode, result, x, null); + } + } + + public static class Op1Stack extends PTXLIRInstruction { + @Opcode private final PTXArithmetic opcode; + @Def({REG, HINT}) protected Value result; + @Use({REG, STACK, CONST}) protected Value x; + + public Op1Stack(PTXArithmetic opcode, Value result, Value x) { + this.opcode = opcode; + this.result = result; + this.x = x; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + emit(tasm, masm, opcode, result, x, null); + } + } + + public static class Op2Stack extends PTXLIRInstruction { + @Opcode private final PTXArithmetic opcode; + @Def({REG, HINT}) protected Value result; + @Use({REG, STACK, CONST}) protected Value x; + @Alive({REG, STACK, CONST}) protected Value y; + + public Op2Stack(PTXArithmetic opcode, Value result, Value x, Value y) { + this.opcode = opcode; + this.result = result; + this.x = x; + this.y = y; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + emit(tasm, masm, opcode, result, x, y, null); + } + + @Override + public void verify() { + super.verify(); + verifyKind(opcode, result, x, y); + } + } + + public static class Op2Reg extends PTXLIRInstruction { + @Opcode private final PTXArithmetic opcode; + @Def({REG, HINT}) protected Value result; + @Use({REG, STACK, CONST}) protected Value x; + @Alive({REG, CONST}) protected Value y; + + public Op2Reg(PTXArithmetic opcode, Value result, Value x, Value y) { + this.opcode = opcode; + this.result = result; + this.x = x; + this.y = y; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + emit(tasm, masm, opcode, result, x, y, null); + } + + @Override + public void verify() { + super.verify(); + verifyKind(opcode, result, x, y); + } + } + + public static class Op2RegCommutative extends PTXLIRInstruction { + @Opcode private final PTXArithmetic opcode; + @Def({REG, HINT}) protected Value result; + @Use({REG, STACK, CONST}) protected Value x; + @Use({REG, CONST}) protected Value y; + + public Op2RegCommutative(PTXArithmetic opcode, Value result, Value x, Value y) { + this.opcode = opcode; + this.result = result; + this.x = x; + this.y = y; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + if (sameRegister(result, y)) { + emit(tasm, masm, opcode, result, x, null); + } else { + PTXMove.move(tasm, masm, result, x); + emit(tasm, masm, opcode, result, y, null); + } + } + + @Override + protected void verify() { + super.verify(); + verifyKind(opcode, result, x, y); + } + } + + public static class ShiftOp extends PTXLIRInstruction { + @Opcode private final PTXArithmetic opcode; + @Def({REG, HINT}) protected Value result; + @Use({REG, STACK, CONST}) protected Value x; + @Alive({REG, CONST}) protected Value y; + + public ShiftOp(PTXArithmetic opcode, Value result, Value x, Value y) { + this.opcode = opcode; + this.result = result; + this.x = x; + this.y = y; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + emit(tasm, masm, opcode, result, x, y, null); + } + + @Override + public void verify() { + super.verify(); + verifyKind(opcode, result, x, x); + assert y.getKind().getStackKind() == Kind.Int; + } + } + + public static class DivOp extends PTXLIRInstruction { + @Opcode private final PTXArithmetic opcode; + @Def protected Value result; + @Use protected Value x; + @Alive protected Value y; + @State protected LIRFrameState state; + + public DivOp(PTXArithmetic opcode, Value result, Value x, Value y, LIRFrameState state) { + this.opcode = opcode; + this.result = result; + this.x = x; + this.y = y; + this.state = state; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + emit(tasm, masm, opcode, result, y, state); + } + + @Override + protected void verify() { + super.verify(); + verifyKind(opcode, result, x, y); + } + } + + + @SuppressWarnings("unused") + protected static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value result) { + switch (opcode) { + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src, LIRFrameState info) { + int exceptionOffset = -1; + if (isRegister(src)) { + Register a = asIntReg(src); + Register d = asIntReg(dst); + switch (opcode) { + case INEG: masm.neg_s32(d, a); break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } else if (isConstant(src)) { + switch (opcode) { + case ISUB: masm.sub_s32(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break; + case IAND: masm.and_b32(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } else { + switch (opcode) { + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + if (info != null) { + assert exceptionOffset != -1; + tasm.recordImplicitException(exceptionOffset, info); + } + } + + public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) { + int exceptionOffset = -1; + if (isConstant(src1)) { + int a = tasm.asIntConst(src1); + Register b = asIntReg(src2); + Register d = asIntReg(dst); + switch (opcode) { + case ISUB: masm.sub_s32(d, a, b); break; + case IAND: masm.and_b32(d, b, a); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } else if (isConstant(src2)) { + Register a = asIntReg(src1); + int b = tasm.asIntConst(src2); + Register d = asIntReg(dst); + switch (opcode) { + case IADD: masm.add_s32(d, a, b); break; + case IAND: masm.and_b32(d, a, b); break; + case IUSHR: masm.shr_u32(d, a, b); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } else { + Register a = asIntReg(src1); + Register b = asIntReg(src2); + Register d = asIntReg(dst); + switch (opcode) { + case IADD: masm.add_s32(d, a, b); break; + case ISUB: masm.sub_s32(d, a, b); break; + case IMUL: masm.mul_s32(d, a, b); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + if (info != null) { + assert exceptionOffset != -1; + tasm.recordImplicitException(exceptionOffset, info); + } + } + + private static void verifyKind(PTXArithmetic opcode, Value result, Value x, Value y) { + assert (opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) + || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long) + || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float) + || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,62 @@ +/* + * 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.lir.ptx; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.ptx.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.asm.*; + +public class PTXBitManipulationOp extends PTXLIRInstruction { + + public enum IntrinsicOpcode { + IPOPCNT, LPOPCNT, IBSR, LBSR, BSF; + } + + @Opcode private final IntrinsicOpcode opcode; + @Def protected Value result; + @Use({OperandFlag.REG, OperandFlag.ADDR}) protected Value input; + + public PTXBitManipulationOp(IntrinsicOpcode opcode, Value result, Value input) { + this.opcode = opcode; + this.result = result; + this.input = input; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + Register dst = ValueUtil.asIntReg(result); + Register src = ValueUtil.asRegister(input); + switch (opcode) { + case IPOPCNT: + masm.popc_b32(dst, src); + break; + case LPOPCNT: + masm.popc_b64(dst, src); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCode.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,40 @@ +/* + * 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.lir.ptx; + +import com.oracle.graal.asm.ptx.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +/** + * Convenience class to provide PTXAssembler for the {@link #emitCode} method. + */ +public abstract class PTXCode implements LIR.Code { + + @Override + public final void emitCode(TargetMethodAssembler tasm) { + emitCode(tasm, (PTXAssembler) tasm.asm); + } + + public abstract void emitCode(TargetMethodAssembler tasm, PTXAssembler masm); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,226 @@ +/* + * 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.ptx; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.ptx.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.calc.*; + +public enum PTXCompare { + ICMP, LCMP, ACMP, FCMP, DCMP; + + public static class CompareOp extends PTXLIRInstruction { + + @Opcode private final PTXCompare opcode; + @Use({REG}) protected Value x; + @Use({REG, STACK, CONST}) protected Value y; + private final Condition condition; + + public CompareOp(PTXCompare opcode, Condition condition, Value x, Value y) { + this.opcode = opcode; + this.condition = condition; + this.x = x; + this.y = y; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + emit(tasm, masm, opcode, condition, x, y); + } + + @Override + protected void verify() { + super.verify(); + assert (name().startsWith("I") && x.getKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || (name().startsWith("L") && x.getKind() == Kind.Long && y.getKind() == Kind.Long) || + (name().startsWith("A") && x.getKind() == Kind.Object && y.getKind() == Kind.Object) || + (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float) || (name().startsWith("D") && x.getKind() == Kind.Double && y.getKind() == Kind.Double); + } + } + + public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXCompare opcode, Condition condition, Value x, Value y) { + if (isConstant(x)) { + int a = tasm.asIntConst(x); + Register b = asIntReg(y); + switch (opcode) { + case ICMP: + emitCompareConstReg(masm, condition, a, b); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } else if (isConstant(y)) { + Register a = asIntReg(x); + int b = tasm.asIntConst(y); + switch (opcode) { + case ICMP: + emitCompareRegConst(masm, condition, a, b); + break; + case ACMP: + if (((Constant) y).isNull()) { + switch (condition) { + case EQ: + masm.setp_eq_s32(a, b); + break; + case NE: + masm.setp_ne_s32(a, b); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } else { + throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons"); + } + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } else { + Register a = asIntReg(x); + Register b = asIntReg(y); + switch (opcode) { + case ICMP: + emitCompareRegReg(masm, condition, a, b); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + } + + private static void emitCompareConstReg(PTXAssembler masm, Condition condition, int a, Register b) { + switch (condition) { + case EQ: + masm.setp_eq_s32(a, b); + break; + case NE: + masm.setp_ne_s32(a, b); + break; + case LT: + masm.setp_lt_s32(a, b); + break; + case LE: + masm.setp_le_s32(a, b); + break; + case GT: + masm.setp_gt_s32(a, b); + break; + case GE: + masm.setp_ge_s32(a, b); + break; + case AT: + masm.setp_gt_u32(a, b); + break; + case AE: + masm.setp_ge_u32(a, b); + break; + case BT: + masm.setp_lt_u32(a, b); + break; + case BE: + masm.setp_le_u32(a, b); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + private static void emitCompareRegConst(PTXAssembler masm, Condition condition, Register a, int b) { + switch (condition) { + case EQ: + masm.setp_eq_s32(a, b); + break; + case NE: + masm.setp_ne_s32(a, b); + break; + case LT: + masm.setp_lt_s32(a, b); + break; + case LE: + masm.setp_le_s32(a, b); + break; + case GT: + masm.setp_gt_s32(a, b); + break; + case GE: + masm.setp_ge_s32(a, b); + break; + case AT: + masm.setp_gt_u32(a, b); + break; + case AE: + masm.setp_ge_u32(a, b); + break; + case BT: + masm.setp_lt_u32(a, b); + break; + case BE: + masm.setp_le_u32(a, b); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + private static void emitCompareRegReg(PTXAssembler masm, Condition condition, Register a, Register b) { + switch (condition) { + case EQ: + masm.setp_eq_s32(a, b); + break; + case NE: + masm.setp_ne_s32(a, b); + break; + case LT: + masm.setp_lt_s32(a, b); + break; + case LE: + masm.setp_le_s32(a, b); + break; + case GT: + masm.setp_gt_s32(a, b); + break; + case GE: + masm.setp_ge_s32(a, b); + break; + case AT: + masm.setp_gt_u32(a, b); + break; + case AE: + masm.setp_ge_u32(a, b); + break; + case BT: + masm.setp_lt_u32(a, b); + break; + case BE: + masm.setp_le_u32(a, b); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,85 @@ +/* + * 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.lir.ptx; + +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.asm.ptx.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.calc.*; + +public class PTXControlFlow { + + public static class ReturnOp extends PTXLIRInstruction { + + @Use({REG, ILLEGAL}) protected Value x; + + public ReturnOp(Value x) { + this.x = x; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + if (tasm.frameContext != null) { + tasm.frameContext.leave(tasm); + } + masm.exit(); + } + } + + public static class BranchOp extends PTXLIRInstruction implements StandardOp.BranchOp { + + protected Condition condition; + protected LabelRef destination; + @State protected LIRFrameState state; + + public BranchOp(Condition condition, LabelRef destination, LIRFrameState state) { + this.condition = condition; + this.destination = destination; + this.state = state; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + masm.at(); + Label l = destination.label(); + l.addPatchAt(tasm.asm.codeBuffer.position()); + String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET; + masm.bra(target); + } + + @Override + public LabelRef destination() { + return destination; + } + + @Override + public void negate(LabelRef newDestination) { + destination = newDestination; + condition = condition.negate(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXLIRInstruction.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,40 @@ +/* + * 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.lir.ptx; + +import com.oracle.graal.asm.ptx.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +/** + * Convenience class to provide PTXAssembler for the {@link #emitCode} method. + */ +public abstract class PTXLIRInstruction extends LIRInstruction { + + @Override + public final void emitCode(TargetMethodAssembler tasm) { + emitCode(tasm, (PTXAssembler) tasm.asm); + } + + public abstract void emitCode(TargetMethodAssembler tasm, PTXAssembler masm); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,282 @@ +/* + * 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.lir.ptx; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.ptx.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.StandardOp.MoveOp; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.ptx.*; + +public class PTXMove { + + @Opcode("MOVE") + public static class SpillMoveOp extends PTXLIRInstruction implements MoveOp { + + @Def({REG, STACK}) protected Value result; + @Use({REG, STACK, CONST}) protected Value input; + + public SpillMoveOp(Value result, Value input) { + this.result = result; + this.input = input; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + move(tasm, masm, getResult(), getInput()); + } + + @Override + public Value getInput() { + return input; + } + + @Override + public Value getResult() { + return result; + } + } + + @Opcode("MOVE") + public static class MoveToRegOp extends PTXLIRInstruction implements MoveOp { + + @Def({REG, HINT}) protected Value result; + @Use({REG, STACK, CONST}) protected Value input; + + public MoveToRegOp(Value result, Value input) { + this.result = result; + this.input = input; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + move(tasm, masm, getResult(), getInput()); + } + + @Override + public Value getInput() { + return input; + } + + @Override + public Value getResult() { + return result; + } + } + + @Opcode("MOVE") + public static class MoveFromRegOp extends PTXLIRInstruction implements MoveOp { + + @Def({REG, STACK}) protected Value result; + @Use({REG, CONST, HINT}) protected Value input; + + public MoveFromRegOp(Value result, Value input) { + this.result = result; + this.input = input; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + move(tasm, masm, getResult(), getInput()); + } + + @Override + public Value getInput() { + return input; + } + + @Override + public Value getResult() { + return result; + } + } + + public static class LoadOp extends PTXLIRInstruction { + + @Def({REG}) protected AllocatableValue result; + @Use({ADDR}) protected PTXAddress address; + @State protected LIRFrameState state; + + public LoadOp(AllocatableValue result, PTXAddress address, LIRFrameState state) { + this.result = result; + this.address = address; + this.state = state; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + Register a = asRegister(address.getBase()); + long immOff = address.getDisplacement(); + switch (address.getKind()) { + case Int: + masm.ld_global_s32(asRegister(result), a, immOff); + break; + case Object: + masm.ld_global_u32(asRegister(result), a, immOff); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + } + + public static class StoreOp extends PTXLIRInstruction { + + @Use({ADDR}) protected PTXAddress address; + @Use({REG}) protected AllocatableValue input; + @State protected LIRFrameState state; + + public StoreOp(PTXAddress address, AllocatableValue input, LIRFrameState state) { + this.address = address; + this.input = input; + this.state = state; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + Register a = asRegister(address.getBase()); + long immOff = address.getDisplacement(); + + assert isRegister(input); + switch (address.getKind()) { + case Int: + masm.st_global_s32(a, immOff, asRegister(input)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + } + + public static class LeaOp extends PTXLIRInstruction { + + @Def({REG}) protected AllocatableValue result; + @Use({ADDR, UNINITIALIZED}) protected PTXAddress address; + + public LeaOp(AllocatableValue result, PTXAddress address) { + this.result = result; + this.address = address; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + throw new InternalError("NYI"); + } + } + + public static class StackLeaOp extends PTXLIRInstruction { + + @Def({REG}) protected AllocatableValue result; + @Use({STACK, UNINITIALIZED}) protected StackSlot slot; + + public StackLeaOp(AllocatableValue result, StackSlot slot) { + this.result = result; + this.slot = slot; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + throw new InternalError("NYI"); + } + } + + @Opcode("CAS") + public static class CompareAndSwapOp extends PTXLIRInstruction { + + @Def protected AllocatableValue result; + @Use({ADDR}) protected PTXAddress address; + @Use protected AllocatableValue cmpValue; + @Use protected AllocatableValue newValue; + + public CompareAndSwapOp(AllocatableValue result, PTXAddress address, AllocatableValue cmpValue, AllocatableValue newValue) { + this.result = result; + this.address = address; + this.cmpValue = cmpValue; + this.newValue = newValue; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + compareAndSwap(tasm, masm, result, address, cmpValue, newValue); + } + } + + public static void move(TargetMethodAssembler tasm, PTXAssembler masm, Value result, Value input) { + if (isRegister(input)) { + if (isRegister(result)) { + reg2reg(masm, result, input); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } else if (isConstant(input)) { + if (isRegister(result)) { + const2reg(tasm, masm, result, (Constant) input); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + + private static void reg2reg(PTXAssembler masm, Value result, Value input) { + if (asRegister(input).equals(asRegister(result))) { + return; + } + switch (input.getKind()) { + case Int: + masm.mov_s32(asRegister(result), asRegister(input)); + break; + case Object: + masm.mov_u64(asRegister(result), asRegister(input)); + break; + default: + throw GraalInternalError.shouldNotReachHere("kind=" + result.getKind()); + } + } + + private static void const2reg(TargetMethodAssembler tasm, PTXAssembler masm, Value result, Constant input) { + switch (input.getKind().getStackKind()) { + case Int: + if (tasm.runtime.needsDataPatch(input)) { + tasm.recordDataReferenceInCode(input, 0, true); + } + masm.mov_s32(asRegister(result), input.asInt()); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @SuppressWarnings("unused") + protected static void compareAndSwap(TargetMethodAssembler tasm, PTXAssembler masm, AllocatableValue result, PTXAddress address, AllocatableValue cmpValue, AllocatableValue newValue) { + throw new InternalError("NYI"); + } +}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java Mon Mar 04 10:00:49 2013 +0100 @@ -347,28 +347,4 @@ } } } - - /** - * Clears the specified location as a reference in the reference map of the debug information. - * The tracked location can be a {@link RegisterValue} or a {@link StackSlot}. Note that a - * {@link Constant} is automatically tracked. - * - * @param location The location to be removed from the reference map. - * @param registerRefMap A register reference map, as created by {@link #initRegisterRefMap()}. - * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}. - */ - public void clearReference(Value location, BitSet registerRefMap, BitSet frameRefMap) { - if (location.getKind() == Kind.Object) { - if (location instanceof RegisterValue) { - registerRefMap.clear(asRegister(location).number); - } else if (isStackSlot(location)) { - int index = frameRefMapIndex(asStackSlot(location)); - if (index < frameRefMap.size()) { - frameRefMap.clear(index); - } - } else { - assert isConstant(location); - } - } - } }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Mon Mar 04 10:00:49 2013 +0100 @@ -181,6 +181,11 @@ ILLEGAL, /** + * The value can be {@link AllocatableValue#UNUSED}. + */ + UNUSED, + + /** * The register allocator should try to assign a certain register to improve code quality. * Use {@link LIRInstruction#forEachRegisterHint} to access the register hints. */
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Mon Mar 04 10:00:49 2013 +0100 @@ -361,8 +361,10 @@ private static void doAddress(Address address, OperandMode mode, EnumSet<OperandFlag> flags, ValueProcedure proc) { assert flags.contains(OperandFlag.ADDR); - address.setBase(proc.doValue(address.getBase(), mode, LIRInstruction.ADDRESS_FLAGS)); - address.setIndex(proc.doValue(address.getIndex(), mode, LIRInstruction.ADDRESS_FLAGS)); + Value[] components = address.components(); + for (int i = 0; i < components.length; i++) { + components[i] = proc.doValue(components[i], mode, LIRInstruction.ADDRESS_FLAGS); + } } public final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, ValueProcedure proc) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Mon Mar 04 10:00:49 2013 +0100 @@ -232,7 +232,8 @@ private static Value allowed(Object op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) { if ((isVariable(value) && flags.contains(OperandFlag.REG)) || (isRegister(value) && flags.contains(OperandFlag.REG)) || (isStackSlot(value) && flags.contains(OperandFlag.STACK)) || - (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) || (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) { + (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) || (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL)) || + (value == AllocatableValue.UNUSED && flags.contains(OperandFlag.UNUSED))) { return value; } TTY.println("instruction %s", op);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Mon Mar 04 10:00:49 2013 +0100 @@ -33,8 +33,6 @@ */ public class StandardOp { - private static Value[] EMPTY = new Value[0]; - /** * Marker interface for LIR ops that can fall through to the next operation, like a switch * statement. setFallThroughTarget(null) can be used to make the operation fall through to the @@ -99,24 +97,6 @@ } } - public static class PhiJumpOp extends JumpOp { - - @Alive({REG, STACK, CONST}) protected Value[] phiInputs; - - public PhiJumpOp(LabelRef destination, Value[] phiInputs) { - super(destination, null); - this.phiInputs = phiInputs; - } - - public void markResolved() { - phiInputs = EMPTY; - } - - public Value[] getPhiInputs() { - return phiInputs; - } - } - /** * Marker interface for a LIR operation that is a conditional jump to {@link #destination()}. * Conditional jumps may be negated or optimized away after register allocation.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java Mon Mar 04 10:00:49 2013 +0100 @@ -29,7 +29,7 @@ * Represents a value that is yet to be bound to a machine location (such as a {@link RegisterValue} * or {@link StackSlot}) by a register allocator. */ -public final class Variable extends Value { +public final class Variable extends AllocatableValue { private static final long serialVersionUID = 4507578431686109809L;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Mon Mar 04 10:00:49 2013 +0100 @@ -48,7 +48,7 @@ } public final AbstractAssembler asm; - public final CompilationResult targetMethod; + public final CompilationResult compilationResult; public final TargetDescription target; public final CodeCacheProvider runtime; public final FrameMap frameMap; @@ -65,7 +65,6 @@ public final FrameContext frameContext; private List<ExceptionInfo> exceptionInfoList; - private int lastSafepointPos; public TargetMethodAssembler(TargetDescription target, CodeCacheProvider runtime, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext, List<Code> stubs) { this.target = target; @@ -73,52 +72,47 @@ this.frameMap = frameMap; this.stubs = stubs; this.asm = asm; - this.targetMethod = new CompilationResult(); + this.compilationResult = new CompilationResult(); this.frameContext = frameContext; - // 0 is a valid pc for safepoints in template methods - this.lastSafepointPos = -1; } public void setFrameSize(int frameSize) { - targetMethod.setFrameSize(frameSize); + compilationResult.setFrameSize(frameSize); } private static final CompilationResult.Mark[] NO_REFS = {}; public CompilationResult.Mark recordMark(Object id) { - return targetMethod.recordMark(asm.codeBuffer.position(), id, NO_REFS); + return compilationResult.recordMark(asm.codeBuffer.position(), id, NO_REFS); } public CompilationResult.Mark recordMark(Object id, CompilationResult.Mark... references) { - return targetMethod.recordMark(asm.codeBuffer.position(), id, references); + return compilationResult.recordMark(asm.codeBuffer.position(), id, references); } public void blockComment(String s) { - targetMethod.addAnnotation(new CompilationResult.CodeComment(asm.codeBuffer.position(), s)); + compilationResult.addAnnotation(new CompilationResult.CodeComment(asm.codeBuffer.position(), s)); } public CompilationResult finishTargetMethod(Object name, boolean isStub) { // Install code, data and frame size - targetMethod.setTargetCode(asm.codeBuffer.close(false), asm.codeBuffer.position()); + compilationResult.setTargetCode(asm.codeBuffer.close(false), asm.codeBuffer.position()); // Record exception handlers if they exist if (exceptionInfoList != null) { for (ExceptionInfo ei : exceptionInfoList) { int codeOffset = ei.codeOffset; - targetMethod.recordExceptionHandler(codeOffset, ei.exceptionEdge.label().position()); + compilationResult.recordExceptionHandler(codeOffset, ei.exceptionEdge.label().position()); } } - // Set the info on callee-saved registers - targetMethod.setCalleeSaveLayout(frameMap.registerConfig.getCalleeSaveLayout()); - Debug.metric("TargetMethods").increment(); - Debug.metric("CodeBytesEmitted").add(targetMethod.getTargetCodeSize()); - Debug.metric("SafepointsEmitted").add(targetMethod.getSafepoints().size()); - Debug.metric("DataPatches").add(targetMethod.getDataReferences().size()); - Debug.metric("ExceptionHandlersEmitted").add(targetMethod.getExceptionHandlers().size()); + Debug.metric("CodeBytesEmitted").add(compilationResult.getTargetCodeSize()); + Debug.metric("SafepointsEmitted").add(compilationResult.getSafepoints().size()); + Debug.metric("DataPatches").add(compilationResult.getDataReferences().size()); + Debug.metric("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size()); Debug.log("Finished target method %s, isStub %b", name, isStub); - return targetMethod; + return compilationResult; } public void recordExceptionHandlers(int pcOffset, LIRFrameState info) { @@ -135,45 +129,33 @@ public void recordImplicitException(int pcOffset, LIRFrameState info) { // record an implicit exception point if (info != null) { - assert lastSafepointPos < pcOffset : lastSafepointPos + "<" + pcOffset; - lastSafepointPos = pcOffset; - targetMethod.recordSafepoint(pcOffset, info.debugInfo()); + compilationResult.recordSafepoint(pcOffset, info.debugInfo()); assert info.exceptionEdge == null; } } - public void recordDirectCall(int posBefore, int posAfter, Object callTarget, LIRFrameState info) { + public void recordDirectCall(int posBefore, int posAfter, InvokeTarget callTarget, LIRFrameState info) { DebugInfo debugInfo = info != null ? info.debugInfo() : null; - assert lastSafepointPos < posAfter; - lastSafepointPos = posAfter; - targetMethod.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, true); + compilationResult.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, true); } - public void recordIndirectCall(int posBefore, int posAfter, Object callTarget, LIRFrameState info) { + public void recordIndirectCall(int posBefore, int posAfter, InvokeTarget callTarget, LIRFrameState info) { DebugInfo debugInfo = info != null ? info.debugInfo() : null; - assert lastSafepointPos < posAfter; - lastSafepointPos = posAfter; - targetMethod.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false); + compilationResult.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false); } public void recordSafepoint(int pos, LIRFrameState info) { // safepoints always need debug info DebugInfo debugInfo = info.debugInfo(); - assert lastSafepointPos < pos; - lastSafepointPos = pos; - targetMethod.recordSafepoint(pos, debugInfo); + compilationResult.recordSafepoint(pos, debugInfo); } public Address recordDataReferenceInCode(Constant data, int alignment, boolean inlined) { assert data != null; int pos = asm.codeBuffer.position(); Debug.log("Data reference in code: pos = %d, data = %s", pos, data.toString()); - targetMethod.recordDataReference(pos, data, alignment, inlined); - return Address.Placeholder; - } - - public int lastSafepointPos() { - return lastSafepointPos; + compilationResult.recordDataReference(pos, data, alignment, inlined); + return asm.getPlaceholder(); } /** @@ -181,7 +163,7 @@ * including long constants that fit into the 32-bit range. */ public int asIntConst(Value value) { - assert (value.getKind().getStackKind() == Kind.Int || value.getKind() == Kind.Jsr || value.getKind() == Kind.Long) && isConstant(value); + assert (value.getKind().getStackKind() == Kind.Int || value.getKind() == Kind.Long) && isConstant(value); Constant constant = (Constant) value; assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch"; long c = constant.asLong(); @@ -251,7 +233,7 @@ public Address asAddress(Value value) { if (isStackSlot(value)) { StackSlot slot = (StackSlot) value; - return new Address(slot.getKind(), frameMap.registerConfig.getFrameRegister().asValue(), frameMap.offsetForStackSlot(slot)); + return asm.makeAddress(slot.getKind(), frameMap.registerConfig.getFrameRegister().asValue(), frameMap.offsetForStackSlot(slot)); } return (Address) value; }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Mon Mar 04 10:00:49 2013 +0100 @@ -179,7 +179,7 @@ }); } nodes.mark(earlyExit); - for (ValueProxyNode proxy : earlyExit.proxies()) { + for (ProxyNode proxy : earlyExit.proxies()) { nodes.mark(proxy); } } @@ -271,9 +271,9 @@ anchored.replaceFirstInput(earlyExit, merge); } - for (final ValueProxyNode vpn : earlyExit.proxies().snapshot()) { + for (final ProxyNode vpn : earlyExit.proxies().snapshot()) { final ValueNode replaceWith; - ValueProxyNode newVpn = getDuplicatedNode(vpn); + ProxyNode newVpn = getDuplicatedNode(vpn); if (newVpn != null) { PhiNode phi = graph.add(vpn.type() == PhiType.Value ? vpn.stamp() == StampFactory.virtual() ? new PhiNode(vpn.stamp(), merge) : new PhiNode(vpn.kind(), merge) : new PhiNode( vpn.type(), merge));
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Mon Mar 04 10:00:49 2013 +0100 @@ -60,7 +60,7 @@ while (!loopBegin.isDeleted()) { int mark = graph.getMark(); peel(loop); - new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph); + new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph); if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > GraalOptions.MaximumDesiredSize * 3) { throw new BailoutException("FullUnroll : Graph seems to grow out of proportion"); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractCallTargetNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractCallTargetNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -32,10 +32,10 @@ private final Stamp returnStamp; private final JavaType[] signature; - private final Object target; + private final InvokeTarget target; private final CallingConvention.Type callType; - public AbstractCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, CallingConvention.Type callType) { + public AbstractCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, InvokeTarget target, CallingConvention.Type callType) { super(arguments); this.returnStamp = returnStamp; this.signature = signature; @@ -52,7 +52,7 @@ return signature; } - public Object target() { + public InvokeTarget target() { return target; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -108,7 +108,7 @@ } public void removeProxies() { - for (ValueProxyNode vpn : proxies().snapshot()) { + for (ProxyNode vpn : proxies().snapshot()) { // can not use graph.replaceFloating because vpn.value may be null during killCFG vpn.replaceAtUsages(vpn.value()); vpn.safeDelete(); @@ -131,11 +131,11 @@ } public NodeIterable<Node> anchored() { - return usages().filter(isNotA(ValueProxyNode.class)); + return usages().filter(isNotA(ProxyNode.class)); } - public NodeIterable<ValueProxyNode> proxies() { - return usages().filter(ValueProxyNode.class); + public NodeIterable<ProxyNode> proxies() { + return usages().filter(ProxyNode.class); } public NodeIterable<FixedNode> getBlockNodes() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -165,17 +165,6 @@ } /** - * Returns a node for an address (jsr/ret address) constant. - * - * @param i the address value for which to create the instruction - * @param graph - * @return a node representing the address - */ - public static ConstantNode forJsr(int i, Graph graph) { - return graph.unique(new ConstantNode(Constant.forJsr(i))); - } - - /** * Returns a node for an object constant. * * @param o the object value for which to create the instruction
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DirectCallTargetNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -30,7 +30,7 @@ public class DirectCallTargetNode extends AbstractCallTargetNode { - public DirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, CallingConvention.Type callType) { + public DirectCallTargetNode(List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, InvokeTarget target, CallingConvention.Type callType) { super(arguments, returnStamp, signature, target, callType); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Mon Mar 04 10:00:49 2013 +0100 @@ -68,6 +68,12 @@ */ public static final int AFTER_EXCEPTION_BCI = -3; + /** + * This BCI should be used for frame states that cannot be the target of a deoptimization, like + * snippet frame states. + */ + public static final int INVALID_FRAMESTATE_BCI = -5; + @Input private FrameState outerFrameState; @Input private final NodeInputList<ValueNode> values;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IndirectCallTargetNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -32,7 +32,7 @@ @Input protected ValueNode computedAddress; - public IndirectCallTargetNode(ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, Object target, CallingConvention.Type callType) { + public IndirectCallTargetNode(ValueNode computedAddress, List<ValueNode> arguments, Stamp returnStamp, JavaType[] signature, InvokeTarget target, CallingConvention.Type callType) { super(arguments, returnStamp, signature, target, callType); this.computedAddress = computedAddress; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -109,6 +109,11 @@ } @Override + public Object getLocationIdentity() { + return LocationNode.ANY_LOCATION; + } + + @Override public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -161,6 +161,11 @@ return true; } + @Override + public Object getLocationIdentity() { + return LocationNode.ANY_LOCATION; + } + public FrameState stateDuring() { FrameState tempStateAfter = stateAfter(); FrameState stateDuring = tempStateAfter.duplicateModified(bci(), tempStateAfter.rethrowException(), kind());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -37,7 +37,8 @@ public static enum PhiType { Value(null), // normal value phis - Guard(StampFactory.dependency()), Memory(StampFactory.dependency()); + Guard(StampFactory.dependency()), + Memory(StampFactory.dependency()); public final Stamp stamp;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes; + +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.ValueNumberable; +import com.oracle.graal.nodes.PhiNode.PhiType; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * A value proxy that is inserted in the frame state of a loop exit for any value that is created + * inside the loop (i.e. was not live on entry to the loop) and is (potentially) used after the + * loop. + */ +@NodeInfo(nameTemplate = "{p#type/s}Proxy") +public class ProxyNode extends FloatingNode implements Node.IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, LIRLowerable { + + @Input(notDataflow = true) private BeginNode proxyPoint; + @Input private ValueNode value; + private final PhiType type; + + public ProxyNode(ValueNode value, BeginNode exit, PhiType type) { + super(type == PhiType.Value ? value.stamp() : type.stamp); + this.type = type; + assert exit != null; + this.proxyPoint = exit; + this.value = value; + } + + public ValueNode value() { + return value; + } + + @Override + public boolean inferStamp() { + return updateStamp(value.stamp()); + } + + @Override + public Stamp stamp() { + return value().stamp(); + } + + public BeginNode proxyPoint() { + return proxyPoint; + } + + public PhiType type() { + return type; + } + + @Override + public boolean verify() { + assert value != null; + assert proxyPoint != null; + return super.verify(); + } + + @Override + public void generate(LIRGeneratorTool generator) { + assert type == PhiType.Memory; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (type == PhiType.Value && value.isConstant()) { + return value; + } + return this; + } + + @Override + public void virtualize(VirtualizerTool tool) { + if (type == PhiType.Value) { + State state = tool.getObjectState(value); + if (state != null && state.getState() == EscapeState.Virtual) { + tool.replaceWithVirtual(state.getVirtualObject()); + } + } + } +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -29,4 +29,8 @@ */ public class StartNode extends BeginStateSplitNode implements MemoryCheckpoint { + @Override + public Object getLocationIdentity() { + return LocationNode.ANY_LOCATION; + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java Mon Mar 04 10:00:49 2013 +0100 @@ -31,7 +31,7 @@ public class ValueNodeUtil { public static ValueNode assertKind(Kind kind, ValueNode x) { - assert x != null && ((x.kind() == kind) || (x.kind() == Kind.Jsr && kind == Kind.Object)) : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.kind()); + assert x != null && x.kind() == kind : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.kind()); return x; } @@ -48,11 +48,6 @@ return x; } - public static ValueNode assertJsr(ValueNode x) { - assert x != null && (x.kind() == Kind.Jsr); - return x; - } - public static ValueNode assertInt(ValueNode x) { assert x != null && (x.kind() == Kind.Int); return x;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java Mon Mar 04 09:48:14 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +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.nodes; - -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.ValueNumberable; -import com.oracle.graal.nodes.PhiNode.PhiType; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * A value proxy that is inserted in the frame state of a loop exit for any value that is created - * inside the loop (i.e. was not live on entry to the loop) and is (potentially) used after the - * loop. - */ -public class ValueProxyNode extends FloatingNode implements Node.IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable { - - @Input(notDataflow = true) private BeginNode proxyPoint; - @Input private ValueNode value; - private final PhiType type; - - public ValueProxyNode(ValueNode value, BeginNode exit, PhiType type) { - super(value.stamp()); - this.type = type; - assert exit != null; - this.proxyPoint = exit; - this.value = value; - } - - public ValueNode value() { - return value; - } - - @Override - public boolean inferStamp() { - return updateStamp(value.stamp()); - } - - @Override - public Stamp stamp() { - return value().stamp(); - } - - public BeginNode proxyPoint() { - return proxyPoint; - } - - public PhiType type() { - return type; - } - - @Override - public boolean verify() { - assert value != null; - assert proxyPoint != null; - return super.verify(); - } - - @Override - public ValueNode canonical(CanonicalizerTool tool) { - if (value.isConstant()) { - return value; - } - return this; - } - - @Override - public void virtualize(VirtualizerTool tool) { - State state = tool.getObjectState(value); - if (state != null && state.getState() == EscapeState.Virtual) { - tool.replaceWithVirtual(state.getVirtualObject()); - } - } -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/Condition.java Mon Mar 04 10:00:49 2013 +0100 @@ -342,7 +342,6 @@ case Byte: case Char: case Short: - case Jsr: case Int: { int x = lt.asInt(); int y = rt.asInt();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -35,9 +35,26 @@ public final class ConvertNode extends FloatingNode implements Canonicalizable, LIRLowerable { public enum Op { - I2L(Int, Long), L2I(Long, Int), I2B(Int, Byte), I2C(Int, Char), I2S(Int, Short), F2D(Float, Double), D2F(Double, Float), I2F(Int, Float), I2D(Int, Double), F2I(Float, Int), D2I(Double, Int), L2F( - Long, Float), L2D(Long, Double), F2L(Float, Long), D2L(Double, Long), UNSIGNED_I2L(Int, Long), MOV_I2F(Int, Float), MOV_L2D(Long, Double), MOV_F2I(Float, Int), MOV_D2L(Double, - Long); + I2L(Int, Long), + L2I(Long, Int), + I2B(Int, Byte), + I2C(Int, Char), + I2S(Int, Short), + F2D(Float, Double), + D2F(Double, Float), + I2F(Int, Float), + I2D(Int, Double), + F2I(Float, Int), + D2I(Double, Int), + L2F(Long, Float), + L2D(Long, Double), + F2L(Float, Long), + D2L(Double, Long), + UNSIGNED_I2L(Int, Long), + MOV_I2F(Int, Float), + MOV_L2D(Long, Double), + MOV_F2I(Float, Int), + MOV_D2L(Double, Long); public final Kind from; public final Kind to;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Mon Mar 04 10:00:49 2013 +0100 @@ -108,9 +108,38 @@ return loops; } + public void clearNodeToBlock() { + nodeToBlock.clear(); + for (Block block : reversePostOrder) { + identifyBlock(block, block.beginNode); + } + } + protected static final int BLOCK_ID_INITIAL = -1; protected static final int BLOCK_ID_VISITED = -2; + private void identifyBlock(Block block, BeginNode begin) { + block.beginNode = begin; + Node cur = begin; + Node last; + do { + assert !cur.isDeleted(); + + assert nodeToBlock.get(cur) == null; + nodeToBlock.set(cur, block); + if (cur instanceof MergeNode) { + for (PhiNode phi : ((MergeNode) cur).phis()) { + nodeToBlock.set(phi, block); + } + } + + last = cur; + cur = cur.successors().first(); + } while (cur != null && !(cur instanceof BeginNode)); + + block.endNode = (FixedNode) last; + } + private void identifyBlocks() { // Find all block headers int numBlocks = 0; @@ -118,26 +147,7 @@ if (node instanceof BeginNode) { Block block = new Block(); numBlocks++; - - block.beginNode = (BeginNode) node; - Node cur = node; - Node last; - do { - assert !cur.isDeleted(); - - assert nodeToBlock.get(cur) == null; - nodeToBlock.set(cur, block); - if (cur instanceof MergeNode) { - for (PhiNode phi : ((MergeNode) cur).phis()) { - nodeToBlock.set(phi, block); - } - } - - last = cur; - cur = cur.successors().first(); - } while (cur != null && !(cur instanceof BeginNode)); - - block.endNode = (FixedNode) last; + identifyBlock(block, (BeginNode) node); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -53,7 +53,7 @@ @Override public void generate(LIRGeneratorTool gen) { - gen.setResult(this, gen.emitLoad(gen.makeAddress(location(), object()), getNullCheck())); + gen.setResult(this, location().generateLoad(gen, object(), getNullCheck())); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -28,17 +28,14 @@ import com.oracle.graal.nodes.spi.*; /** - * Extension of a {@linkplain LocationNode location} to include a scaled index or an additional - * offset. + * Extension of a {@linkplain LocationNode location} to include a scaled index. Can represent + * locations in the form of [base + index * scale + disp] where base and index are nodes and scale + * and disp are integer constants. */ public final class IndexedLocationNode extends LocationNode implements Canonicalizable { - /** - * An offset or index depending on whether {@link #indexScalingEnabled} is true or false - * respectively. - */ @Input private ValueNode index; - private final boolean indexScalingEnabled; + private final int indexScaling; /** * Gets the index or offset of this location. @@ -52,21 +49,20 @@ } /** - * @return whether scaling of the index by the value kind's size is enabled (the default) or - * disabled. + * @return Constant that is used to scale the index. */ - public boolean indexScalingEnabled() { - return indexScalingEnabled; + public int indexScaling() { + return indexScaling; } - public static IndexedLocationNode create(Object identity, Kind kind, int displacement, ValueNode index, Graph graph, boolean indexScalingEnabled) { - return graph.unique(new IndexedLocationNode(identity, kind, index, displacement, indexScalingEnabled)); + public static IndexedLocationNode create(Object identity, Kind kind, int displacement, ValueNode index, Graph graph, int indexScaling) { + return graph.unique(new IndexedLocationNode(identity, kind, index, displacement, indexScaling)); } - private IndexedLocationNode(Object identity, Kind kind, ValueNode index, int displacement, boolean indexScalingEnabled) { + private IndexedLocationNode(Object identity, Kind kind, ValueNode index, int displacement, int indexScaling) { super(identity, kind, displacement); this.index = index; - this.indexScalingEnabled = indexScalingEnabled; + this.indexScaling = indexScaling; } @Override @@ -74,12 +70,7 @@ Constant constantIndex = index.asConstant(); if (constantIndex != null) { long constantIndexLong = constantIndex.asLong(); - if (indexScalingEnabled) { - if (tool.target() == null) { - return this; - } - constantIndexLong *= tool.target().sizeInBytes(getValueKind()); - } + constantIndexLong *= indexScaling; constantIndexLong += displacement(); int constantIndexInt = (int) constantIndexLong; if (constantIndexLong == constantIndexInt) { @@ -88,4 +79,19 @@ } return this; } + + @Override + public Value generateLea(LIRGeneratorTool gen, ValueNode base) { + return gen.emitLea(gen.operand(base), displacement(), gen.operand(index()), indexScaling()); + } + + @Override + public Value generateLoad(LIRGeneratorTool gen, ValueNode base, boolean canTrap) { + return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), canTrap); + } + + @Override + public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, boolean canTrap) { + gen.emitStore(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), gen.operand(value), canTrap); + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -25,13 +25,15 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ValueNumberable; +import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; /** - * A location for a memory access in terms of the kind of value accessed and the displacement (in - * bytes) from a base object or address. + * A location for a memory access in terms of the kind of value accessed and how to access it. The + * base version can represent addresses of the form [base + disp] where base is a node and disp is a + * constant. */ @NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}") public class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable { @@ -41,27 +43,37 @@ private Object locationIdentity; /** + * Creates a new unique location identity for read and write operations. + * + * @param name the name of the new location identity, for debugging purposes + * @return the new location identity + */ + public static Object createLocation(final String name) { + return new Object() { + + @Override + public String toString() { + return name; + } + }; + } + + /** * Denotes any location. A write to such a location kills all values in a memory map during an * analysis of memory accesses in a graph. */ - public static final Object ANY_LOCATION = new Object() { + public static final Object ANY_LOCATION = createLocation("ANY_LOCATION"); - @Override - public String toString() { - return "ANY_LOCATION"; - } - }; + /** + * Denotes an unknown location. A read from this location cannot be moved or coalesced with + * other reads because its interaction with other reads is not known. + */ + public static final Object UNKNOWN_LOCATION = createLocation("UNKNOWN_LOCATION"); /** * Denotes the location of a value that is guaranteed to be final. */ - public static final Object FINAL_LOCATION = new Object() { - - @Override - public String toString() { - return "FINAL_LOCATION"; - } - }; + public static final Object FINAL_LOCATION = createLocation("FINAL_LOCATION"); public static Object getArrayLocation(Kind elementKind) { return elementKind; @@ -95,4 +107,16 @@ public void generate(LIRGeneratorTool generator) { // nothing to do... } + + public Value generateLea(LIRGeneratorTool gen, ValueNode base) { + return gen.emitLea(gen.operand(base), displacement(), Value.ILLEGAL, 0); + } + + public Value generateLoad(LIRGeneratorTool gen, ValueNode base, boolean canTrap) { + return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, canTrap); + } + + public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, boolean canTrap) { + gen.emitStore(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, gen.operand(value), canTrap); + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -43,6 +43,11 @@ } @Override + public Object getLocationIdentity() { + return LocationNode.ANY_LOCATION; + } + + @Override public void generate(LIRGeneratorTool generator) { generator.emitMembar(barriers); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java Mon Mar 04 10:00:49 2013 +0100 @@ -22,6 +22,21 @@ */ package com.oracle.graal.nodes.extended; +import com.oracle.graal.nodes.*; + +/** + * This interface marks is used for subclasses of {@link FixedNode} that kill a set of memory + * locations represented by a location identity (i.e. change a value at one or more locations that + * belong to this location identity). + */ public interface MemoryCheckpoint { + /** + * This method is used to determine which set of memory locations is killed by this node. + * Returning the special value {@link LocationNode#ANY_LOCATION} will kill all memory locations. + * + * @return the identity of the location killed by this node. + */ + Object getLocationIdentity(); + }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -51,7 +51,7 @@ @Override public void generate(LIRGeneratorTool gen) { - gen.setResult(this, gen.emitLoad(gen.makeAddress(location(), object()), getNullCheck())); + gen.setResult(this, location().generateLoad(gen, object(), getNullCheck())); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -49,6 +49,11 @@ } @Override + public Object getLocationIdentity() { + return LocationNode.ANY_LOCATION; + } + + @Override public void generate(LIRGeneratorTool gen) { gen.visitRuntimeCall(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -93,7 +93,7 @@ if (kind() != object.kind()) { assert generator.target().sizeInBytes(kind()) == generator.target().sizeInBytes(object.kind()) : "unsafe cast cannot be used to change the size of a value"; Value result = generator.newVariable(kind()); - generator.emitMove(generator.operand(object), result); + generator.emitMove(result, generator.operand(object)); generator.setResult(this, result); } else { // The LIR only cares about the kind of an operand, not the actual type of an object. So
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -33,7 +33,7 @@ * Store of a value at a location specified as an offset relative to an object. No null check is * performed before the store. */ -public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, Canonicalizable { +public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, Canonicalizable, MemoryCheckpoint { @Input private ValueNode value; @Input(notDataflow = true) private FrameState stateAfter; @@ -72,6 +72,11 @@ } @Override + public Object getLocationIdentity() { + return LocationNode.ANY_LOCATION; + } + + @Override public void virtualize(VirtualizerTool tool) { State state = tool.getObjectState(object()); if (state != null && state.getState() == EscapeState.Virtual) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -37,6 +37,11 @@ } @Override + public Object getLocationIdentity() { + return LocationNode.ANY_LOCATION; + } + + @Override public void generate(LIRGeneratorTool generator) { // nothing to do... }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -29,7 +29,7 @@ /** * Writes a given {@linkplain #value() value} a {@linkplain AccessNode memory location}. */ -public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable { +public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint { @Input private ValueNode value; @Input(notDataflow = true) private FrameState stateAfter; @@ -59,9 +59,14 @@ @Override public void generate(LIRGeneratorTool gen) { - gen.emitStore(gen.makeAddress(location(), object()), gen.operand(value()), getNullCheck()); + location().generateStore(gen, object(), value(), getNullCheck()); } @NodeIntrinsic public static native void writeMemory(Object object, Object value, Object location); + + @Override + public Object getLocationIdentity() { + return location().locationIdentity(); + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -71,6 +71,11 @@ } @Override + public Object getLocationIdentity() { + return LocationNode.ANY_LOCATION; + } + + @Override public void generate(LIRGeneratorTool gen) { gen.visitCompareAndSwap(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -42,6 +42,11 @@ } @Override + public Object getLocationIdentity() { + return LocationNode.ANY_LOCATION; + } + + @Override public void generate(LIRGeneratorTool gen) { gen.visitExceptionObject(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -40,6 +40,11 @@ super(object); } + @Override + public Object getLocationIdentity() { + return LocationNode.ANY_LOCATION; + } + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -41,6 +41,11 @@ super(object); } + @Override + public Object getLocationIdentity() { + return LocationNode.ANY_LOCATION; + } + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java Mon Mar 04 10:00:49 2013 +0100 @@ -28,8 +28,6 @@ public interface CanonicalizerTool { - TargetDescription target(); - Assumptions assumptions(); MetaAccessProvider runtime();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Mon Mar 04 10:00:49 2013 +0100 @@ -45,16 +45,6 @@ */ public abstract boolean canInlineConstant(Constant c); - /** - * Checks whether the supplied constant can be used without loading it into a register for store - * operations, i.e., on the right hand side of a memory access. - * - * @param c The constant to check. - * @return True if the constant can be used directly, false if the constant needs to be in a - * register. - */ - public abstract boolean canStoreConstant(Constant c); - public abstract RegisterAttributes attributes(Register register); public abstract Value operand(ValueNode object); @@ -63,17 +53,17 @@ public abstract Value setResult(ValueNode x, Value operand); - public abstract Address makeAddress(LocationNode location, ValueNode object); - public abstract Value emitMove(Value input); - public abstract void emitMove(Value src, Value dst); + public abstract void emitMove(Value dst, Value src); - public abstract Value emitLoad(Value loadAddress, boolean canTrap); + public abstract Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap); - public abstract void emitStore(Value storeAddress, Value input, boolean canTrap); + public abstract void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, boolean canTrap); - public abstract Value emitLea(Value address); + public abstract Value emitLea(Value base, int displacement, Value index, int scale); + + public abstract Value emitLea(StackSlot slot); public abstract Value emitNegate(Value input);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Mon Mar 04 10:00:49 2013 +0100 @@ -199,7 +199,6 @@ return 0xffffL; case Short: return 0xffffL; - case Jsr: case Int: return 0xffffffffL; case Long:
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Mon Mar 04 10:00:49 2013 +0100 @@ -57,8 +57,6 @@ setCache(Kind.Float, new FloatStamp(Kind.Float)); setCache(Kind.Double, new FloatStamp(Kind.Double)); - setCache(Kind.Jsr, new IntegerStamp(Kind.Jsr)); - setCache(Kind.Object, objectStamp); setCache(Kind.Void, voidStamp); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Mon Mar 04 10:00:49 2013 +0100 @@ -140,18 +140,18 @@ ValueNode singleValue = phiNode.singleValue(); if (singleValue != null) { Collection<PhiNode> phiUsages = phiNode.usages().filter(PhiNode.class).snapshot(); - Collection<ValueProxyNode> proxyUsages = phiNode.usages().filter(ValueProxyNode.class).snapshot(); + Collection<ProxyNode> proxyUsages = phiNode.usages().filter(ProxyNode.class).snapshot(); ((StructuredGraph) phiNode.graph()).replaceFloating(phiNode, singleValue); for (PhiNode phi : phiUsages) { checkRedundantPhi(phi); } - for (ValueProxyNode proxy : proxyUsages) { + for (ProxyNode proxy : proxyUsages) { checkRedundantProxy(proxy); } } } - public static void checkRedundantProxy(ValueProxyNode vpn) { + public static void checkRedundantProxy(ProxyNode vpn) { BeginNode proxyPoint = vpn.proxyPoint(); if (proxyPoint instanceof LoopExitNode) { LoopExitNode exit = (LoopExitNode) proxyPoint; @@ -164,12 +164,12 @@ } if (vpnValue == v2) { Collection<PhiNode> phiUsages = vpn.usages().filter(PhiNode.class).snapshot(); - Collection<ValueProxyNode> proxyUsages = vpn.usages().filter(ValueProxyNode.class).snapshot(); + Collection<ProxyNode> proxyUsages = vpn.usages().filter(ProxyNode.class).snapshot(); ((StructuredGraph) vpn.graph()).replaceFloating(vpn, vpnValue); for (PhiNode phi : phiUsages) { checkRedundantPhi(phi); } - for (ValueProxyNode proxy : proxyUsages) { + for (ProxyNode proxy : proxyUsages) { checkRedundantProxy(proxy); } return; @@ -185,7 +185,7 @@ GraphUtil.checkRedundantPhi(phi); } for (LoopExitNode exit : begin.loopExits()) { - for (ValueProxyNode vpn : exit.proxies().snapshot()) { + for (ProxyNode vpn : exit.proxies().snapshot()) { GraphUtil.checkRedundantProxy(vpn); } } @@ -259,8 +259,8 @@ public static ValueNode unProxify(ValueNode proxy) { ValueNode v = proxy; - while (v instanceof ValueProxyNode) { - v = ((ValueProxyNode) v).value(); + while (v instanceof ProxyNode) { + v = ((ProxyNode) v).value(); } return v; } @@ -293,8 +293,8 @@ public static ValueNode originalValue(ValueNode proxy) { ValueNode v = proxy; do { - if (v instanceof ValueProxyNode) { - v = ((ValueProxyNode) v).value(); + if (v instanceof ProxyNode) { + v = ((ProxyNode) v).value(); } else if (v instanceof PhiNode) { v = ((PhiNode) v).singleValue(); } else { @@ -308,8 +308,8 @@ NodeWorkList worklist = proxy.graph().createNodeWorkList(); worklist.add(proxy); for (Node node : worklist) { - if (node instanceof ValueProxyNode) { - worklist.add(((ValueProxyNode) node).value()); + if (node instanceof ProxyNode) { + worklist.add(((ProxyNode) node).value()); } else if (node instanceof PhiNode) { worklist.addAll(((PhiNode) node).values()); } else {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -48,7 +48,6 @@ public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits"); private final int newNodesMark; - private final TargetDescription target; private final Assumptions assumptions; private final MetaAccessProvider runtime; private final CustomCanonicalizer customCanonicalizer; @@ -63,33 +62,31 @@ ValueNode canonicalize(Node node); } - public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) { - this(target, runtime, assumptions, null, 0, null); + public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions) { + this(runtime, assumptions, null, 0, null); } /** - * @param target * @param runtime * @param assumptions * @param workingSet the initial working set of nodes on which the canonicalizer works, should * be an auto-grow node bitmap * @param customCanonicalizer */ - public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) { - this(target, runtime, assumptions, workingSet, 0, customCanonicalizer); + public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) { + this(runtime, assumptions, workingSet, 0, customCanonicalizer); } /** * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by this * mark are processed otherwise all nodes in the graph are processed */ - public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) { - this(target, runtime, assumptions, null, newNodesMark, customCanonicalizer); + public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) { + this(runtime, assumptions, null, newNodesMark, customCanonicalizer); } - public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) { + public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) { this.newNodesMark = newNodesMark; - this.target = target; this.assumptions = assumptions; this.runtime = runtime; this.customCanonicalizer = customCanonicalizer; @@ -108,7 +105,7 @@ if (newNodesMark > 0) { workList.addAll(graph.getNewNodes(newNodesMark)); } - tool = new Tool(workList, runtime, target, assumptions); + tool = new Tool(workList, runtime, assumptions); processWorkSet(graph); } @@ -309,13 +306,11 @@ private final NodeWorkList nodeWorkSet; private final MetaAccessProvider runtime; - private final TargetDescription target; private final Assumptions assumptions; - public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, TargetDescription target, Assumptions assumptions) { + public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions) { this.nodeWorkSet = nodeWorkSet; this.runtime = runtime; - this.target = target; this.assumptions = assumptions; } @@ -326,15 +321,6 @@ } /** - * @return the current target or {@code null} if no target is available in the current - * context. - */ - @Override - public TargetDescription target() { - return target; - } - - /** * @return an object that can be used for recording assumptions or {@code null} if * assumptions are not allowed in the current context. */
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -37,11 +37,14 @@ public class CullFrameStatesPhase extends Phase { private static final DebugMetric metricFrameStatesCulled = Debug.metric("FrameStatesCulled"); + private static final DebugMetric metricNodesRemoved = Debug.metric("NodesRemoved"); private static final DebugMetric metricMergesTraversed = Debug.metric("MergesTraversed"); @Override protected void run(StructuredGraph graph) { + int initialNodes = graph.getNodeCount(); new CullFrameStates(graph.start(), new State(null)).apply(); + metricNodesRemoved.add(initialNodes - graph.getNodeCount()); } public static class State implements MergeableState<State> {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -29,271 +29,218 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.graph.*; +import com.oracle.graal.phases.graph.ReentrantNodeIterator.LoopInfo; +import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; public class FloatingReadPhase extends Phase { - private IdentityHashMap<LoopBeginNode, List<MemoryMap>> loopEndStatesMap; - - private static class LoopState { - - public LoopBeginNode loopBegin; - public MemoryMap state; - public IdentityHashMap<PhiNode, Object> loopPhiLocations = new IdentityHashMap<>(); - public ValueNode loopEntryAnyLocation; - - public LoopState(LoopBeginNode loopBegin, MemoryMap state, ValueNode loopEntryAnyLocation) { - this.loopBegin = loopBegin; - this.state = state; - this.loopEntryAnyLocation = loopEntryAnyLocation; - } - - @Override - public String toString() { - return "State@" + loopBegin; - } - } - - private class MemoryMap implements MergeableState<MemoryMap> { + private static class MemoryMap { private IdentityHashMap<Object, ValueNode> lastMemorySnapshot; - private LinkedList<LoopState> loops; public MemoryMap(MemoryMap memoryMap) { lastMemorySnapshot = new IdentityHashMap<>(memoryMap.lastMemorySnapshot); - loops = new LinkedList<>(memoryMap.loops); + } + + public MemoryMap(StartNode start) { + this(); + lastMemorySnapshot.put(LocationNode.ANY_LOCATION, start); } public MemoryMap() { lastMemorySnapshot = new IdentityHashMap<>(); - loops = new LinkedList<>(); + } + + private ValueNode getLastLocationAccess(Object locationIdentity) { + ValueNode lastLocationAccess; + if (locationIdentity == LocationNode.FINAL_LOCATION) { + return null; + } else { + lastLocationAccess = lastMemorySnapshot.get(locationIdentity); + if (lastLocationAccess == null) { + lastLocationAccess = lastMemorySnapshot.get(LocationNode.ANY_LOCATION); + assert lastLocationAccess != null; + } + return lastLocationAccess; + } } @Override public String toString() { - return "Map=" + lastMemorySnapshot.toString() + " Loops=" + loops.toString(); - } - - @SuppressWarnings("unchecked") - @Override - public boolean merge(MergeNode merge, List<MemoryMap> withStates) { - if (withStates.size() == 0) { - return true; - } - - int minLoops = loops.size(); - for (MemoryMap other : withStates) { - int otherLoops = other.loops.size(); - if (otherLoops < minLoops) { - minLoops = otherLoops; - } - } - while (loops.size() > minLoops) { - loops.pop(); - } - for (MemoryMap other : withStates) { - while (other.loops.size() > minLoops) { - other.loops.pop(); - } - } - - Set<Object> keys = new HashSet<>(); - for (Object key : lastMemorySnapshot.keySet()) { - keys.add(key); - } - for (MemoryMap other : withStates) { - assert other.loops.size() == loops.size(); - assert other.loops.size() < 1 || other.loops.peek().loopBegin == loops.peek().loopBegin; - for (Object key : other.lastMemorySnapshot.keySet()) { - keys.add(key); - } - } - IdentityHashMap<Object, ValueNode> newMemorySnapshot = (IdentityHashMap<Object, ValueNode>) lastMemorySnapshot.clone(); - - for (Object key : keys) { - ValueNode merged = lastMemorySnapshot.get(key); - if (merged == null) { - merged = lastMemorySnapshot.get(LocationNode.ANY_LOCATION); - } - int mergedStatesCount = 1; - boolean isPhi = false; - for (MemoryMap other : withStates) { - ValueNode otherValue = other.lastMemorySnapshot.get(key); - if (otherValue == null) { - otherValue = other.lastMemorySnapshot.get(LocationNode.ANY_LOCATION); - } - if (isPhi) { - ((PhiNode) merged).addInput(otherValue); - } else if (merged != otherValue) { - PhiNode phi = merge.graph().add(new PhiNode(PhiType.Memory, merge)); - for (int j = 0; j < mergedStatesCount; j++) { - phi.addInput(merged); - } - phi.addInput(otherValue); - merged = phi; - isPhi = true; - newMemorySnapshot.put(key, phi); - } - mergedStatesCount++; - } - } - - lastMemorySnapshot = newMemorySnapshot; - return true; - } - - @Override - public void loopBegin(LoopBeginNode loopBegin) { - LoopState loopState = new LoopState(loopBegin, this, lastMemorySnapshot.get(LocationNode.ANY_LOCATION)); - for (Map.Entry<Object, ValueNode> entry : lastMemorySnapshot.entrySet()) { - PhiNode phi = loopBegin.graph().add(new PhiNode(PhiType.Memory, loopBegin)); - phi.addInput(entry.getValue()); - entry.setValue(phi); - loopState.loopPhiLocations.put(phi, entry.getKey()); - } - loops.push(loopState); - } - - @Override - public void loopEnds(LoopBeginNode loopBegin, List<MemoryMap> loopEndStates) { - loopEndStatesMap.put(loopBegin, loopEndStates); - tryFinishLoopPhis(this, loopBegin); - } - - @Override - public void afterSplit(BeginNode node) { - // nothing - } - - @Override - public MemoryMap clone() { - return new MemoryMap(this); + return "Map=" + lastMemorySnapshot.toString(); } } + private final Map<LoopBeginNode, Set<Object>> modifiedInLoops = new IdentityHashMap<>(); + @Override protected void run(StructuredGraph graph) { - loopEndStatesMap = new IdentityHashMap<>(); - new PostOrderNodeIterator<MemoryMap>(graph.start(), new MemoryMap()) { - - @Override - protected void node(FixedNode node) { - processNode(node, state); - } - }.apply(); - } - - private void processNode(FixedNode node, MemoryMap state) { - if (node instanceof ReadNode) { - processRead((ReadNode) node, state); - } else if (node instanceof WriteNode) { - processWrite((WriteNode) node, state); - } else if (node instanceof MemoryCheckpoint) { - processCheckpoint((MemoryCheckpoint) node, state); - } else if (node instanceof LoopExitNode) { - processLoopExit((LoopExitNode) node, state); - } - } - - private static void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) { - processAnyLocationWrite((ValueNode) checkpoint, state); + ReentrantNodeIterator.apply(new CollectMemoryCheckpointsClosure(), graph.start(), new HashSet<>(), null); + ReentrantNodeIterator.apply(new FloatingReadClosure(), graph.start(), new MemoryMap(graph.start()), null); } - private static void processWrite(WriteNode writeNode, MemoryMap state) { - if (writeNode.location().locationIdentity() == LocationNode.ANY_LOCATION) { - processAnyLocationWrite(writeNode, state); + private class CollectMemoryCheckpointsClosure extends NodeIteratorClosure<Set<Object>> { + + @Override + protected void processNode(FixedNode node, Set<Object> currentState) { + if (node instanceof MemoryCheckpoint) { + currentState.add(((MemoryCheckpoint) node).getLocationIdentity()); + } } - state.lastMemorySnapshot.put(writeNode.location().locationIdentity(), writeNode); - } - private static void processAnyLocationWrite(ValueNode modifiying, MemoryMap state) { - for (Map.Entry<Object, ValueNode> entry : state.lastMemorySnapshot.entrySet()) { - entry.setValue(modifiying); + @Override + protected Set<Object> merge(MergeNode merge, List<Set<Object>> states) { + Set<Object> result = new HashSet<>(); + for (Set<Object> other : states) { + result.addAll(other); + } + return result; } - state.lastMemorySnapshot.put(LocationNode.ANY_LOCATION, modifiying); - state.loops.clear(); - } - private void processRead(ReadNode readNode, MemoryMap state) { - StructuredGraph graph = (StructuredGraph) readNode.graph(); - assert readNode.getNullCheck() == false; - Object locationIdentity = readNode.location().locationIdentity(); - ValueNode lastLocationAccess = getLastLocationAccessForRead(state, locationIdentity); - FloatingReadNode floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), lastLocationAccess, readNode.stamp(), readNode.dependencies())); - floatingRead.setNullCheck(readNode.getNullCheck()); - ValueAnchorNode anchor = null; - for (GuardNode guard : readNode.dependencies().filter(GuardNode.class)) { - if (anchor == null) { - anchor = graph.add(new ValueAnchorNode()); + @Override + protected Set<Object> afterSplit(BeginNode node, Set<Object> oldState) { + return new HashSet<>(oldState); + } + + @Override + protected Map<LoopExitNode, Set<Object>> processLoop(LoopBeginNode loop, Set<Object> initialState) { + LoopInfo<Set<Object>> loopInfo = ReentrantNodeIterator.processLoop(this, loop, new HashSet<>()); + Set<Object> modifiedLocations = new HashSet<>(); + for (Set<Object> end : loopInfo.endStates.values()) { + modifiedLocations.addAll(end); } - anchor.addAnchoredNode(guard); + for (Set<Object> exit : loopInfo.exitStates.values()) { + exit.addAll(modifiedLocations); + exit.addAll(initialState); + } + assert !modifiedLocations.contains(LocationNode.FINAL_LOCATION); + modifiedInLoops.put(loop, modifiedLocations); + return loopInfo.exitStates; } - if (anchor != null) { - graph.addAfterFixed(readNode, anchor); - } - graph.replaceFixedWithFloating(readNode, floatingRead); + } - private ValueNode getLastLocationAccessForRead(MemoryMap state, Object locationIdentity) { - ValueNode lastLocationAccess; - if (locationIdentity == LocationNode.FINAL_LOCATION) { - lastLocationAccess = null; - } else { - lastLocationAccess = state.lastMemorySnapshot.get(locationIdentity); - if (lastLocationAccess == null) { - LoopState lastLoop = state.loops.peek(); - if (lastLoop == null) { - lastLocationAccess = state.lastMemorySnapshot.get(LocationNode.ANY_LOCATION); - } else { - ValueNode phiInit; - if (state.loops.size() > 1) { - phiInit = getLastLocationAccessForRead(state.loops.get(1).state, locationIdentity); - } else { - phiInit = lastLoop.loopEntryAnyLocation; + private class FloatingReadClosure extends NodeIteratorClosure<MemoryMap> { + + @Override + protected void processNode(FixedNode node, MemoryMap state) { + if (node instanceof ReadNode) { + processRead((ReadNode) node, state); + } else if (node instanceof MemoryCheckpoint) { + processCheckpoint((MemoryCheckpoint) node, state); + } + } + + private void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) { + if (checkpoint.getLocationIdentity() == LocationNode.ANY_LOCATION) { + state.lastMemorySnapshot.clear(); + } + state.lastMemorySnapshot.put(checkpoint.getLocationIdentity(), (ValueNode) checkpoint); + } + + private void processRead(ReadNode readNode, MemoryMap state) { + StructuredGraph graph = (StructuredGraph) readNode.graph(); + assert readNode.getNullCheck() == false; + Object locationIdentity = readNode.location().locationIdentity(); + if (locationIdentity != LocationNode.UNKNOWN_LOCATION) { + ValueNode lastLocationAccess = state.getLastLocationAccess(locationIdentity); + FloatingReadNode floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), lastLocationAccess, readNode.stamp(), readNode.dependencies())); + floatingRead.setNullCheck(readNode.getNullCheck()); + ValueAnchorNode anchor = null; + for (GuardNode guard : readNode.dependencies().filter(GuardNode.class)) { + if (anchor == null) { + anchor = graph.add(new ValueAnchorNode()); + graph.addAfterFixed(readNode, anchor); } - PhiNode phi = lastLoop.loopBegin.graph().add(new PhiNode(PhiType.Memory, lastLoop.loopBegin)); - phi.addInput(phiInit); - lastLoop.state.lastMemorySnapshot.put(locationIdentity, phi); - lastLoop.loopPhiLocations.put(phi, locationIdentity); - tryFinishLoopPhis(lastLoop.state, lastLoop.loopBegin); - lastLocationAccess = phi; + anchor.addAnchoredNode(guard); } - state.lastMemorySnapshot.put(locationIdentity, lastLocationAccess); + graph.replaceFixedWithFloating(readNode, floatingRead); } } - return lastLocationAccess; - } + + @Override + protected MemoryMap merge(MergeNode merge, List<MemoryMap> states) { + MemoryMap newState = new MemoryMap(); - private static void processLoopExit(LoopExitNode exit, MemoryMap state) { - for (Map.Entry<Object, ValueNode> entry : state.lastMemorySnapshot.entrySet()) { - entry.setValue(exit.graph().unique(new ValueProxyNode(entry.getValue(), exit, PhiType.Memory))); - } - if (!state.loops.isEmpty()) { - state.loops.pop(); - } - } + Set<Object> keys = new HashSet<>(); + for (MemoryMap other : states) { + keys.addAll(other.lastMemorySnapshot.keySet()); + } + assert !keys.contains(LocationNode.FINAL_LOCATION); - private void tryFinishLoopPhis(MemoryMap loopMemory, LoopBeginNode loopBegin) { - List<MemoryMap> loopEndStates = loopEndStatesMap.get(loopBegin); - if (loopEndStates == null) { - return; - } - LoopState loopState = loopMemory.loops.get(0); - int i = 0; - while (loopState.loopBegin != loopBegin) { - loopState = loopMemory.loops.get(++i); + for (Object key : keys) { + int mergedStatesCount = 0; + boolean isPhi = false; + ValueNode merged = null; + for (MemoryMap state : states) { + ValueNode last = state.getLastLocationAccess(key); + if (isPhi) { + ((PhiNode) merged).addInput(last); + } else { + if (merged == last) { + // nothing to do + } else if (merged == null) { + merged = last; + } else { + PhiNode phi = merge.graph().add(new PhiNode(PhiType.Memory, merge)); + for (int j = 0; j < mergedStatesCount; j++) { + phi.addInput(merged); + } + phi.addInput(last); + merged = phi; + isPhi = true; + } + } + mergedStatesCount++; + } + newState.lastMemorySnapshot.put(key, merged); + } + return newState; } - for (PhiNode phi : loopBegin.phis()) { - if (phi.type() == PhiType.Memory && phi.valueCount() == 1) { - Object location = loopState.loopPhiLocations.get(phi); - assert location != null : "unknown location for " + phi; - for (MemoryMap endState : loopEndStates) { - ValueNode otherNode = endState.lastMemorySnapshot.get(location); - if (otherNode == null) { - otherNode = endState.lastMemorySnapshot.get(LocationNode.ANY_LOCATION); - } - phi.addInput(otherNode); + + @Override + protected MemoryMap afterSplit(BeginNode node, MemoryMap oldState) { + return new MemoryMap(oldState); + } + + @Override + protected Map<LoopExitNode, MemoryMap> processLoop(LoopBeginNode loop, MemoryMap initialState) { + Set<Object> modifiedLocations = modifiedInLoops.get(loop); + if (modifiedLocations.contains(LocationNode.ANY_LOCATION)) { + // create phis for all locations if ANY is modified in the loop + modifiedLocations = new HashSet<>(modifiedLocations); + modifiedLocations.addAll(initialState.lastMemorySnapshot.keySet()); + } + + Map<Object, PhiNode> phis = new HashMap<>(); + for (Object location : modifiedLocations) { + PhiNode phi = loop.graph().add(new PhiNode(PhiType.Memory, loop)); + phi.addInput(initialState.getLastLocationAccess(location)); + phis.put(location, phi); + initialState.lastMemorySnapshot.put(location, phi); + } + + LoopInfo<MemoryMap> loopInfo = ReentrantNodeIterator.processLoop(this, loop, initialState); + + for (Map.Entry<LoopEndNode, MemoryMap> entry : loopInfo.endStates.entrySet()) { + int endIndex = loop.phiPredecessorIndex(entry.getKey()); + for (Map.Entry<Object, PhiNode> phiEntry : phis.entrySet()) { + Object key = phiEntry.getKey(); + PhiNode phi = phiEntry.getValue(); + phi.initializeValueAt(endIndex, entry.getValue().getLastLocationAccess(key)); } } + for (Map.Entry<LoopExitNode, MemoryMap> entry : loopInfo.exitStates.entrySet()) { + LoopExitNode exit = entry.getKey(); + MemoryMap state = entry.getValue(); + for (Object location : modifiedLocations) { + ValueNode lastAccessAtExit = state.lastMemorySnapshot.get(location); + if (lastAccessAtExit != null) { + state.lastMemorySnapshot.put(location, loop.graph().add(new ProxyNode(lastAccessAtExit, exit, PhiType.Memory))); + } + } + } + return loopInfo.exitStates; } } }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -24,6 +24,7 @@ import java.lang.reflect.*; import java.util.*; +import java.util.concurrent.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -47,7 +48,6 @@ * invoke.bci, method, true); */ - private final TargetDescription target; private final PhasePlan plan; private final GraalCodeCacheProvider runtime; @@ -63,18 +63,15 @@ private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize"); private static final DebugMetric metricInliningRuns = Debug.metric("Runs"); - public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Collection<Invoke> hints, Assumptions assumptions, GraphCache cache, PhasePlan plan, - OptimisticOptimizations optimisticOpts) { - this(target, runtime, assumptions, cache, plan, createInliningPolicy(runtime, assumptions, optimisticOpts, hints), optimisticOpts); + public InliningPhase(GraalCodeCacheProvider runtime, Collection<Invoke> hints, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) { + this(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, - OptimisticOptimizations optimisticOpts) { - this.target = target; + public InliningPhase(GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy, OptimisticOptimizations optimisticOpts) { this.runtime = runtime; this.assumptions = assumptions; this.cache = cache; @@ -103,7 +100,7 @@ Iterable<Node> newNodes = graph.getNewNodes(mark); inliningPolicy.scanInvokes(newNodes); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph); + new CanonicalizerPhase(runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph); } metricInliningPerformed.increment(); } catch (BailoutException bailout) { @@ -131,26 +128,32 @@ return cachedGraph; } } - StructuredGraph newGraph = new StructuredGraph(method); - if (plan != null) { - plan.runPhases(PhasePosition.AFTER_PARSING, newGraph); - } - assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING"; + final StructuredGraph newGraph = new StructuredGraph(method); + return Debug.scope("InlineGraph", newGraph, new Callable<StructuredGraph>() { + + @Override + public StructuredGraph call() throws Exception { + if (plan != null) { + plan.runPhases(PhasePosition.AFTER_PARSING, newGraph); + } + assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING"; - if (GraalOptions.ProbabilityAnalysis) { - new DeadCodeEliminationPhase().apply(newGraph); - new ComputeProbabilityPhase().apply(newGraph); - } - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(newGraph); - } - if (GraalOptions.CullFrameStates) { - new CullFrameStatesPhase().apply(newGraph); - } - if (GraalOptions.CacheGraphs && cache != null) { - cache.put(newGraph); - } - return newGraph; + if (GraalOptions.ProbabilityAnalysis) { + new DeadCodeEliminationPhase().apply(newGraph); + new ComputeProbabilityPhase().apply(newGraph); + } + if (GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(runtime, assumptions).apply(newGraph); + } + if (GraalOptions.CullFrameStates) { + new CullFrameStatesPhase().apply(newGraph); + } + if (GraalOptions.CacheGraphs && cache != null) { + cache.put(newGraph); + } + return newGraph; + } + }); } private interface InliningDecision {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Mon Mar 04 10:00:49 2013 +0100 @@ -696,7 +696,8 @@ 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 + // 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) { @@ -966,8 +967,6 @@ return logNotInlinedMethodAndReturnFalse(invoke, method, "the method's class is not initialized"); } else if (!method.canBeInlined()) { return logNotInlinedMethodAndReturnFalse(invoke, method, "it is marked non-inlinable"); - } else if (computeInliningLevel(invoke) > GraalOptions.MaximumInlineLevel) { - return logNotInlinedMethodAndReturnFalse(invoke, method, "it exceeds the maximum inlining depth"); } else if (computeRecursiveInliningLevel(invoke.stateAfter(), method) > GraalOptions.MaximumRecursiveInlining) { return logNotInlinedMethodAndReturnFalse(invoke, method, "it exceeds the maximum recursive inlining depth"); } else if (new OptimisticOptimizations(method).lessOptimisticThan(optimisticOpts)) { @@ -1123,7 +1122,7 @@ } else { // only handle the outermost frame states if (frameState.outerFrameState() == null) { - assert frameState.method() == inlineGraph.method(); + assert frameState.bci == FrameState.INVALID_FRAMESTATE_BCI || frameState.method() == inlineGraph.method(); if (outerFrameState == null) { outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.node().kind()); outerFrameState.setDuringCall(true);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -33,12 +33,10 @@ public class IterativeConditionalEliminationPhase extends Phase { - private final TargetDescription target; private final MetaAccessProvider runtime; private final Assumptions assumptions; - public IterativeConditionalEliminationPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) { - this.target = target; + public IterativeConditionalEliminationPhase(MetaAccessProvider runtime, Assumptions assumptions) { this.runtime = runtime; this.assumptions = assumptions; } @@ -55,7 +53,7 @@ if (canonicalizationRoots.isEmpty()) { break; } - new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots, null).apply(graph); + new CanonicalizerPhase(runtime, assumptions, canonicalizationRoots, null).apply(graph); canonicalizationRoots.clear(); } }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -139,7 +139,7 @@ deferred = false; processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null, schedule, processed); Debug.dump(graph, "Lowering iteration %d", i++); - new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph); + new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph); if (!deferred && !containsLowerable(graph.getNewNodes(mark))) { // No new lowerable nodes - done!
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -59,8 +59,8 @@ if (visited.isMarked(lastLocationAccess)) { return true; // dataflow loops must come from Phis assume them ok until proven wrong } - if (lastLocationAccess instanceof ValueProxyNode) { - return isWrites(n, ((ValueProxyNode) lastLocationAccess).value(), visited); + if (lastLocationAccess instanceof ProxyNode) { + return isWrites(n, ((ProxyNode) lastLocationAccess).value(), visited); } if (lastLocationAccess instanceof WriteNode) { WriteNode other = (WriteNode) lastLocationAccess; @@ -83,10 +83,10 @@ if (exisiting != null) { return exisiting; } - if (lastLocationAccess instanceof ValueProxyNode) { - ValueProxyNode proxy = (ValueProxyNode) lastLocationAccess; + if (lastLocationAccess instanceof ProxyNode) { + ProxyNode proxy = (ProxyNode) lastLocationAccess; ValueNode value = getValue(n, proxy.value(), nodeMap); - return lastLocationAccess.graph().add(new ValueProxyNode(value, proxy.proxyPoint(), PhiType.Value)); + return lastLocationAccess.graph().add(new ProxyNode(value, proxy.proxyPoint(), PhiType.Value)); } if (lastLocationAccess instanceof WriteNode) { return ((WriteNode) lastLocationAccess).value();
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -23,14 +23,17 @@ package com.oracle.graal.phases.common; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.PhiNode.*; import com.oracle.graal.phases.*; public class RemoveValueProxyPhase extends Phase { @Override protected void run(StructuredGraph graph) { - for (ValueProxyNode vpn : graph.getNodes(ValueProxyNode.class)) { - graph.replaceFloating(vpn, vpn.value()); + for (ProxyNode vpn : graph.getNodes(ProxyNode.class)) { + if (vpn.type() == PhiType.Value) { + graph.replaceFloating(vpn, vpn.value()); + } } for (LoopExitNode exit : graph.getNodes(LoopExitNode.class)) { FrameState stateAfter = exit.stateAfter();
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Mon Mar 04 10:00:49 2013 +0100 @@ -43,7 +43,6 @@ static boolean InlineMonomorphicCalls = true; static boolean InlinePolymorphicCalls = true; static boolean InlineMegamorphicCalls = ____; - public static int MaximumInlineLevel = 30; public static int MaximumDesiredSize = 5000; public static int MaximumRecursiveInlining = 1; public static boolean LimitInlinedProbability = ____; @@ -151,7 +150,7 @@ public static boolean ExitVMOnException = true; // Code generator settings - public static boolean CheckCastElimination = true; + public static boolean ConditionalElimination = true; public static boolean CullFrameStates = ____; public static boolean UseProfilingInformation = true; static boolean RemoveNeverExecutedCode = true; @@ -169,6 +168,8 @@ public static boolean CanOmitFrame = true; public static int SafepointPollOffset = 256; + public static boolean MemoryAwareScheduling = true; + // Translating tableswitch instructions public static int MinimumJumpTableSize = 5; public static int RangeTestsSwitchDensity = 5;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java Mon Mar 04 10:00:49 2013 +0100 @@ -56,7 +56,6 @@ * 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(); } }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Mon Mar 04 10:00:49 2013 +0100 @@ -29,54 +29,49 @@ public final class ReentrantBlockIterator { - public abstract static class MergeableBlockState<T> { + public static class LoopInfo<StateT> { - public abstract T cloneState(); + public final List<StateT> endStates = new ArrayList<>(); + public final List<StateT> exitStates = new ArrayList<>(); } - public static class LoopInfo<T extends MergeableBlockState<T>> { + public abstract static class BlockIteratorClosure<StateT> { - public final List<T> endStates = new ArrayList<>(); - public final List<T> exitStates = new ArrayList<>(); - } - - public abstract static class BlockIteratorClosure<T extends MergeableBlockState<T>> { + protected abstract void processBlock(Block block, StateT currentState); - protected abstract void processBlock(Block block, T currentState); - - protected abstract T merge(MergeNode merge, List<T> states); + protected abstract StateT merge(MergeNode merge, List<StateT> states); - protected abstract T afterSplit(FixedNode node, T oldState); + protected abstract StateT afterSplit(FixedNode node, StateT oldState); - protected abstract List<T> processLoop(Loop loop, T initialState); + protected abstract List<StateT> processLoop(Loop loop, StateT initialState); } private ReentrantBlockIterator() { // no instances allowed } - public static <T extends MergeableBlockState<T>> LoopInfo<T> processLoop(BlockIteratorClosure<T> closure, Loop loop, T initialState) { - IdentityHashMap<FixedNode, T> blockEndStates = apply(closure, loop.header, initialState, new HashSet<>(loop.blocks)); + public static <StateT> LoopInfo<StateT> processLoop(BlockIteratorClosure<StateT> closure, Loop loop, StateT initialState) { + IdentityHashMap<FixedNode, StateT> blockEndStates = apply(closure, loop.header, initialState, new HashSet<>(loop.blocks)); - LoopInfo<T> info = new LoopInfo<>(); + LoopInfo<StateT> info = new LoopInfo<>(); List<Block> predecessors = loop.header.getPredecessors(); for (int i = 1; i < predecessors.size(); i++) { info.endStates.add(blockEndStates.get(predecessors.get(i).getEndNode())); } for (Block loopExit : loop.exits) { assert loopExit.getPredecessorCount() == 1; - T exitState = blockEndStates.get(loopExit.getFirstPredecessor().getEndNode()); + StateT exitState = blockEndStates.get(loopExit.getFirstPredecessor().getEndNode()); assert exitState != null; info.exitStates.add(exitState); } return info; } - public static <T extends MergeableBlockState<T>> IdentityHashMap<FixedNode, T> apply(BlockIteratorClosure<T> closure, Block start, T initialState, Set<Block> boundary) { + public static <StateT> IdentityHashMap<FixedNode, StateT> apply(BlockIteratorClosure<StateT> closure, Block start, StateT initialState, Set<Block> boundary) { Deque<Block> blockQueue = new ArrayDeque<>(); - IdentityHashMap<FixedNode, T> blockEndStates = new IdentityHashMap<>(); + IdentityHashMap<FixedNode, StateT> blockEndStates = new IdentityHashMap<>(); - T state = initialState; + StateT state = initialState; Block current = start; do { @@ -98,7 +93,7 @@ LoopBeginNode loopBegin = loop.loopBegin(); assert successor.getBeginNode() == loopBegin; - List<T> exitStates = closure.processLoop(loop, state); + List<StateT> exitStates = closure.processLoop(loop, state); int i = 0; assert loop.exits.size() == exitStates.size(); @@ -123,8 +118,8 @@ blockEndStates.put(end, state); MergeNode merge = end.merge(); boolean endsVisited = true; - for (int i = 0; i < merge.forwardEndCount(); i++) { - if (!blockEndStates.containsKey(merge.forwardEndAt(i))) { + for (EndNode forwardEnd : merge.forwardEnds()) { + if (!blockEndStates.containsKey(forwardEnd)) { endsVisited = false; break; } @@ -157,9 +152,9 @@ current = blockQueue.removeFirst(); if (current.getPredecessors().size() > 1) { MergeNode merge = (MergeNode) current.getBeginNode(); - ArrayList<T> states = new ArrayList<>(merge.forwardEndCount()); + ArrayList<StateT> states = new ArrayList<>(merge.forwardEndCount()); for (int i = 0; i < merge.forwardEndCount(); i++) { - T other = blockEndStates.get(merge.forwardEndAt(i)); + StateT other = blockEndStates.get(merge.forwardEndAt(i)); assert other != null; states.add(other); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,158 @@ +/* + * 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.phases.graph; + +import java.util.*; + +import com.oracle.graal.graph.NodeClass.NodeClassIterator; +import com.oracle.graal.nodes.*; + +public final class ReentrantNodeIterator { + + public static class LoopInfo<StateT> { + + public final Map<LoopEndNode, StateT> endStates = new IdentityHashMap<>(4); + public final Map<LoopExitNode, StateT> exitStates = new IdentityHashMap<>(2); + } + + public abstract static class NodeIteratorClosure<StateT> { + + protected abstract void processNode(FixedNode node, StateT currentState); + + protected abstract StateT merge(MergeNode merge, List<StateT> states); + + protected abstract StateT afterSplit(BeginNode node, StateT oldState); + + protected abstract Map<LoopExitNode, StateT> processLoop(LoopBeginNode loop, StateT initialState); + } + + private ReentrantNodeIterator() { + // no instances allowed + } + + public static <StateT> LoopInfo<StateT> processLoop(NodeIteratorClosure<StateT> closure, LoopBeginNode loop, StateT initialState) { + HashSet<FixedNode> boundary = new HashSet<>(); + for (LoopExitNode exit : loop.loopExits()) { + boundary.add(exit); + } + Map<FixedNode, StateT> blockEndStates = apply(closure, loop, initialState, boundary); + + LoopInfo<StateT> info = new LoopInfo<>(); + for (LoopEndNode end : loop.loopEnds()) { + assert blockEndStates.containsKey(end) : "no end state for " + end; + info.endStates.put(end, blockEndStates.get(end)); + } + for (LoopExitNode exit : loop.loopExits()) { + assert blockEndStates.containsKey(exit) : "no exit state for " + exit; + info.exitStates.put(exit, blockEndStates.get(exit)); + } + return info; + } + + public static <StateT> Map<FixedNode, StateT> apply(NodeIteratorClosure<StateT> closure, FixedNode start, StateT initialState, Set<FixedNode> boundary) { + Deque<BeginNode> nodeQueue = new ArrayDeque<>(); + IdentityHashMap<FixedNode, StateT> blockEndStates = new IdentityHashMap<>(); + + StateT state = initialState; + FixedNode current = start; + do { + while (current instanceof FixedWithNextNode) { + if (boundary != null && boundary.contains(current)) { + blockEndStates.put(current, state); + current = null; + } else { + FixedNode next = ((FixedWithNextNode) current).next(); + closure.processNode(current, state); + current = next; + } + } + + if (current != null) { + closure.processNode(current, state); + + NodeClassIterator successors = current.successors().iterator(); + if (!successors.hasNext()) { + if (current instanceof LoopEndNode) { + blockEndStates.put(current, state); + } else if (current instanceof EndNode) { + // add the end node and see if the merge is ready for processing + MergeNode merge = ((EndNode) current).merge(); + if (merge instanceof LoopBeginNode) { + Map<LoopExitNode, StateT> loopExitState = closure.processLoop((LoopBeginNode) merge, state); + for (Map.Entry<LoopExitNode, StateT> entry : loopExitState.entrySet()) { + blockEndStates.put(entry.getKey(), entry.getValue()); + nodeQueue.add(entry.getKey()); + } + } else { + assert !blockEndStates.containsKey(current); + blockEndStates.put(current, state); + boolean endsVisited = true; + for (EndNode forwardEnd : merge.forwardEnds()) { + if (!blockEndStates.containsKey(forwardEnd)) { + endsVisited = false; + break; + } + } + if (endsVisited) { + ArrayList<StateT> states = new ArrayList<>(merge.forwardEndCount()); + for (int i = 0; i < merge.forwardEndCount(); i++) { + EndNode forwardEnd = merge.forwardEndAt(i); + assert blockEndStates.containsKey(forwardEnd); + StateT other = blockEndStates.get(forwardEnd); + states.add(other); + } + state = closure.merge(merge, states); + current = merge; + continue; + } + } + } + } else { + FixedNode firstSuccessor = (FixedNode) successors.next(); + if (!successors.hasNext()) { + current = firstSuccessor; + continue; + } else { + while (successors.hasNext()) { + BeginNode successor = (BeginNode) successors.next(); + blockEndStates.put(successor, closure.afterSplit(successor, state)); + nodeQueue.add(successor); + } + state = closure.afterSplit((BeginNode) firstSuccessor, state); + current = firstSuccessor; + continue; + } + } + } + + // get next queued block + if (nodeQueue.isEmpty()) { + return blockEndStates; + } else { + current = nodeQueue.removeFirst(); + state = blockEndStates.get(current); + assert !(current instanceof MergeNode) && current instanceof BeginNode; + } + } while (true); + } +}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -28,12 +28,102 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.graph.*; +import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; +import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo; -public class SchedulePhase extends Phase { +public final class SchedulePhase extends Phase { + + public static enum SchedulingStrategy { + EARLIEST, LATEST, LATEST_OUT_OF_LOOPS + } + + /** + * This closure iterates over all nodes of a scheduled graph (it expects a + * {@link SchedulingStrategy#EARLIEST} schedule) and keeps a list of "actuve" reads. Whenever it + * encounters a read, it adds it to the active reads. Whenever it encounters a memory + * checkpoint, it adds all reads that need to be committed before this checkpoint to the + * "phantom" usages and inputs, so that the read is scheduled before the checkpoint afterwards. + * + * At merges, the intersection of all sets of active reads is calculated. A read that was + * committed within one predecessor branch cannot be scheduled after the merge anyway. + * + * Similarly for loops, all reads that are killed somewhere within the loop are removed from the + * exits' active reads, since they cannot be scheduled after the exit anyway. + */ + private class MemoryScheduleClosure extends BlockIteratorClosure<HashSet<FloatingReadNode>> { + + @Override + protected void processBlock(Block block, HashSet<FloatingReadNode> currentState) { + for (Node node : getBlockToNodesMap().get(block)) { + if (node instanceof FloatingReadNode) { + currentState.add((FloatingReadNode) node); + } else if (node instanceof MemoryCheckpoint) { + Object identity = ((MemoryCheckpoint) node).getLocationIdentity(); + for (Iterator<FloatingReadNode> iter = currentState.iterator(); iter.hasNext();) { + FloatingReadNode read = iter.next(); + FixedNode fixed = (FixedNode) node; + if (identity == LocationNode.ANY_LOCATION || read.location().locationIdentity() == identity) { + addPhantomReference(read, fixed); + } + } + } + } + } + + public void addPhantomReference(FloatingReadNode read, FixedNode fixed) { + List<FixedNode> usageList = phantomUsages.get(read); + if (usageList == null) { + phantomUsages.put(read, usageList = new ArrayList<>()); + } + usageList.add(fixed); + List<FloatingNode> inputList = phantomInputs.get(fixed); + if (inputList == null) { + phantomInputs.put(fixed, inputList = new ArrayList<>()); + } + inputList.add(read); + } + + @Override + protected HashSet<FloatingReadNode> merge(MergeNode merge, List<HashSet<FloatingReadNode>> states) { + HashSet<FloatingReadNode> state = new HashSet<>(states.get(0)); + for (int i = 1; i < states.size(); i++) { + state.retainAll(states.get(i)); + } + return state; + } + + @Override + protected HashSet<FloatingReadNode> afterSplit(FixedNode node, HashSet<FloatingReadNode> oldState) { + return new HashSet<>(oldState); + } + + @Override + protected List<HashSet<FloatingReadNode>> processLoop(Loop loop, HashSet<FloatingReadNode> state) { + LoopInfo<HashSet<FloatingReadNode>> info = ReentrantBlockIterator.processLoop(this, loop, new HashSet<>(state)); + + List<HashSet<FloatingReadNode>> loopEndStates = info.endStates; + + // collect all reads that were killed in some branch within the loop + Set<FloatingReadNode> killedReads = new HashSet<>(state); + Set<FloatingReadNode> survivingReads = new HashSet<>(loopEndStates.get(0)); + for (int i = 1; i < loopEndStates.size(); i++) { + survivingReads.retainAll(loopEndStates.get(i)); + } + killedReads.removeAll(survivingReads); + + // reads that were killed within the loop cannot be scheduled after the loop anyway + for (HashSet<FloatingReadNode> exitState : info.exitStates) { + exitState.removeAll(killedReads); + } + return info.exitStates; + } + } private ControlFlowGraph cfg; private NodeMap<Block> earliestCache; @@ -42,6 +132,8 @@ * Map from blocks to the nodes in each block. */ private BlockMap<List<ScheduledNode>> blockToNodesMap; + private final Map<FloatingNode, List<FixedNode>> phantomUsages = new IdentityHashMap<>(); + private final Map<FixedNode, List<FloatingNode>> phantomInputs = new IdentityHashMap<>(); public SchedulePhase() { super("Schedule"); @@ -49,12 +141,26 @@ @Override protected void run(StructuredGraph graph) { + SchedulingStrategy strategy = GraalOptions.OptScheduleOutOfLoops ? SchedulingStrategy.LATEST_OUT_OF_LOOPS : SchedulingStrategy.LATEST; + cfg = ControlFlowGraph.compute(graph, true, true, true, false); earliestCache = graph.createNodeMap(); blockToNodesMap = new BlockMap<>(cfg); - assignBlockToNodes(graph); - sortNodesWithinBlocks(graph); + if (GraalOptions.MemoryAwareScheduling && graph.getNodes(FloatingReadNode.class).isNotEmpty()) { + + assignBlockToNodes(graph, SchedulingStrategy.EARLIEST); + sortNodesWithinBlocks(graph, SchedulingStrategy.EARLIEST); + + MemoryScheduleClosure closure = new MemoryScheduleClosure(); + ReentrantBlockIterator.apply(closure, getCFG().getStartBlock(), new HashSet<FloatingReadNode>(), null); + + cfg.clearNodeToBlock(); + blockToNodesMap = new BlockMap<>(cfg); + } + + assignBlockToNodes(graph, strategy); + sortNodesWithinBlocks(graph, strategy); } /** @@ -94,7 +200,7 @@ return blockToNodesMap.get(block); } - private void assignBlockToNodes(StructuredGraph graph) { + private void assignBlockToNodes(StructuredGraph graph, SchedulingStrategy strategy) { for (Block block : cfg.getBlocks()) { List<ScheduledNode> nodes = new ArrayList<>(); assert blockToNodesMap.get(block) == null; @@ -106,7 +212,7 @@ for (Node n : graph.getNodes()) { if (n instanceof ScheduledNode) { - assignBlockToNode((ScheduledNode) n); + assignBlockToNode((ScheduledNode) n, strategy); } } } @@ -115,7 +221,7 @@ * Assigns a block to the given node. This method expects that PhiNodes and FixedNodes are * already assigned to a block. */ - private void assignBlockToNode(ScheduledNode node) { + private void assignBlockToNode(ScheduledNode node, SchedulingStrategy strategy) { assert !node.isDeleted(); Block prevBlock = cfg.getNodeToBlock().get(node); @@ -126,17 +232,26 @@ // ControlFlowGraph.identifyBlocks assert !(node instanceof PhiNode) : node; assert !(node instanceof FixedNode) : node; - // if in CFG, schedule at the latest position possible in the outermost loop possible - Block latestBlock = latestBlock(node); + Block block; - if (latestBlock == null) { - block = earliestBlock(node); - } else if (GraalOptions.OptScheduleOutOfLoops && !(node instanceof VirtualObjectNode)) { - Block earliestBlock = earliestBlock(node); - block = scheduleOutOfLoops(node, latestBlock, earliestBlock); - assert earliestBlock.dominates(block) : "Graph can not be scheduled : inconsistent for " + node + " (" + earliestBlock + " needs to dominate " + block + ")"; - } else { - block = latestBlock; + switch (strategy) { + case EARLIEST: + block = earliestBlock(node); + break; + case LATEST: + case LATEST_OUT_OF_LOOPS: + block = latestBlock(node, strategy); + if (block == null) { + block = earliestBlock(node); + } else if (strategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS && !(node instanceof VirtualObjectNode)) { + // schedule at the latest position possible in the outermost loop possible + Block earliestBlock = earliestBlock(node); + block = scheduleOutOfLoops(node, block, earliestBlock); + assert earliestBlock.dominates(block) : "Graph can not be scheduled : inconsistent for " + node + " (" + earliestBlock + " needs to dominate " + block + ")"; + } + break; + default: + throw new GraalInternalError("unknown scheduling strategy"); } cfg.getNodeToBlock().set(node, block); blockToNodesMap.get(block).add(node); @@ -145,17 +260,27 @@ /** * Calculates the last block that the given node could be scheduled in, i.e., the common * dominator of all usages. To do so all usages are also assigned to blocks. + * + * @param strategy */ - private Block latestBlock(ScheduledNode node) { + private Block latestBlock(ScheduledNode node, SchedulingStrategy strategy) { CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(null); for (Node succ : node.successors().nonNull()) { assert cfg.getNodeToBlock().get(succ) != null; cdbc.apply(cfg.getNodeToBlock().get(succ)); } - ensureScheduledUsages(node); + ensureScheduledUsages(node, strategy); for (Node usage : node.usages()) { - blocksForUsage(node, usage, cdbc); + blocksForUsage(node, usage, cdbc, strategy); } + List<FixedNode> usages = phantomUsages.get(node); + if (usages != null) { + for (FixedNode usage : usages) { + assert cfg.getNodeToBlock().get(usage) != null; + cdbc.apply(cfg.getNodeToBlock().get(usage)); + } + } + return cdbc.block; } @@ -204,7 +329,12 @@ assert node.predecessor() == null; for (Node input : node.inputs().nonNull()) { assert input instanceof ValueNode; - Block inputEarliest = earliestBlock(input); + Block inputEarliest; + if (input instanceof InvokeWithExceptionNode) { + inputEarliest = cfg.getNodeToBlock().get(((InvokeWithExceptionNode) input).next()); + } else { + inputEarliest = earliestBlock(input); + } if (!dominators.get(inputEarliest.getId())) { earliest = inputEarliest; do { @@ -242,7 +372,7 @@ * @param usage the usage whose blocks need to be considered * @param closure the closure that will be called for each block */ - private void blocksForUsage(ScheduledNode node, Node usage, BlockClosure closure) { + private void blocksForUsage(ScheduledNode node, Node usage, BlockClosure closure, SchedulingStrategy strategy) { assert !(node instanceof PhiNode); if (usage instanceof PhiNode) { @@ -274,7 +404,7 @@ if (unscheduledUsage instanceof VirtualState) { // If a FrameState is an outer FrameState this method behaves as if the inner // FrameState was the actual usage, by recursing. - blocksForUsage(node, unscheduledUsage, closure); + blocksForUsage(node, unscheduledUsage, closure, strategy); } else if (unscheduledUsage instanceof MergeNode) { // Only FrameStates can be connected to MergeNodes. assert usage instanceof FrameState; @@ -288,20 +418,20 @@ assert usage instanceof FrameState; assert unscheduledUsage instanceof StateSplit; // Otherwise: Put the input into the same block as the usage. - assignBlockToNode((ScheduledNode) unscheduledUsage); + assignBlockToNode((ScheduledNode) unscheduledUsage, strategy); closure.apply(cfg.getNodeToBlock().get(unscheduledUsage)); } } } else { // All other types of usages: Put the input into the same block as the usage. - assignBlockToNode((ScheduledNode) usage); + assignBlockToNode((ScheduledNode) usage, strategy); closure.apply(cfg.getNodeToBlock().get(usage)); } } - private void ensureScheduledUsages(Node node) { + private void ensureScheduledUsages(Node node, SchedulingStrategy strategy) { for (Node usage : node.usages().filter(ScheduledNode.class)) { - assignBlockToNode((ScheduledNode) usage); + assignBlockToNode((ScheduledNode) usage, strategy); } // now true usages are ready } @@ -316,27 +446,43 @@ return ControlFlowGraph.commonDominator(a, b); } - private void sortNodesWithinBlocks(StructuredGraph graph) { + private void sortNodesWithinBlocks(StructuredGraph graph, SchedulingStrategy strategy) { NodeBitMap visited = graph.createNodeBitMap(); for (Block b : cfg.getBlocks()) { - sortNodesWithinBlock(b, visited); + sortNodesWithinBlock(b, visited, strategy); } } + private void sortNodesWithinBlock(Block b, NodeBitMap visited, SchedulingStrategy strategy) { + assert !visited.isMarked(b.getBeginNode()) && cfg.blockFor(b.getBeginNode()) == b; + assert !visited.isMarked(b.getEndNode()) && cfg.blockFor(b.getEndNode()) == b; + + List<ScheduledNode> sortedInstructions; + switch (strategy) { + case EARLIEST: + sortedInstructions = sortNodesWithinBlockEarliest(b, visited); + break; + case LATEST: + case LATEST_OUT_OF_LOOPS: + sortedInstructions = sortNodesWithinBlockLatest(b, visited); + break; + default: + throw new GraalInternalError("unknown scheduling strategy"); + } + blockToNodesMap.put(b, sortedInstructions); + } + /** * Sorts the nodes within a block by adding the nodes to a list in a post-order iteration over * all inputs. This means that a node is added to the list after all its inputs have been * processed. */ - private void sortNodesWithinBlock(Block b, NodeBitMap visited) { + private List<ScheduledNode> sortNodesWithinBlockLatest(Block b, NodeBitMap visited) { List<ScheduledNode> instructions = blockToNodesMap.get(b); - List<ScheduledNode> sortedInstructions = new ArrayList<>(instructions.size() + 2); - - assert !visited.isMarked(b.getBeginNode()) && cfg.blockFor(b.getBeginNode()) == b; - assert !visited.isMarked(b.getEndNode()) && cfg.blockFor(b.getEndNode()) == b; + List<ScheduledNode> sortedInstructions = new ArrayList<>(blockToNodesMap.get(b).size() + 2); for (ScheduledNode i : instructions) { - addToSorting(b, i, sortedInstructions, visited); + addToLatestSorting(b, i, sortedInstructions, visited); } // Make sure that last node gets really last (i.e. when a frame state successor hangs off @@ -363,25 +509,25 @@ sortedInstructions.add(b.getEndNode()); } } - blockToNodesMap.put(b, sortedInstructions); + return sortedInstructions; } - private void addUnscheduledToSorting(Block b, VirtualState state, List<ScheduledNode> sortedInstructions, NodeBitMap visited) { + private void addUnscheduledToLatestSorting(Block b, VirtualState state, List<ScheduledNode> sortedInstructions, NodeBitMap visited) { if (state != null) { // UnscheduledNodes should never be marked as visited. assert !visited.isMarked(state); for (Node input : state.inputs()) { if (input instanceof VirtualState) { - addUnscheduledToSorting(b, (VirtualState) input, sortedInstructions, visited); + addUnscheduledToLatestSorting(b, (VirtualState) input, sortedInstructions, visited); } else { - addToSorting(b, (ScheduledNode) input, sortedInstructions, visited); + addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited); } } } } - private void addToSorting(Block b, ScheduledNode i, List<ScheduledNode> sortedInstructions, NodeBitMap visited) { + private void addToLatestSorting(Block b, ScheduledNode i, List<ScheduledNode> sortedInstructions, NodeBitMap visited) { if (i == null || visited.isMarked(i) || cfg.getNodeToBlock().get(i) != b || i instanceof PhiNode || i instanceof LocalNode) { return; } @@ -396,17 +542,74 @@ assert state == null; state = (FrameState) input; } else { - addToSorting(b, (ScheduledNode) input, sortedInstructions, visited); + addToLatestSorting(b, (ScheduledNode) input, sortedInstructions, visited); + } + } + List<FloatingNode> inputs = phantomInputs.get(i); + if (inputs != null) { + for (FloatingNode input : inputs) { + addToLatestSorting(b, input, sortedInstructions, visited); } } - addToSorting(b, (ScheduledNode) i.predecessor(), sortedInstructions, visited); + addToLatestSorting(b, (ScheduledNode) i.predecessor(), sortedInstructions, visited); visited.mark(i); - addUnscheduledToSorting(b, state, sortedInstructions, visited); + addUnscheduledToLatestSorting(b, state, sortedInstructions, visited); assert write == null || !visited.isMarked(write); - addToSorting(b, write, sortedInstructions, visited); + addToLatestSorting(b, write, sortedInstructions, visited); // Now predecessors and inputs are scheduled => we can add this node. sortedInstructions.add(i); } + + /** + * Sorts the nodes within a block by adding the nodes to a list in a post-order iteration over + * all usages. The resulting list is reversed to create an earliest-possible scheduling of + * nodes. + */ + private List<ScheduledNode> sortNodesWithinBlockEarliest(Block b, NodeBitMap visited) { + List<ScheduledNode> sortedInstructions = new ArrayList<>(blockToNodesMap.get(b).size() + 2); + addToEarliestSorting(b, b.getEndNode(), sortedInstructions, visited); + Collections.reverse(sortedInstructions); + return sortedInstructions; + } + + private void addToEarliestSorting(Block b, ScheduledNode i, List<ScheduledNode> sortedInstructions, NodeBitMap visited) { + if (i == null || visited.isMarked(i) || cfg.getNodeToBlock().get(i) != b || i instanceof PhiNode || i instanceof LocalNode) { + return; + } + + visited.mark(i); + for (Node usage : i.usages()) { + if (usage instanceof VirtualState) { + // only fixed nodes can have VirtualState -> no need to schedule them + } else { + if (i instanceof LoopExitNode && usage instanceof ProxyNode) { + // value proxies should be scheduled before the loopexit, not after + } else { + addToEarliestSorting(b, (ScheduledNode) usage, sortedInstructions, visited); + } + } + } + + if (i instanceof BeginNode) { + ArrayList<ProxyNode> proxies = (i instanceof LoopExitNode) ? new ArrayList<ProxyNode>() : null; + for (ScheduledNode inBlock : blockToNodesMap.get(b)) { + if (!visited.isMarked(inBlock)) { + if (inBlock instanceof ProxyNode) { + proxies.add((ProxyNode) inBlock); + } else { + addToEarliestSorting(b, inBlock, sortedInstructions, visited); + } + } + } + sortedInstructions.add(i); + if (proxies != null) { + sortedInstructions.addAll(proxies); + } + } else { + sortedInstructions.add(i); + addToEarliestSorting(b, (ScheduledNode) i.predecessor(), sortedInstructions, visited); + } + } }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Mon Mar 04 10:00:49 2013 +0100 @@ -28,7 +28,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.alloc.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.debug.*; @@ -100,10 +99,6 @@ private static final AtomicInteger uniqueId = new AtomicInteger(); public void dumpSandboxed(Object object, String message) { - GraalCompiler compiler = Debug.contextLookup(GraalCompiler.class); - if (compiler == null) { - return; - } if (cfgPrinter == null) { cfgFile = new File("compilations-" + timestamp + "_" + uniqueId.incrementAndGet() + ".cfg"); @@ -120,7 +115,7 @@ return; } - cfgPrinter.target = compiler.target; + cfgPrinter.target = Debug.contextLookup(TargetDescription.class); if (object instanceof LIR) { cfgPrinter.lir = (LIR) object; } else { @@ -131,7 +126,7 @@ cfgPrinter.cfg = cfgPrinter.lir.cfg; } - CodeCacheProvider runtime = compiler.runtime; + CodeCacheProvider runtime = Debug.contextLookup(CodeCacheProvider.class); if (object instanceof BciBlockMapping) { BciBlockMapping blockMap = (BciBlockMapping) object;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java Mon Mar 04 10:00:49 2013 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.schedule.*; /** * Observes compilation events and uses {@link IdealGraphPrinter} to generate a graph representation @@ -153,13 +154,14 @@ // Save inline context for next dump. previousInlineContext = inlineContext; + final SchedulePhase predefinedSchedule = getPredefinedSchedule(); Debug.sandbox("PrintingGraph", new Runnable() { @Override public void run() { // Finally, output the graph. try { - printer.print(graph, message, null); + printer.print(graph, message, predefinedSchedule); } catch (IOException e) { failuresCount++; printer = null; @@ -191,6 +193,16 @@ return result; } + private static SchedulePhase getPredefinedSchedule() { + SchedulePhase result = null; + for (Object o : Debug.context()) { + if (o instanceof SchedulePhase) { + result = (SchedulePhase) o; + } + } + return result; + } + private void openScope(String name, boolean showThread) { String prefix = showThread ? Thread.currentThread().getName() + ":" : ""; try {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java Mon Mar 04 10:00:49 2013 +0100 @@ -30,7 +30,6 @@ import com.oracle.graal.api.code.CompilationResult.CodeAnnotation; import com.oracle.graal.api.code.CompilationResult.CodeComment; import com.oracle.graal.api.code.CompilationResult.JumpTable; -import com.oracle.graal.api.code.CompilationResult.LookupTable; /** * A HexCodeFile is a textual format for representing a chunk of machine code along with extra @@ -122,8 +121,6 @@ public final ArrayList<JumpTable> jumpTables = new ArrayList<>(); - public final ArrayList<LookupTable> lookupTables = new ArrayList<>(); - public final String isa; public final int wordWidth; @@ -169,10 +166,6 @@ ps.printf("JumpTable %d %d %d %d %s%n", table.position, table.entrySize, table.low, table.high, SECTION_DELIM); } - for (LookupTable table : lookupTables) { - ps.printf("LookupTable %d %d %d %d %s%n", table.position, table.npairs, table.keySize, table.keySize, SECTION_DELIM); - } - for (Map.Entry<Integer, List<String>> e : comments.entrySet()) { int pos = e.getKey(); for (String comment : e.getValue()) { @@ -233,9 +226,6 @@ if (a instanceof JumpTable) { JumpTable table = (JumpTable) a; hcf.jumpTables.add(table); - } else if (a instanceof LookupTable) { - LookupTable table = (LookupTable) a; - hcf.lookupTables.add(table); } else if (a instanceof CodeComment) { CodeComment comment = (CodeComment) a; hcf.addComment(comment.position, comment.value); @@ -422,15 +412,6 @@ int low = parseInt(bodyOffset + m.start(3), m.group(3)); int high = parseInt(bodyOffset + m.start(4), m.group(4)); hcf.jumpTables.add(new JumpTable(pos, low, high, entrySize)); - } else if (header.equals("LookupTable")) { - checkHCF("LookupTable", headerOffset); - m = HexCodeFile.LOOKUP_TABLE.matcher(body); - check(m.matches(), bodyOffset, "LookupTable does not match pattern " + HexCodeFile.LOOKUP_TABLE); - int pos = parseInt(bodyOffset + m.start(1), m.group(1)); - int npairs = parseInt(bodyOffset + m.start(2), m.group(2)); - int keySize = parseInt(bodyOffset + m.start(3), m.group(3)); - int offsetSize = parseInt(bodyOffset + m.start(4), m.group(4)); - hcf.lookupTables.add(new LookupTable(pos, npairs, keySize, offsetSize)); } else { error(offset, "Unknown section header: " + header); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,119 @@ +/* + * 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.ptx; + +import static com.oracle.graal.api.code.MemoryBarriers.*; +import static com.oracle.graal.api.code.Register.RegisterFlag.*; + +import java.nio.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.Register.*; + +/** + * Represents the PTX architecture. + */ +public class PTX extends Architecture { + + // @formatter:off + + /* + * Register State Space + * + * Registers (.reg state space) are fast storage locations. The number of + * registers is limited, and will vary from platform to platform. When the + * limit is exceeded, register variables will be spilled to memory, causing + * changes in performance. For each architecture, there is a recommended + * maximum number of registers to use (see the "CUDA Programming Guide" for + * details). + */ + + // General purpose registers + public static final Register r0 = new Register(0, 0, 8, "r0", CPU, RegisterFlag.Byte); + public static final Register r1 = new Register(1, 1, 8, "r1", CPU, RegisterFlag.Byte); + public static final Register r2 = new Register(2, 2, 8, "r2", CPU, RegisterFlag.Byte); + public static final Register r3 = new Register(3, 3, 8, "r3", CPU, RegisterFlag.Byte); + public static final Register r4 = new Register(4, 4, 8, "r4", CPU, RegisterFlag.Byte); + public static final Register r5 = new Register(5, 5, 8, "r5", CPU, RegisterFlag.Byte); + public static final Register r6 = new Register(6, 6, 8, "r6", CPU, RegisterFlag.Byte); + public static final Register r7 = new Register(7, 7, 8, "r7", CPU, RegisterFlag.Byte); + + public static final Register r8 = new Register(8, 8, 8, "r8", CPU, RegisterFlag.Byte); + public static final Register r9 = new Register(9, 9, 8, "r9", CPU, RegisterFlag.Byte); + public static final Register r10 = new Register(10, 10, 8, "r10", CPU, RegisterFlag.Byte); + public static final Register r11 = new Register(11, 11, 8, "r11", CPU, RegisterFlag.Byte); + public static final Register r12 = new Register(12, 12, 8, "r12", CPU, RegisterFlag.Byte); + public static final Register r13 = new Register(13, 13, 8, "r13", CPU, RegisterFlag.Byte); + public static final Register r14 = new Register(14, 14, 8, "r14", CPU, RegisterFlag.Byte); + public static final Register r15 = new Register(15, 15, 8, "r15", CPU, RegisterFlag.Byte); + + public static final Register[] gprRegisters = { + r0, r1, r2, r3, r4, r5, r6, r7, + r8, r9, r10, r11, r12, r13, r14, r15 + }; + + // Floating point registers + public static final Register f0 = new Register(16, 0, 8, "f0", FPU); + public static final Register f1 = new Register(17, 1, 8, "f1", FPU); + public static final Register f2 = new Register(18, 2, 8, "f2", FPU); + public static final Register f3 = new Register(19, 3, 8, "f3", FPU); + public static final Register f4 = new Register(20, 4, 8, "f4", FPU); + public static final Register f5 = new Register(21, 5, 8, "f5", FPU); + public static final Register f6 = new Register(22, 6, 8, "f6", FPU); + public static final Register f7 = new Register(23, 7, 8, "f7", FPU); + + public static final Register f8 = new Register(24, 8, 8, "f8", FPU); + public static final Register f9 = new Register(25, 9, 8, "f9", FPU); + public static final Register f10 = new Register(26, 10, 8, "f10", FPU); + public static final Register f11 = new Register(27, 11, 8, "f11", FPU); + public static final Register f12 = new Register(28, 12, 8, "f12", FPU); + public static final Register f13 = new Register(29, 13, 8, "f13", FPU); + public static final Register f14 = new Register(30, 14, 8, "f14", FPU); + public static final Register f15 = new Register(31, 15, 8, "f15", FPU); + + public static final Register[] fpuRegisters = { + f0, f1, f2, f3, f4, f5, f6, f7, + f8, f9, f10, f11, f12, f13, f14, f15 + }; + + public static final Register[] allRegisters = { + // GPR + r0, r1, r2, r3, r4, r5, r6, r7, + r8, r9, r10, r11, r12, r13, r14, r15, + // FPU + f0, f1, f2, f3, f4, f5, f6, f7, + f8, f9, f10, f11, f12, f13, f14, f15 + }; + + public PTX() { + super("PTX", + 8, + ByteOrder.LITTLE_ENDIAN, + allRegisters, + LOAD_STORE | STORE_STORE, + 0, + r15.encoding + 1, + 8); + } + // @formatter:on +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTXAddress.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,123 @@ +/* + * 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.ptx; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; + +/** + * Represents an address in target machine memory, specified via some combination of a base register + * and a displacement. + */ +public final class PTXAddress extends Address { + + private static final long serialVersionUID = 8343625682010474837L; + + private final Value[] base; + private final long displacement; + + /** + * Creates an {@link PTXAddress} with given base register and no displacement. + * + * @param kind the kind of the value being addressed + * @param base the base register + */ + public PTXAddress(Kind kind, Value base) { + this(kind, base, 0); + } + + /** + * Creates an {@link PTXAddress} with given base register and a displacement. This is the most + * general constructor. + * + * @param kind the kind of the value being addressed + * @param base the base register + * @param displacement the displacement + */ + public PTXAddress(Kind kind, Value base, long displacement) { + super(kind); + this.base = new Value[1]; + this.setBase(base); + this.displacement = displacement; + + assert !isConstant(base) && !isStackSlot(base); + } + + @Override + public Value[] components() { + return base; + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append(getKind().getJavaName()).append("["); + String sep = ""; + if (isLegal(getBase())) { + s.append(getBase()); + sep = " + "; + } + if (getDisplacement() < 0) { + s.append(" - ").append(-getDisplacement()); + } else if (getDisplacement() > 0) { + s.append(sep).append(getDisplacement()); + } + s.append("]"); + return s.toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof PTXAddress) { + PTXAddress addr = (PTXAddress) obj; + return getKind() == addr.getKind() && getDisplacement() == addr.getDisplacement() && getBase().equals(addr.getBase()); + } + return false; + } + + @Override + public int hashCode() { + return getBase().hashCode() ^ ((int) getDisplacement() << 4) ^ (getKind().ordinal() << 12); + } + + /** + * @return Base register that defines the start of the address computation. If not present, is + * denoted by {@link Value#ILLEGAL}. + */ + public Value getBase() { + return base[0]; + } + + public void setBase(Value base) { + this.base[0] = base; + } + + /** + * @return Optional additive displacement. + */ + public long getDisplacement() { + return displacement; + } +}
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -280,7 +280,7 @@ @Test public void test10() { Mark[] noMarks = {}; - Call callAt63 = new Call("ignore", 63, 5, true, null); + Call callAt63 = new Call(null, 63, 5, true, null); Mark markAt63 = new Mark(63, "1", noMarks); test("compareSites", callAt63, callAt63); test("compareSites", callAt63, markAt63);
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -426,9 +426,9 @@ Assumptions assumptions = new Assumptions(true); new ComputeProbabilityPhase().apply(graph); Debug.dump(graph, "Graph"); - new InliningPhase(null, runtime(), null, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); + new InliningPhase(runtime(), null, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); Debug.dump(graph, "Graph"); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); assertNotInGraph(graph, Invoke.class);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/PointerTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,399 @@ +/* + * 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.snippets; + +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.compiler.test.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.snippets.Snippet.SnippetInliningPolicy; +import com.oracle.graal.word.*; + +/** + * Tests for the {@link Pointer} read and write operations. + */ +public class PointerTest extends GraalCompilerTest implements SnippetsInterface { + + private static final Object ID = new Object(); + private static final Kind[] KINDS = new Kind[]{Kind.Byte, Kind.Char, Kind.Short, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object}; + private final TargetDescription target; + private final SnippetInstaller installer; + + public PointerTest() { + target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget(); + installer = new SnippetInstaller(runtime, new Assumptions(false), target); + } + + private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>(); + + @Override + protected StructuredGraph parse(Method m) { + ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m); + return installer.makeGraph(resolvedMethod, inliningPolicy.get()); + } + + @Test + public void test_read1() { + for (Kind kind : KINDS) { + assertRead(parse("read" + kind.name() + "1"), kind, false, ID); + } + } + + @Test + public void test_read2() { + for (Kind kind : KINDS) { + assertRead(parse("read" + kind.name() + "2"), kind, true, ID); + } + } + + @Test + public void test_read3() { + for (Kind kind : KINDS) { + assertRead(parse("read" + kind.name() + "3"), kind, false, LocationNode.UNKNOWN_LOCATION); + } + } + + @Test + public void test_write1() { + for (Kind kind : KINDS) { + assertWrite(parse("write" + kind.name() + "1"), kind, false, ID); + } + } + + @Test + public void test_write2() { + for (Kind kind : KINDS) { + assertWrite(parse("write" + kind.name() + "2"), kind, true, ID); + } + } + + @Test + public void test_write3() { + for (Kind kind : KINDS) { + assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationNode.ANY_LOCATION); + } + } + + private void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, Object locationIdentity) { + ReadNode read = (ReadNode) graph.start().next(); + Assert.assertEquals(kind.getStackKind(), read.kind()); + + UnsafeCastNode cast = (UnsafeCastNode) read.object(); + Assert.assertEquals(graph.getLocal(0), cast.object()); + Assert.assertEquals(target.wordKind, cast.kind()); + + IndexedLocationNode location = (IndexedLocationNode) read.location(); + Assert.assertEquals(kind, location.getValueKind()); + Assert.assertEquals(locationIdentity, location.locationIdentity()); + Assert.assertEquals(1, location.indexScaling()); + + if (indexConvert) { + ConvertNode convert = (ConvertNode) location.index(); + Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); + Assert.assertEquals(graph.getLocal(1), convert.value()); + } else { + Assert.assertEquals(graph.getLocal(1), location.index()); + } + + ReturnNode ret = (ReturnNode) read.next(); + Assert.assertEquals(read, ret.result()); + } + + private void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, Object locationIdentity) { + WriteNode write = (WriteNode) graph.start().next(); + Assert.assertEquals(graph.getLocal(2), write.value()); + Assert.assertEquals(Kind.Void, write.kind()); + Assert.assertEquals(FrameState.INVALID_FRAMESTATE_BCI, write.stateAfter().bci); + + UnsafeCastNode cast = (UnsafeCastNode) write.object(); + Assert.assertEquals(graph.getLocal(0), cast.object()); + Assert.assertEquals(target.wordKind, cast.kind()); + + IndexedLocationNode location = (IndexedLocationNode) write.location(); + Assert.assertEquals(kind, location.getValueKind()); + Assert.assertEquals(locationIdentity, location.locationIdentity()); + Assert.assertEquals(1, location.indexScaling()); + + if (indexConvert) { + ConvertNode convert = (ConvertNode) location.index(); + Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); + Assert.assertEquals(graph.getLocal(1), convert.value()); + } else { + Assert.assertEquals(graph.getLocal(1), location.index()); + } + + AbstractStateSplit stateSplit = (AbstractStateSplit) write.next(); + Assert.assertEquals(FrameState.AFTER_BCI, stateSplit.stateAfter().bci); + + ReturnNode ret = (ReturnNode) stateSplit.next(); + Assert.assertEquals(null, ret.result()); + } + + @Snippet + public static byte readByte1(Object o, int offset) { + return Word.fromObject(o).readByte(offset, ID); + } + + @Snippet + public static byte readByte2(Object o, int offset) { + return Word.fromObject(o).readByte(Word.signed(offset), ID); + } + + @Snippet + public static byte readByte3(Object o, int offset) { + return Word.fromObject(o).readByte(offset); + } + + @Snippet + public static void writeByte1(Object o, int offset, byte value) { + Word.fromObject(o).writeByte(offset, value, ID); + } + + @Snippet + public static void writeByte2(Object o, int offset, byte value) { + Word.fromObject(o).writeByte(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeByte3(Object o, int offset, byte value) { + Word.fromObject(o).writeByte(offset, value); + } + + @Snippet + public static char readChar1(Object o, int offset) { + return Word.fromObject(o).readChar(offset, ID); + } + + @Snippet + public static char readChar2(Object o, int offset) { + return Word.fromObject(o).readChar(Word.signed(offset), ID); + } + + @Snippet + public static char readChar3(Object o, int offset) { + return Word.fromObject(o).readChar(offset); + } + + @Snippet + public static void writeChar1(Object o, int offset, char value) { + Word.fromObject(o).writeChar(offset, value, ID); + } + + @Snippet + public static void writeChar2(Object o, int offset, char value) { + Word.fromObject(o).writeChar(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeChar3(Object o, int offset, char value) { + Word.fromObject(o).writeChar(offset, value); + } + + @Snippet + public static short readShort1(Object o, int offset) { + return Word.fromObject(o).readShort(offset, ID); + } + + @Snippet + public static short readShort2(Object o, int offset) { + return Word.fromObject(o).readShort(Word.signed(offset), ID); + } + + @Snippet + public static short readShort3(Object o, int offset) { + return Word.fromObject(o).readShort(offset); + } + + @Snippet + public static void writeShort1(Object o, int offset, short value) { + Word.fromObject(o).writeShort(offset, value, ID); + } + + @Snippet + public static void writeShort2(Object o, int offset, short value) { + Word.fromObject(o).writeShort(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeShort3(Object o, int offset, short value) { + Word.fromObject(o).writeShort(offset, value); + } + + @Snippet + public static int readInt1(Object o, int offset) { + return Word.fromObject(o).readInt(offset, ID); + } + + @Snippet + public static int readInt2(Object o, int offset) { + return Word.fromObject(o).readInt(Word.signed(offset), ID); + } + + @Snippet + public static int readInt3(Object o, int offset) { + return Word.fromObject(o).readInt(offset); + } + + @Snippet + public static void writeInt1(Object o, int offset, int value) { + Word.fromObject(o).writeInt(offset, value, ID); + } + + @Snippet + public static void writeInt2(Object o, int offset, int value) { + Word.fromObject(o).writeInt(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeInt3(Object o, int offset, int value) { + Word.fromObject(o).writeInt(offset, value); + } + + @Snippet + public static long readLong1(Object o, int offset) { + return Word.fromObject(o).readLong(offset, ID); + } + + @Snippet + public static long readLong2(Object o, int offset) { + return Word.fromObject(o).readLong(Word.signed(offset), ID); + } + + @Snippet + public static long readLong3(Object o, int offset) { + return Word.fromObject(o).readLong(offset); + } + + @Snippet + public static void writeLong1(Object o, int offset, long value) { + Word.fromObject(o).writeLong(offset, value, ID); + } + + @Snippet + public static void writeLong2(Object o, int offset, long value) { + Word.fromObject(o).writeLong(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeLong3(Object o, int offset, long value) { + Word.fromObject(o).writeLong(offset, value); + } + + @Snippet + public static float readFloat1(Object o, int offset) { + return Word.fromObject(o).readFloat(offset, ID); + } + + @Snippet + public static float readFloat2(Object o, int offset) { + return Word.fromObject(o).readFloat(Word.signed(offset), ID); + } + + @Snippet + public static float readFloat3(Object o, int offset) { + return Word.fromObject(o).readFloat(offset); + } + + @Snippet + public static void writeFloat1(Object o, int offset, float value) { + Word.fromObject(o).writeFloat(offset, value, ID); + } + + @Snippet + public static void writeFloat2(Object o, int offset, float value) { + Word.fromObject(o).writeFloat(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeFloat3(Object o, int offset, float value) { + Word.fromObject(o).writeFloat(offset, value); + } + + @Snippet + public static double readDouble1(Object o, int offset) { + return Word.fromObject(o).readDouble(offset, ID); + } + + @Snippet + public static double readDouble2(Object o, int offset) { + return Word.fromObject(o).readDouble(Word.signed(offset), ID); + } + + @Snippet + public static double readDouble3(Object o, int offset) { + return Word.fromObject(o).readDouble(offset); + } + + @Snippet + public static void writeDouble1(Object o, int offset, double value) { + Word.fromObject(o).writeDouble(offset, value, ID); + } + + @Snippet + public static void writeDouble2(Object o, int offset, double value) { + Word.fromObject(o).writeDouble(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeDouble3(Object o, int offset, double value) { + Word.fromObject(o).writeDouble(offset, value); + } + + @Snippet + public static Object readObject1(Object o, int offset) { + return Word.fromObject(o).readObject(offset, ID); + } + + @Snippet + public static Object readObject2(Object o, int offset) { + return Word.fromObject(o).readObject(Word.signed(offset), ID); + } + + @Snippet + public static Object readObject3(Object o, int offset) { + return Word.fromObject(o).readObject(offset); + } + + @Snippet + public static void writeObject1(Object o, int offset, Object value) { + Word.fromObject(o).writeObject(offset, value, ID); + } + + @Snippet + public static void writeObject2(Object o, int offset, Object value) { + Word.fromObject(o).writeObject(Word.signed(offset), value, ID); + } + + @Snippet + public static void writeObject3(Object o, int offset, Object value) { + Word.fromObject(o).writeObject(offset, value); + } + +}
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -29,7 +29,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; import com.oracle.graal.snippets.Snippet.SnippetInliningPolicy; @@ -43,7 +42,7 @@ private final SnippetInstaller installer; public WordTest() { - TargetDescription target = Graal.getRequiredCapability(GraalCompiler.class).target; + TargetDescription target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget(); installer = new SnippetInstaller(runtime, new Assumptions(false), target); } @@ -52,7 +51,7 @@ @Override protected StructuredGraph parse(Method m) { ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m); - return installer.makeGraph(resolvedMethod, inliningPolicy.get(), false); + return installer.makeGraph(resolvedMethod, inliningPolicy.get()); } @Test
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java Mon Mar 04 10:00:49 2013 +0100 @@ -223,11 +223,15 @@ usage.replaceFirstInput(instanceOf, instantiation.asCondition(trueValue)); } + private boolean usageFollowsInstantiation() { + return instantiation.result != null && instantiation.result.merge().next() == usage; + } + @Override public void replace(ValueNode oldNode, ValueNode newNode) { assert newNode instanceof PhiNode; assert oldNode == instanceOf; - if (sameBlock && solitaryUsage) { + if (sameBlock && solitaryUsage && usageFollowsInstantiation()) { removeIntermediateMaterialization(newNode); } else { newNode.inferStamp();
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetFrameStateCleanupPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetFrameStateCleanupPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -22,30 +22,98 @@ */ package com.oracle.graal.snippets; -import com.oracle.graal.graph.*; +import java.util.*; + import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.graph.*; +import com.oracle.graal.phases.graph.ReentrantNodeIterator.LoopInfo; +import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; /** * Removes frame states from {@linkplain StateSplit#hasSideEffect() non-side-effecting} nodes in a * snippet. + * + * The frame states of side-effecting nodes are replaced with + * {@linkplain FrameState#INVALID_FRAMESTATE_BCI invalid} frame states. Loops that contain invalid + * frame states are also assigned an invalid frame state. + * + * The invalid frame states ensure that no deoptimization to a snippet frame state will happen. */ public class SnippetFrameStateCleanupPhase extends Phase { @Override protected void run(StructuredGraph graph) { - for (Node node : graph.getNodes().filterInterface(StateSplit.class)) { - StateSplit stateSplit = (StateSplit) node; - FrameState frameState = stateSplit.stateAfter(); - if (!stateSplit.hasSideEffect()) { + ReentrantNodeIterator.apply(new SnippetFrameStateCleanupClosure(), graph.start(), new CleanupState(false), null); + } + + private static class CleanupState { + + public boolean containsFrameState; + + public CleanupState(boolean containsFrameState) { + this.containsFrameState = containsFrameState; + } + } + + /** + * A proper (loop-aware) iteration over the graph is used to detect loops that contain invalid + * frame states, so that they can be marked with an invalid frame state. + */ + private static class SnippetFrameStateCleanupClosure extends NodeIteratorClosure<CleanupState> { + + @Override + protected void processNode(FixedNode node, CleanupState currentState) { + if (node instanceof StateSplit) { + StateSplit stateSplit = (StateSplit) node; + FrameState frameState = stateSplit.stateAfter(); if (frameState != null) { - stateSplit.setStateAfter(null); + if (stateSplit.hasSideEffect()) { + currentState.containsFrameState = true; + stateSplit.setStateAfter(node.graph().add(new FrameState(FrameState.INVALID_FRAMESTATE_BCI))); + } else { + stateSplit.setStateAfter(null); + } if (frameState.usages().isEmpty()) { GraphUtil.killWithUnusedFloatingInputs(frameState); } } } } + + @Override + protected CleanupState merge(MergeNode merge, List<CleanupState> states) { + for (CleanupState state : states) { + if (state.containsFrameState) { + return new CleanupState(true); + } + } + return new CleanupState(false); + } + + @Override + protected CleanupState afterSplit(BeginNode node, CleanupState oldState) { + return new CleanupState(oldState.containsFrameState); + } + + @Override + protected Map<LoopExitNode, CleanupState> processLoop(LoopBeginNode loop, CleanupState initialState) { + LoopInfo<CleanupState> info = ReentrantNodeIterator.processLoop(this, loop, new CleanupState(false)); + boolean containsFrameState = false; + for (CleanupState state : info.endStates.values()) { + containsFrameState |= state.containsFrameState; + } + if (containsFrameState) { + loop.setStateAfter(loop.graph().add(new FrameState(FrameState.INVALID_FRAMESTATE_BCI))); + } + if (containsFrameState || initialState.containsFrameState) { + for (CleanupState state : info.exitStates.values()) { + state.containsFrameState = true; + } + } + return info.exitStates; + } + } }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Mon Mar 04 10:00:49 2013 +0100 @@ -89,7 +89,7 @@ } ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method); assert snippet.getCompilerStorage().get(Graph.class) == null : method; - StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet), false); + StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet)); // System.out.println("snippet: " + graph); snippet.getCompilerStorage().put(Graph.class, graph); } @@ -152,9 +152,8 @@ substitute = runtime.lookupJavaMethod(substituteMethod); original = runtime.lookupJavaMethod(originalMethod); try { - // System.out.println("substitution: " + MetaUtil.format("%H.%n(%p)", original) + - // " --> " + MetaUtil.format("%H.%n(%p)", substitute)); - StructuredGraph graph = makeGraph(substitute, inliningPolicy(substitute), true); + Debug.log("substitution: " + MetaUtil.format("%H.%n(%p)", original) + " --> " + MetaUtil.format("%H.%n(%p)", substitute)); + StructuredGraph graph = makeGraph(substitute, inliningPolicy(substitute)); Object oldValue = original.getCompilerStorage().put(Graph.class, graph); assert oldValue == null; } finally { @@ -192,7 +191,7 @@ } } - public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy, final boolean isSubstitution) { + public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { return Debug.scope("BuildSnippetGraph", new Object[]{method}, new Callable<StructuredGraph>() { @Override @@ -201,12 +200,8 @@ new SnippetIntrinsificationPhase(runtime, pool, SnippetTemplate.hasConstantParameter(method)).apply(graph); - if (isSubstitution && !substituteCallsOriginal) { - // TODO (ds) remove the constraint of only processing substitutions - // once issues with the arraycopy snippets have been resolved - new SnippetFrameStateCleanupPhase().apply(graph); - new DeadCodeEliminationPhase().apply(graph); - } + new SnippetFrameStateCleanupPhase().apply(graph); + new DeadCodeEliminationPhase().apply(graph); new InsertStateAfterPlaceholderPhase().apply(graph); @@ -221,7 +216,6 @@ StructuredGraph graph = graphCache.get(method); if (graph == null) { graph = buildGraph(method, policy == null ? inliningPolicy(method) : policy); - // System.out.println("built " + graph); graphCache.put(method, graph); } return graph; @@ -248,13 +242,9 @@ new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(originalGraph); InliningUtil.inline(invoke, originalGraph, true); - // TODO the inlined frame states still show the call from the substitute to the - // original. - // If this poses a problem, a phase should added to fix up these frame states. - Debug.dump(graph, "after inlining %s", callee); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + new CanonicalizerPhase(runtime, assumptions).apply(graph); } substituteCallsOriginal = true; } else { @@ -264,7 +254,7 @@ Debug.dump(graph, "after inlining %s", callee); if (GraalOptions.OptCanonicalizer) { new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + new CanonicalizerPhase(runtime, assumptions).apply(graph); } } } @@ -276,7 +266,7 @@ new DeadCodeEliminationPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + new CanonicalizerPhase(runtime, assumptions).apply(graph); } for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -364,7 +364,7 @@ if (newInstance instanceof ValueNode && (((ValueNode) newInstance).kind() != Kind.Object || ((ValueNode) newInstance).stamp() == StampFactory.forNodeIntrinsic())) { StructuredGraph graph = (StructuredGraph) newInstance.graph(); for (CheckCastNode checkCastNode : newInstance.usages().filter(CheckCastNode.class).snapshot()) { - for (ValueProxyNode vpn : checkCastNode.usages().filter(ValueProxyNode.class).snapshot()) { + for (ProxyNode vpn : checkCastNode.usages().filter(ProxyNode.class).snapshot()) { graph.replaceFloating(vpn, checkCastNode); } for (Node checkCastUsage : checkCastNode.usages().snapshot()) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetProvider.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetProvider.java Mon Mar 04 10:00:49 2013 +0100 @@ -23,8 +23,9 @@ package com.oracle.graal.snippets; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.target.*; public interface SnippetProvider { - void installSnippets(SnippetInstaller installer, Assumptions assumptions); + void installSnippets(Backend backend, SnippetInstaller installer, Assumptions assumptions); }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Mon Mar 04 10:00:49 2013 +0100 @@ -285,7 +285,7 @@ new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime), false).apply(snippetCopy); new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy); - new CanonicalizerPhase(null, runtime, assumptions, 0, null).apply(snippetCopy); + new CanonicalizerPhase(runtime, assumptions, 0, null).apply(snippetCopy); } // Gather the template parameters @@ -344,7 +344,7 @@ LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin); int mark = snippetCopy.getMark(); LoopTransformations.fullUnroll(loop, runtime, null); - new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(snippetCopy); + new CanonicalizerPhase(runtime, assumptions, mark, null).apply(snippetCopy); } FixedNode explodeLoopNext = explodeLoop.next(); explodeLoop.clearSuccessors();
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectObjectStoreNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectObjectStoreNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -62,7 +62,7 @@ @Override public void lower(LoweringTool tool) { StructuredGraph graph = (StructuredGraph) this.graph(); - IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, false); + IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), displacement, offset, graph, 1); WriteNode write = graph.add(new WriteNode(object, value, location)); graph.replaceFixedWithFixed(this, write); }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectReadNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectReadNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.snippets.nodes; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -46,7 +45,7 @@ @Override public void generate(LIRGeneratorTool gen) { - gen.setResult(this, gen.emitLoad(new Address(readKind, gen.operand(address)), false)); + gen.setResult(this, gen.emitLoad(readKind, gen.operand(address), 0, Value.ILLEGAL, 0, false)); } @NodeIntrinsic
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectStoreNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/DirectStoreNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.snippets.nodes; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -49,7 +48,7 @@ @Override public void generate(LIRGeneratorTool gen) { Value v = gen.operand(value); - gen.emitStore(new Address(kind, gen.operand(address)), v, false); + gen.emitStore(kind, gen.operand(address), 0, Value.ILLEGAL, 0, v, false); } /*
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MacroNode.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MacroNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.common.*; public class MacroNode extends AbstractStateSplit implements Lowerable { @@ -47,14 +48,32 @@ this.returnType = invoke.methodCallTarget().returnType(); } + public int getBci() { + return bci; + } + + public ResolvedJavaMethod getTargetMethod() { + return targetMethod; + } + + @SuppressWarnings("unused") + protected StructuredGraph getSnippetGraph(LoweringTool tool) { + return null; + } + @Override public void lower(LoweringTool tool) { - replaceWithInvoke(); + StructuredGraph snippetGraph = getSnippetGraph(tool); + + InvokeNode invoke = replaceWithInvoke(); + + if (snippetGraph != null) { + InliningUtil.inline(invoke, snippetGraph, false); + } } - public InvokeNode replaceWithInvoke() { + private InvokeNode replaceWithInvoke() { InvokeNode invoke = createInvoke(); - ((StructuredGraph) graph()).replaceFixedWithFixed(this, invoke); return invoke; }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java Mon Mar 04 10:00:49 2013 +0100 @@ -32,10 +32,9 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.Virtualizable.EscapeState; import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.phases.graph.ReentrantBlockIterator.MergeableBlockState; import com.oracle.graal.virtual.nodes.*; -class BlockState extends MergeableBlockState<BlockState> { +class BlockState { private final HashMap<VirtualObjectNode, ObjectState> objectStates = new HashMap<>(); private final HashMap<ValueNode, VirtualObjectNode> objectAliases = new HashMap<>(); @@ -70,7 +69,6 @@ return object == null ? null : getObjectState(object); } - @Override public BlockState cloneState() { return new BlockState(this); }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -40,14 +40,12 @@ public class PartialEscapeAnalysisPhase extends Phase { - private final TargetDescription target; private final MetaAccessProvider runtime; private final Assumptions assumptions; private CustomCanonicalizer customCanonicalizer; private final boolean iterative; - public PartialEscapeAnalysisPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, boolean iterative) { - this.target = target; + public PartialEscapeAnalysisPhase(MetaAccessProvider runtime, Assumptions assumptions, boolean iterative) { this.runtime = runtime; this.assumptions = assumptions; this.iterative = iterative; @@ -114,7 +112,7 @@ return false; } if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions, null, customCanonicalizer).apply(graph); + new CanonicalizerPhase(runtime, assumptions, null, customCanonicalizer).apply(graph); } return true; }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Mon Mar 04 10:00:49 2013 +0100 @@ -457,9 +457,9 @@ } private void processLoopExit(LoopExitNode exitNode, BlockState initialState, BlockState exitState) { - HashMap<VirtualObjectNode, ValueProxyNode> proxies = new HashMap<>(); + HashMap<VirtualObjectNode, ProxyNode> proxies = new HashMap<>(); - for (ValueProxyNode proxy : exitNode.proxies()) { + for (ProxyNode proxy : exitNode.proxies()) { ObjectState obj = exitState.getObjectState(proxy.value()); if (obj != null) { proxies.put(obj.virtual, proxy); @@ -473,7 +473,7 @@ ObjectState valueObj = exitState.getObjectState(value); if (valueObj == null) { if ((value instanceof PhiNode && ((PhiNode) value).merge() == exitNode.loopBegin()) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) { - ValueProxyNode proxy = new ValueProxyNode(value, exitNode, PhiType.Value); + ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value); obj.setEntry(i, proxy); effects.addFloatingNode(proxy); } @@ -481,9 +481,9 @@ } } else { if (initialObj == null || initialObj.isVirtual()) { - ValueProxyNode proxy = proxies.get(obj.virtual); + ProxyNode proxy = proxies.get(obj.virtual); if (proxy == null) { - proxy = new ValueProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value); + proxy = new ProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value); effects.addFloatingNode(proxy); } else { effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue());
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Pointer.java Mon Mar 04 10:00:49 2013 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.word; +import com.oracle.graal.nodes.extended.*; + public interface Pointer extends Unsigned { /** @@ -42,6 +44,438 @@ * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + byte readByte(WordBase offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + char readChar(WordBase offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + short readShort(WordBase offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + int readInt(WordBase offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + long readLong(WordBase offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + float readFloat(WordBase offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + double readDouble(WordBase offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + Word readWord(WordBase offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + Object readObject(WordBase offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + byte readByte(int offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + char readChar(int offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + short readShort(int offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + int readInt(int offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + long readLong(int offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + float readFloat(int offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + double readDouble(int offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + Word readWord(int offset, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + Object readObject(int offset, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeByte(WordBase offset, byte val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeChar(WordBase offset, char val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeShort(WordBase offset, short val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeInt(WordBase offset, int val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeLong(WordBase offset, long val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeFloat(WordBase offset, float val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeDouble(WordBase offset, double val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeWord(WordBase offset, WordBase val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeObject(WordBase offset, Object val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeByte(int offset, byte val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeChar(int offset, char val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeShort(int offset, short val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeInt(int offset, int val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeLong(int offset, long val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeFloat(int offset, float val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeDouble(int offset, double val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeWord(int offset, WordBase val, Object locationIdentity); + + /** + * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + void writeObject(int offset, Object val, Object locationIdentity); + + /** + * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in + * bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param offset the signed offset for the memory access * @return the result of the memory access */ byte readByte(WordBase offset); @@ -232,150 +666,6 @@ Object readObject(int offset); /** - * Reads the constant memory at address {@code (this + offset)}. Both the base address and - * offset are in bytes. - * <p> - * The caller guarantees that the memory content is final, i.e., never changing. The compiler - * can therefore eliminate memory accesses more aggressively. - * <p> - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller - * knows that the highest-order bit of the unsigned value is never used). - * - * @param offset the signed offset for the memory access - * @return the result of the memory access - */ - byte readFinalByte(WordBase offset); - - /** - * Reads the constant memory at address {@code (this + offset)}. Both the base address and - * offset are in bytes. - * <p> - * The caller guarantees that the memory content is final, i.e., never changing. The compiler - * can therefore eliminate memory accesses more aggressively. - * <p> - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller - * knows that the highest-order bit of the unsigned value is never used). - * - * @param offset the signed offset for the memory access - * @return the result of the memory access - */ - char readFinalChar(WordBase offset); - - /** - * Reads the constant memory at address {@code (this + offset)}. Both the base address and - * offset are in bytes. - * <p> - * The caller guarantees that the memory content is final, i.e., never changing. The compiler - * can therefore eliminate memory accesses more aggressively. - * <p> - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller - * knows that the highest-order bit of the unsigned value is never used). - * - * @param offset the signed offset for the memory access - * @return the result of the memory access - */ - short readFinalShort(WordBase offset); - - /** - * Reads the constant memory at address {@code (this + offset)}. Both the base address and - * offset are in bytes. - * <p> - * The caller guarantees that the memory content is final, i.e., never changing. The compiler - * can therefore eliminate memory accesses more aggressively. - * <p> - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller - * knows that the highest-order bit of the unsigned value is never used). - * - * @param offset the signed offset for the memory access - * @return the result of the memory access - */ - int readFinalInt(WordBase offset); - - /** - * Reads the constant memory at address {@code (this + offset)}. Both the base address and - * offset are in bytes. - * <p> - * The caller guarantees that the memory content is final, i.e., never changing. The compiler - * can therefore eliminate memory accesses more aggressively. - * <p> - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller - * knows that the highest-order bit of the unsigned value is never used). - * - * @param offset the signed offset for the memory access - * @return the result of the memory access - */ - long readFinalLong(WordBase offset); - - /** - * Reads the constant memory at address {@code (this + offset)}. Both the base address and - * offset are in bytes. - * <p> - * The caller guarantees that the memory content is final, i.e., never changing. The compiler - * can therefore eliminate memory accesses more aggressively. - * <p> - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller - * knows that the highest-order bit of the unsigned value is never used). - * - * @param offset the signed offset for the memory access - * @return the result of the memory access - */ - float readFinalFloat(WordBase offset); - - /** - * Reads the constant memory at address {@code (this + offset)}. Both the base address and - * offset are in bytes. - * <p> - * The caller guarantees that the memory content is final, i.e., never changing. The compiler - * can therefore eliminate memory accesses more aggressively. - * <p> - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller - * knows that the highest-order bit of the unsigned value is never used). - * - * @param offset the signed offset for the memory access - * @return the result of the memory access - */ - double readFinalDouble(WordBase offset); - - /** - * Reads the constant memory at address {@code (this + offset)}. Both the base address and - * offset are in bytes. - * <p> - * The caller guarantees that the memory content is final, i.e., never changing. The compiler - * can therefore eliminate memory accesses more aggressively. - * <p> - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller - * knows that the highest-order bit of the unsigned value is never used). - * - * @param offset the signed offset for the memory access - * @return the result of the memory access - */ - Word readFinalWord(WordBase offset); - - /** - * Reads the constant memory at address {@code (this + offset)}. Both the base address and - * offset are in bytes. - * <p> - * The caller guarantees that the memory content is final, i.e., never changing. The compiler - * can therefore eliminate memory accesses more aggressively. - * <p> - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller - * knows that the highest-order bit of the unsigned value is never used). - * - * @param offset the signed offset for the memory access - * @return the result of the memory access - */ - Object readFinalObject(WordBase offset); - - /** * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. * <p> @@ -412,7 +702,7 @@ * @param offset the signed offset for the memory access * @param val the value to be written to memory */ - void writeShort(WordBase offset, Short val); + void writeShort(WordBase offset, short val); /** * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Mon Mar 04 10:00:49 2013 +0100 @@ -58,7 +58,6 @@ COMPARISON, NOT, READ, - READ_FINAL, WRITE, ZERO, FROM_UNSIGNED, @@ -598,6 +597,218 @@ @Override @Operation(opcode = Opcode.READ) + public byte readByte(WordBase offset, Object locationIdentity) { + return unsafe.getByte(add((Word) offset).unbox()); + } + + @Override + @Operation(opcode = Opcode.READ) + public char readChar(WordBase offset, Object locationIdentity) { + return unsafe.getChar(add((Word) offset).unbox()); + } + + @Override + @Operation(opcode = Opcode.READ) + public short readShort(WordBase offset, Object locationIdentity) { + return unsafe.getShort(add((Word) offset).unbox()); + } + + @Override + @Operation(opcode = Opcode.READ) + public int readInt(WordBase offset, Object locationIdentity) { + return unsafe.getInt(add((Word) offset).unbox()); + } + + @Override + @Operation(opcode = Opcode.READ) + public long readLong(WordBase offset, Object locationIdentity) { + return unsafe.getLong(add((Word) offset).unbox()); + } + + @Override + @Operation(opcode = Opcode.READ) + public float readFloat(WordBase offset, Object locationIdentity) { + return unsafe.getFloat(add((Word) offset).unbox()); + } + + @Override + @Operation(opcode = Opcode.READ) + public double readDouble(WordBase offset, Object locationIdentity) { + return unsafe.getDouble(add((Word) offset).unbox()); + } + + @Override + @Operation(opcode = Opcode.READ) + public Word readWord(WordBase offset, Object locationIdentity) { + return box(unsafe.getAddress(add((Word) offset).unbox())); + } + + @Override + @Operation(opcode = Opcode.READ) + public native Object readObject(WordBase offset, Object locationIdentity); + + @Override + @Operation(opcode = Opcode.READ) + public byte readByte(int offset, Object locationIdentity) { + return readByte(signed(offset), locationIdentity); + } + + @Override + @Operation(opcode = Opcode.READ) + public char readChar(int offset, Object locationIdentity) { + return readChar(signed(offset), locationIdentity); + } + + @Override + @Operation(opcode = Opcode.READ) + public short readShort(int offset, Object locationIdentity) { + return readShort(signed(offset), locationIdentity); + } + + @Override + @Operation(opcode = Opcode.READ) + public int readInt(int offset, Object locationIdentity) { + return readInt(signed(offset), locationIdentity); + } + + @Override + @Operation(opcode = Opcode.READ) + public long readLong(int offset, Object locationIdentity) { + return readLong(signed(offset), locationIdentity); + } + + @Override + @Operation(opcode = Opcode.READ) + public float readFloat(int offset, Object locationIdentity) { + return readFloat(signed(offset), locationIdentity); + } + + @Override + @Operation(opcode = Opcode.READ) + public double readDouble(int offset, Object locationIdentity) { + return readDouble(signed(offset), locationIdentity); + } + + @Override + @Operation(opcode = Opcode.READ) + public Word readWord(int offset, Object locationIdentity) { + return readWord(signed(offset), locationIdentity); + } + + @Override + @Operation(opcode = Opcode.READ) + public Object readObject(int offset, Object locationIdentity) { + return readObject(signed(offset), locationIdentity); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeByte(WordBase offset, byte val, Object locationIdentity) { + unsafe.putByte(add((Word) offset).unbox(), val); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeChar(WordBase offset, char val, Object locationIdentity) { + unsafe.putChar(add((Word) offset).unbox(), val); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeShort(WordBase offset, short val, Object locationIdentity) { + unsafe.putShort(add((Word) offset).unbox(), val); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeInt(WordBase offset, int val, Object locationIdentity) { + unsafe.putInt(add((Word) offset).unbox(), val); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeLong(WordBase offset, long val, Object locationIdentity) { + unsafe.putLong(add((Word) offset).unbox(), val); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeFloat(WordBase offset, float val, Object locationIdentity) { + unsafe.putFloat(add((Word) offset).unbox(), val); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeDouble(WordBase offset, double val, Object locationIdentity) { + unsafe.putDouble(add((Word) offset).unbox(), val); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeWord(WordBase offset, WordBase val, Object locationIdentity) { + unsafe.putAddress(add((Word) offset).unbox(), ((Word) val).unbox()); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public native void writeObject(WordBase offset, Object val, Object locationIdentity); + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeByte(int offset, byte val, Object locationIdentity) { + writeByte(signed(offset), val, locationIdentity); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeChar(int offset, char val, Object locationIdentity) { + writeChar(signed(offset), val, locationIdentity); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeShort(int offset, short val, Object locationIdentity) { + writeShort(signed(offset), val, locationIdentity); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeInt(int offset, int val, Object locationIdentity) { + writeInt(signed(offset), val, locationIdentity); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeLong(int offset, long val, Object locationIdentity) { + writeLong(signed(offset), val, locationIdentity); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeFloat(int offset, float val, Object locationIdentity) { + writeFloat(signed(offset), val, locationIdentity); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeDouble(int offset, double val, Object locationIdentity) { + writeDouble(signed(offset), val, locationIdentity); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeWord(int offset, WordBase val, Object locationIdentity) { + writeWord(signed(offset), val, locationIdentity); + } + + @Override + @Operation(opcode = Opcode.WRITE) + public void writeObject(int offset, Object val, Object locationIdentity) { + writeObject(signed(offset), val, locationIdentity); + } + + @Override + @Operation(opcode = Opcode.READ) public byte readByte(WordBase offset) { return unsafe.getByte(add((Word) offset).unbox()); } @@ -703,60 +914,6 @@ } @Override - @Operation(opcode = Opcode.READ_FINAL) - public byte readFinalByte(WordBase offset) { - return readByte(offset); - } - - @Override - @Operation(opcode = Opcode.READ_FINAL) - public char readFinalChar(WordBase offset) { - return readChar(offset); - } - - @Override - @Operation(opcode = Opcode.READ_FINAL) - public short readFinalShort(WordBase offset) { - return readShort(offset); - } - - @Override - @Operation(opcode = Opcode.READ_FINAL) - public int readFinalInt(WordBase offset) { - return readInt(offset); - } - - @Override - @Operation(opcode = Opcode.READ_FINAL) - public long readFinalLong(WordBase offset) { - return readLong(offset); - } - - @Override - @Operation(opcode = Opcode.READ_FINAL) - public float readFinalFloat(WordBase offset) { - return readFloat(offset); - } - - @Override - @Operation(opcode = Opcode.READ_FINAL) - public double readFinalDouble(WordBase offset) { - return readDouble(offset); - } - - @Override - @Operation(opcode = Opcode.READ_FINAL) - public Word readFinalWord(WordBase offset) { - return readWord(offset); - } - - @Override - @Operation(opcode = Opcode.READ_FINAL) - public Object readFinalObject(WordBase offset) { - return readObject(offset); - } - - @Override @Operation(opcode = Opcode.WRITE) public void writeByte(WordBase offset, byte val) { unsafe.putByte(add((Word) offset).unbox(), val); @@ -770,7 +927,7 @@ @Override @Operation(opcode = Opcode.WRITE) - public void writeShort(WordBase offset, Short val) { + public void writeShort(WordBase offset, short val) { unsafe.putShort(add((Word) offset).unbox(), val); }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Mar 04 10:00:49 2013 +0100 @@ -138,18 +138,17 @@ break; case READ: - assert arguments.size() == 2; - replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, LocationNode.ANY_LOCATION)); - break; - - case READ_FINAL: - assert arguments.size() == 2; - replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, LocationNode.FINAL_LOCATION)); + assert arguments.size() == 2 || arguments.size() == 3; + Kind readKind = asKind(callTargetNode.returnType()); + Object readLocation = arguments.size() == 2 ? LocationNode.UNKNOWN_LOCATION : arguments.get(2).asConstant().asObject(); + replace(invoke, readOp(graph, arguments.get(0), arguments.get(1), invoke, readKind, readLocation)); break; case WRITE: - assert arguments.size() == 3; - replace(invoke, writeOp(graph, arguments.get(0), arguments.get(1), arguments.get(2), invoke, LocationNode.ANY_LOCATION)); + assert arguments.size() == 3 || arguments.size() == 4; + Kind writeKind = asKind(targetMethod.getSignature().getParameterType(1, targetMethod.getDeclaringClass())); + Object writeLocation = arguments.size() == 3 ? LocationNode.ANY_LOCATION : arguments.get(3).asConstant().asObject(); + replace(invoke, writeOp(graph, arguments.get(0), arguments.get(1), arguments.get(2), invoke, writeKind, writeLocation)); break; case ZERO: @@ -259,8 +258,8 @@ return op; } - private static ValueNode readOp(StructuredGraph graph, ValueNode base, ValueNode offset, Invoke invoke, Object locationIdentity) { - IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, invoke.node().kind(), 0, offset, graph, false); + private static ValueNode readOp(StructuredGraph graph, ValueNode base, ValueNode offset, Invoke invoke, Kind readKind, Object locationIdentity) { + IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, readKind, 0, offset, graph, 1); ReadNode read = graph.add(new ReadNode(base, location, invoke.node().stamp())); graph.addBeforeFixed(invoke.node(), read); // The read must not float outside its block otherwise it may float above an explicit zero @@ -269,9 +268,10 @@ return read; } - private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode offset, ValueNode value, Invoke invoke, Object locationIdentity) { - IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, value.kind(), 0, offset, graph, false); + private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode offset, ValueNode value, Invoke invoke, Kind writeKind, Object locationIdentity) { + IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, writeKind, 0, offset, graph, 1); WriteNode write = graph.add(new WriteNode(base, value, location)); + write.setStateAfter(invoke.stateAfter()); graph.addBeforeFixed(invoke.node(), write); return write; } @@ -324,6 +324,14 @@ return false; } + public Kind asKind(JavaType type) { + if (type instanceof ResolvedJavaType) { + return isWord((ResolvedJavaType) type) ? wordKind : type.getKind(); + } else { + return Kind.Object; + } + } + private void changeToWord(ValueNode valueNode) { if (valueNode.isConstant() && valueNode.asConstant().getKind() == Kind.Object) { WordBase value = (WordBase) valueNode.asConstant().asObject();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/NodeFactory.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,66 @@ +/* + * 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.truffle.api.codegen; + +import java.util.*; + +/** + * Enables the dynamic creation of generated nodes. It provides an convenient way to instantiate + * generated node classes without using reflection. + */ +public interface NodeFactory<T> { + + /** + * Instantiates the node using the arguments array. The arguments length and types must suffice + * one of the returned signatures in {@link #getNodeSignatures()}. If the arguments array does + * not suffice one of the node signatures an {@link IllegalArgumentException} is thrown. + * + * @param arguments the argument values + * @return the instantiated node + * @throws IllegalArgumentException + */ + T createNode(Object... arguments); + + /** + * Instantiates a new specialized variant of the node. This is an optional method and throws an + * {@link UnsupportedOperationException} if not supported. + * + * @param thisNode the current node + * @param specializionClasses + * @return the specialized node + */ + T createNodeSpecialized(T thisNode, Class<?>... specializionClasses); + + /** + * Returns the node class that will get created by {@link #createNode(Object...)}. The node + * class does not match exactly to the instantiated object but they are guaranteed to be + * assignable. + */ + Class<T> getNodeClass(); + + /** + * Returns a list of signatures that can be used to invoke {@link #createNode(Object...)}. + */ + List<List<Class<?>>> getNodeSignatures(); + +}
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Mon Mar 04 10:00:49 2013 +0100 @@ -28,6 +28,7 @@ import javax.lang.model.type.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.intrinsics.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.nodes.Node.Children; @@ -44,6 +45,7 @@ private final TypeMirror stableAnnotation; private final TypeMirror contentStableAnnotation; private final TypeMirror typeConversion; + private final TypeMirror truffleIntrinsics; private final List<String> errors = new ArrayList<>(); @@ -55,6 +57,7 @@ stableAnnotation = getRequired(context, Child.class); contentStableAnnotation = getRequired(context, Children.class); typeConversion = getRequired(context, TypeConversion.class); + truffleIntrinsics = getRequired(context, TruffleIntrinsics.class); } public boolean verify(ProcessorContext context, Element element, AnnotationMirror mirror) { @@ -77,6 +80,10 @@ return type; } + public TypeMirror getTruffleIntrinsics() { + return truffleIntrinsics; + } + public TypeMirror getTypeConversion() { return typeConversion; }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Mon Mar 04 10:00:49 2013 +0100 @@ -47,6 +47,14 @@ } } + public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) { + TypeMirror boxedType = primitiveType; + if (boxedType.getKind().isPrimitive()) { + boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType(); + } + return boxedType; + } + public static List<AnnotationMirror> collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element, Class<? extends Annotation> annotationClass) { List<AnnotationMirror> result = Utils.getAnnotationValueList(markerAnnotation, elementName); @@ -61,6 +69,42 @@ return result; } + public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror[] types) { + if (types.length == 0) { + return context.getType(Object.class); + } + TypeMirror prev = types[0]; + for (int i = 1; i < types.length; i++) { + prev = getCommonSuperType(context, prev, types[i]); + } + return prev; + } + + public static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) { + if (typeEquals(type1, type2)) { + return type1; + } + TypeElement element1 = fromTypeMirror(type1); + TypeElement element2 = fromTypeMirror(type2); + if (element1 == null || element2 == null) { + return context.getType(Object.class); + } + + List<TypeElement> element1Types = getDirectSuperTypes(element1); + element1Types.add(0, element1); + List<TypeElement> element2Types = getDirectSuperTypes(element2); + element2Types.add(0, element2); + + for (TypeElement superType1 : element1Types) { + for (TypeElement superType2 : element2Types) { + if (typeEquals(superType1.asType(), superType2.asType())) { + return superType2.asType(); + } + } + } + return context.getType(Object.class); + } + public static String getReadableSignature(ExecutableElement method) { // TODO toString does not guarantee a good signature return method.toString(); @@ -146,31 +190,43 @@ case LONG: return "long"; case DECLARED: - return getGenericName(fromTypeMirror(mirror)); + return getDeclaredName((DeclaredType) mirror); case ARRAY: return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]"; case VOID: return "void"; + case WILDCARD: + return getWildcardName((WildcardType) mirror); case TYPEVAR: - return ((TypeParameterElement) ((TypeVariable) mirror).asElement()).getSimpleName().toString(); + return "?"; default: throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror); } } - private static String getGenericName(TypeElement element) { - String simpleName = element.getSimpleName().toString(); + private static String getWildcardName(WildcardType type) { + StringBuilder b = new StringBuilder(); + if (type.getExtendsBound() != null) { + b.append("? extends ").append(getSimpleName(type.getExtendsBound())); + } else if (type.getSuperBound() != null) { + b.append("? super ").append(getSimpleName(type.getExtendsBound())); + } + return b.toString(); + } - if (element.getTypeParameters().size() == 0) { + private static String getDeclaredName(DeclaredType element) { + String simpleName = element.asElement().getSimpleName().toString(); + + if (element.getTypeArguments().size() == 0) { return simpleName; } StringBuilder b = new StringBuilder(simpleName); b.append("<"); - if (element.getTypeParameters().size() > 0) { - for (int i = 0; i < element.getTypeParameters().size(); i++) { - b.append("?"); - if (i < element.getTypeParameters().size() - 1) { + if (element.getTypeArguments().size() > 0) { + for (int i = 0; i < element.getTypeArguments().size(); i++) { + b.append(getSimpleName(element.getTypeArguments().get(i))); + if (i < element.getTypeArguments().size() - 1) { b.append(", "); } } @@ -282,6 +338,19 @@ return null; } + public static List<TypeElement> getDirectSuperTypes(TypeElement element) { + List<TypeElement> types = new ArrayList<>(); + if (element.getSuperclass() != null) { + TypeElement superElement = fromTypeMirror(element.getSuperclass()); + if (superElement != null) { + types.add(superElement); + types.addAll(getDirectSuperTypes(superElement)); + } + } + + return types; + } + public static List<TypeElement> getSuperTypes(TypeElement element) { List<TypeElement> types = new ArrayList<>(); List<TypeElement> superTypes = null; @@ -468,8 +537,10 @@ for (int i = 0; i < params.length; i++) { TypeMirror param1 = params[i]; TypeMirror param2 = method.getParameters().get(i).asType(); - if (!getQualifiedName(param1).equals(getQualifiedName(param2))) { - continue method; + if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) { + if (!getQualifiedName(param1).equals(getQualifiedName(param2))) { + continue method; + } } } return method;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java Mon Mar 04 10:00:49 2013 +0100 @@ -103,6 +103,18 @@ return annotations; } + /* Support JDK8 langtools. */ + @SuppressWarnings("unused") + public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) { + throw new UnsupportedOperationException(); + } + + /* Support for some JDK8 builds. (remove after jdk8 is released) */ + @SuppressWarnings("unused") + public <A extends Annotation> A[] getAnnotations(Class<A> annotationType) { + throw new UnsupportedOperationException(); + } + @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) { throw new UnsupportedOperationException();
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Mon Mar 04 10:00:49 2013 +0100 @@ -59,6 +59,7 @@ } } + /* Support JDK8 langtools. */ public boolean isDefault() { return false; } @@ -113,7 +114,7 @@ } public CodeTreeBuilder createBuilder() { - CodeTreeBuilder builder = new CodeTreeBuilder(); + CodeTreeBuilder builder = new CodeTreeBuilder(null); this.bodyTree = builder.getTree(); this.bodyTree.setEnclosingElement(this); this.body = null;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Mon Mar 04 10:00:49 2013 +0100 @@ -33,17 +33,25 @@ public class CodeTreeBuilder { + private final CodeTreeBuilder parent; + private BuilderCodeTree currentElement; private final BuilderCodeTree root; - public CodeTreeBuilder() { + private int treeCount; + + public CodeTreeBuilder(CodeTreeBuilder parent) { this.root = new BuilderCodeTree(GROUP, null, null); this.currentElement = root; + this.parent = parent; } - public CodeTreeBuilder(CodeTree tree) { - this.root = (BuilderCodeTree) tree; - this.currentElement = root; + public int getTreeCount() { + return treeCount; + } + + public boolean isEmpty() { + return treeCount == 0; } public CodeTreeBuilder statement(String statement) { @@ -55,11 +63,11 @@ } public static CodeTreeBuilder createBuilder() { - return new CodeTreeBuilder(); + return new CodeTreeBuilder(null); } public static CodeTree singleString(String s) { - return new CodeTreeBuilder().string(s).getTree(); + return new CodeTreeBuilder(null).string(s).getTree(); } private CodeTreeBuilder push(CodeTreeKind kind) { @@ -89,11 +97,14 @@ currentElement = tree; break; } + treeCount++; return this; } private void clearLast(CodeTreeKind kind) { - clearLastRec(kind, currentElement.getEnclosedElements()); + if (clearLastRec(kind, currentElement.getEnclosedElements())) { + treeCount--; + } } public CodeTreeBuilder startStatement() { @@ -193,6 +204,24 @@ return this; } + private CodeTreeBuilder startCurlyBracesCommaGroup() { + startGroup(); + string("{").startCommaGroup(); + registerCallBack(new EndCallback() { + + @Override + public void beforeEnd() { + } + + @Override + public void afterEnd() { + string("}"); + } + }); + endAfter(); + return this; + } + public CodeTreeBuilder startParantheses() { startGroup(); string("(").startGroup(); @@ -211,6 +240,10 @@ return this; } + public CodeTreeBuilder doubleQuote(String s) { + return startGroup().string("\"").string(s).string("\"").end(); + } + public CodeTreeBuilder startDoubleQuote() { startGroup().string("\""); registerCallBack(new EndCallback() { @@ -271,6 +304,15 @@ return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); } + public boolean startIf(boolean elseIf) { + if (elseIf) { + startElseIf(); + } else { + startIf(); + } + return true; + } + public CodeTreeBuilder startElseIf() { clearLast(CodeTreeKind.NEW_LINE); return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter(); @@ -346,6 +388,19 @@ return startStatement().string("assert "); } + public CodeTreeBuilder startNewArray(ArrayType arrayType, CodeTree size) { + startGroup().string("new ").type(arrayType.getComponentType()).string("["); + if (size != null) { + tree(size); + } + string("]"); + if (size == null) { + string(" "); + startCurlyBracesCommaGroup().endAfter(); + } + return this; + } + public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) { return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter(); } @@ -358,6 +413,13 @@ return push(CodeTreeKind.INDENT); } + public CodeTreeBuilder end(int times) { + for (int i = 0; i < times; i++) { + end(); + } + return this; + } + public CodeTreeBuilder end() { BuilderCodeTree tree = currentElement; EndCallback callback = tree.getAtEndListener(); @@ -372,9 +434,9 @@ } private void toParent() { - Element parent = currentElement.getEnclosingElement(); + Element parentElement = currentElement.getEnclosingElement(); if (currentElement != root) { - this.currentElement = (BuilderCodeTree) parent; + this.currentElement = (BuilderCodeTree) parentElement; } else { this.currentElement = root; } @@ -433,7 +495,7 @@ } public CodeTreeBuilder create() { - return new CodeTreeBuilder(); + return new CodeTreeBuilder(null); } public CodeTreeBuilder type(TypeMirror type) { @@ -496,7 +558,11 @@ while (element != null && (element.getKind() != ElementKind.METHOD)) { element = element.getEnclosingElement(); } - return element != null ? (ExecutableElement) element : null; + ExecutableElement found = element != null ? (ExecutableElement) element : null; + if (found == null && parent != null) { + found = parent.findMethod(); + } + return found; } public CodeTreeBuilder returnTrue() {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java Mon Mar 04 10:00:49 2013 +0100 @@ -58,7 +58,7 @@ } public CodeTreeBuilder createInitBuilder() { - CodeTreeBuilder builder = new CodeTreeBuilder(); + CodeTreeBuilder builder = new CodeTreeBuilder(null); init = builder.getTree(); init.setEnclosingElement(this); return builder;
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java Mon Mar 04 10:00:49 2013 +0100 @@ -36,9 +36,16 @@ public abstract class AbstractCodeWriter extends CodeElementScanner<Void, Void> { + private static final int LINE_LENGTH = 200; + private static final int LINE_WRAP_INDENTS = 3; + private static final String IDENT_STRING = " "; + private static final String LN = "\n"; /* unix style */ + protected Writer writer; private int indent; private boolean newLine; + private int lineLength; + private boolean lineWrapping = false; private OrganizedImports imports; @@ -56,8 +63,7 @@ Writer w = null; try { imports = OrganizedImports.organize(e); - - w = createWriter(e); + w = new TrimTrailingSpaceWriter(createWriter(e)); writer = w; writeRootClass(e); } catch (IOException ex) { @@ -145,7 +151,7 @@ write(" {").writeLn(); writeEmptyLn(); - indent(); + indent(1); List<VariableElement> staticFields = getStaticFields(e); List<VariableElement> instanceFields = getInstanceFields(e); @@ -191,7 +197,7 @@ clazz.accept(this, null); } - dedent(); + dedent(1); write("}"); writeEmptyLn(); } @@ -262,6 +268,14 @@ } else { writeModifiers(f.getModifiers()); write(typeSimpleName(f.asType())); + + if (f.getEnclosingElement().getKind() == ElementKind.METHOD) { + ExecutableElement method = (ExecutableElement) f.getEnclosingElement(); + if (method.isVarArgs() && method.getParameters().indexOf(f) == method.getParameters().size() - 1) { + write("..."); + } + } + write(" "); write(f.getSimpleName()); if (init != null) { @@ -474,9 +488,9 @@ writeLn(";"); } else if (e.getBodyTree() != null) { writeLn(" {"); - indent(); + indent(1); e.getBodyTree().acceptCodeElementScanner(this, p); - dedent(); + dedent(1); writeLn("}"); } else if (e.getBody() != null) { write(" {"); @@ -509,11 +523,11 @@ } break; case INDENT: - indent(); + indent(1); for (CodeTree tree : e.getEnclosedElements()) { tree.acceptCodeElementScanner(this, p); } - dedent(); + dedent(1); break; case NEW_LINE: writeLn(); @@ -565,25 +579,28 @@ } } - private static final String LN = "\n"; - - protected void indent() { - indent++; + protected void indent(int count) { + indent += count; } - protected void dedent() { - indent--; + protected void dedent(int count) { + indent -= count; } protected void writeLn() { - write(LN); - newLine = true; + writeLn(""); } protected void writeLn(String text) { write(text); write(LN); + lineLength = 0; newLine = true; + if (lineWrapping) { + dedent(LINE_WRAP_INDENTS); + lineWrapping = false; + } + lineWrapping = false; } protected void writeEmptyLn() { @@ -596,10 +613,23 @@ private AbstractCodeWriter write(String m) { try { + lineLength += m.length(); if (newLine && m != LN) { writeIndent(); newLine = false; } + if (lineLength > LINE_LENGTH && m.length() > 0) { + char firstChar = m.charAt(0); + if (Character.isAlphabetic(firstChar)) { + if (!lineWrapping) { + indent(LINE_WRAP_INDENTS); + } + lineWrapping = true; + lineLength = 0; + write(LN); + writeIndent(); + } + } writer.write(m); } catch (IOException e) { throw new RuntimeException(e); @@ -609,7 +639,57 @@ private void writeIndent() throws IOException { for (int i = 0; i < indent; i++) { - writer.write(" "); + lineLength += IDENT_STRING.length(); + writer.write(IDENT_STRING); } } + + private static class TrimTrailingSpaceWriter extends Writer { + + private final Writer delegate; + private final StringBuilder buffer = new StringBuilder(); + + public TrimTrailingSpaceWriter(Writer delegate) { + this.delegate = delegate; + } + + @Override + public void close() throws IOException { + this.delegate.close(); + } + + @Override + public void flush() throws IOException { + this.delegate.flush(); + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + buffer.append(cbuf, off, len); + int newLinePoint = buffer.indexOf(LN); + + if (newLinePoint != -1) { + String lhs = trimTrailing(buffer.substring(0, newLinePoint)); + delegate.write(lhs); + delegate.write(LN); + buffer.delete(0, newLinePoint + 1); + } + } + + private static String trimTrailing(String s) { + int cut = 0; + for (int i = s.length() - 1; i >= 0; i--) { + if (Character.isWhitespace(s.charAt(i))) { + cut++; + } else { + break; + } + } + if (cut > 0) { + return s.substring(0, s.length() - cut); + } + return s; + } + } + }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java Mon Mar 04 10:00:49 2013 +0100 @@ -63,19 +63,71 @@ } public String useImport(TypeMirror type) { - String simpleName = getSimpleName(type); - TypeMirror usedByType = simpleNamesUsed.get(type); + switch (type.getKind()) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case SHORT: + case INT: + case LONG: + case VOID: + return Utils.getSimpleName(type); + case DECLARED: + return createDeclaredTypeName((DeclaredType) type); + case ARRAY: + return useImport(((ArrayType) type).getComponentType()) + "[]"; + case WILDCARD: + return createWildcardName((WildcardType) type); + case TYPEVAR: + return "?"; + default: + throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type); + } + } + + private String createWildcardName(WildcardType type) { + StringBuilder b = new StringBuilder(); + if (type.getExtendsBound() != null) { + b.append("? extends ").append(useImport(type.getExtendsBound())); + } else if (type.getSuperBound() != null) { + b.append("? super ").append(useImport(type.getExtendsBound())); + } + return b.toString(); + } + + private String createDeclaredTypeName(DeclaredType type) { + String name = type.asElement().getSimpleName().toString(); + + TypeMirror usedByType = simpleNamesUsed.get(name); if (usedByType == null) { - simpleNamesUsed.put(simpleName, type); + simpleNamesUsed.put(name, type); usedByType = type; - } else if (!typeEquals(type, usedByType)) { - // we need a qualified name - return getQualifiedName(type); } - // we can use the simple name - addUsage(type, importUsage); - return simpleName; + if (typeEquals(type, usedByType)) { + addUsage(type, importUsage); + } else { + name = getQualifiedName(type); + } + + if (type.getTypeArguments().size() == 0) { + return name; + } + + StringBuilder b = new StringBuilder(name); + b.append("<"); + if (type.getTypeArguments().size() > 0) { + for (int i = 0; i < type.getTypeArguments().size(); i++) { + b.append(useImport(type.getTypeArguments().get(i))); + if (i < type.getTypeArguments().size() - 1) { + b.append(", "); + } + } + } + b.append(">"); + return b.toString(); } public String useStaticFieldImport(TypeMirror type, String fieldName) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/ExecutableTypeMethodParser.java Mon Mar 04 10:00:49 2013 +0100 @@ -47,7 +47,7 @@ types.addAll(Arrays.asList(getNode().getTypeSystem().getPrimitiveTypeMirrors())); types.add(getContext().getType(void.class)); - ParameterSpec returnTypeSpec = new ParameterSpec("executedValue", types.toArray(new TypeMirror[types.size()]), getNode().getTypeSystem().getGenericType(), false, Cardinality.ONE); + ParameterSpec returnTypeSpec = new ParameterSpec("executedValue", types.toArray(new TypeMirror[types.size()]), false, Cardinality.ONE); List<ParameterSpec> parameters = new ArrayList<>(); parameters.add(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame(), true));
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Mon Mar 04 10:00:49 2013 +0100 @@ -23,12 +23,15 @@ package com.oracle.truffle.codegen.processor.node; import java.lang.annotation.*; +import java.util.*; import javax.lang.model.element.*; +import javax.lang.model.type.*; import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.template.*; +import com.oracle.truffle.codegen.processor.template.ParameterSpec.*; public class GenericParser extends MethodParser<SpecializationData> { @@ -42,13 +45,19 @@ } @Override - protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) { - return new ParameterSpec(valueName, nodeData.findGenericExecutableType(getContext()).getType().getPrimitiveType(), false); + protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, boolean optional) { + List<ExecutableTypeData> execTypes = nodeData.findGenericExecutableTypes(getContext()); + List<TypeMirror> types = new ArrayList<>(); + for (ExecutableTypeData type : execTypes) { + types.add(type.getType().getPrimitiveType()); + } + TypeMirror[] array = types.toArray(new TypeMirror[types.size()]); + return new ParameterSpec(valueName, array, false, Cardinality.ONE); } @Override protected ParameterSpec createReturnParameterSpec() { - return super.createValueParameterSpec("returnValue", getNode()); + return super.createValueParameterSpec("returnValue", getNode(), false); } @Override
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/MethodParser.java Mon Mar 04 10:00:49 2013 +0100 @@ -41,12 +41,12 @@ return template; } - protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData) { - return new ParameterSpec(valueName, nodeData, false, Cardinality.ONE); + protected ParameterSpec createValueParameterSpec(String valueName, NodeData nodeData, boolean optional) { + return new ParameterSpec(valueName, nodeData, optional, Cardinality.ONE); } protected ParameterSpec createReturnParameterSpec() { - return createValueParameterSpec("operation", getNode()); + return createValueParameterSpec("operation", getNode(), false); } @Override @@ -65,7 +65,7 @@ } if (field.getExecutionKind() == ExecutionKind.DEFAULT) { - defaultParameters.add(createValueParameterSpec(field.getName(), field.getNodeData())); + defaultParameters.add(createValueParameterSpec(field.getName(), field.getNodeData(), false)); } else if (field.getExecutionKind() == ExecutionKind.SHORT_CIRCUIT) { String valueName = field.getName(); if (shortCircuitName != null && valueName.equals(shortCircuitName)) { @@ -73,8 +73,7 @@ } defaultParameters.add(new ParameterSpec(shortCircuitValueName(valueName), getContext().getType(boolean.class), false)); - - defaultParameters.add(createValueParameterSpec(valueName, field.getNodeData())); + defaultParameters.add(createValueParameterSpec(valueName, field.getNodeData(), false)); } else { assert false; }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Mon Mar 04 10:00:49 2013 +0100 @@ -31,6 +31,7 @@ import javax.lang.model.type.*; import javax.lang.model.util.*; +import com.oracle.truffle.api.codegen.*; import com.oracle.truffle.codegen.processor.*; import com.oracle.truffle.codegen.processor.ast.*; import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind; @@ -69,7 +70,8 @@ private static String specializationId(SpecializationData specialization) { String name = ""; - if (specialization.getNode().getSpecializations().length > 1) { + NodeData node = specialization.getNode(); + if (node.getSpecializations().length > 1) { name = specialization.getMethodName(); if (name.startsWith("do")) { name = name.substring(2); @@ -82,8 +84,8 @@ return field.getName() + "Value"; } - private static String valueName(TemplateMethod method, ActualParameter param) { - NodeData node = (NodeData) method.getTemplate(); + private static String valueName(ActualParameter param) { + NodeData node = (NodeData) param.getMethod().getTemplate(); NodeFieldData field = node.findField(param.getSpecification().getName()); if (field != null) { return valueName(field); @@ -92,6 +94,14 @@ } } + private static String castValueName(ActualParameter parameter) { + return valueName(parameter) + "Cast"; + } + + private static String castValueName(NodeFieldData field) { + return valueName(field) + "Cast"; + } + private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame) { if (forceFrame) { method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frame")); @@ -101,7 +111,7 @@ if (forceFrame && spec.getName().equals("frame")) { continue; } - method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(specialization, parameter))); + method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(parameter))); } } @@ -118,21 +128,28 @@ if (unexpectedValueName != null && spec.getName().equals(unexpectedValueName)) { builder.string("ex.getResult()"); } else { - builder.string(valueName(specialization, parameter)); + builder.string(valueName(parameter)); } } } - private static void addValueParameterNamesWithCasts(ProcessorContext context, CodeTreeBuilder body, SpecializationData specialization) { - for (ActualParameter param : specialization.getParameters()) { - TypeData typeData = param.getActualTypeData(specialization.getNode().getTypeSystem()); - if (typeData == null || typeData.isGeneric()) { - body.string(valueName(specialization, param)); + private static void addValueParameterNamesWithCasts(CodeTreeBuilder body, SpecializationData valueSpecialization, SpecializationData targetSpecialization) { + NodeData node = targetSpecialization.getNode(); + TypeSystemData typeSystem = node.getTypeSystem(); + + for (ActualParameter targetParameter : targetSpecialization.getParameters()) { + ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getSpecification().getName()); + TypeData targetType = targetParameter.getActualTypeData(typeSystem); + + TypeData valueType = null; + if (valueParameter != null) { + valueType = valueParameter.getActualTypeData(typeSystem); + } + + if (targetType == null || targetType.isGeneric() || (valueType != null && valueType.equalsType(targetType))) { + body.string(valueName(targetParameter)); } else { - String methodName = TypeSystemCodeGenerator.asTypeMethodName(typeData); - startCallTypeSystemMethod(context, body, specialization.getNode(), methodName); - body.string(valueName(specialization, param)); - body.end().end(); + body.string(castValueName(targetParameter)); } } } @@ -173,6 +190,14 @@ return prefix; } + private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, String value) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + startCallTypeSystemMethod(context, builder, node, methodName); + builder.string(value); + builder.end().end(); + return builder.getRoot(); + } + private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, NodeData node, String methodName) { VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, node.getTypeSystem()); assert singleton != null; @@ -182,42 +207,205 @@ body.string(".").startCall(methodName); } - private static void emitGuards(ProcessorContext context, CodeTreeBuilder body, String prefix, SpecializationData specialization, boolean onSpecialization, boolean needsCast) { - TypeSystemData typeSystem = specialization.getNode().getTypeSystem(); - // Implict guards based on method signature - String andOperator = prefix; - for (NodeFieldData field : specialization.getNode().getFields()) { - ActualParameter param = specialization.findParameter(field.getName()); - TypeData type = param.getActualTypeData(typeSystem); - if (type == null || type.isGeneric()) { - continue; - } + private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean onSpecialization, + CodeTree guardedStatements, CodeTree elseStatements) { + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, valueSpecialization, guardedSpecialization); + CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, valueSpecialization, guardedSpecialization, onSpecialization); + + int ifCount = 0; - body.string(andOperator); - startCallTypeSystemMethod(context, body, specialization.getNode(), TypeSystemCodeGenerator.isTypeMethodName(type)); - body.string(valueName(specialization, param)); - body.end().end(); // call - andOperator = " && "; + if (implicitGuards != null) { + builder.startIf(); + builder.tree(implicitGuards); + builder.end(); + builder.startBlock(); + ifCount++; + } + + if (explicitGuards != null || !onSpecialization) { + builder.tree(createCasts(parent, valueSpecialization, guardedSpecialization)); + } + + if (explicitGuards != null) { + builder.startIf(); + builder.tree(explicitGuards); + builder.end(); + builder.startBlock(); + ifCount++; } - if (specialization.getGuards().length > 0) { - // Explicitly specified guards - for (SpecializationGuardData guard : specialization.getGuards()) { - if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) { - body.string(andOperator); + if (implicitGuards == null && explicitGuards == null && conditionPrefix != null && !conditionPrefix.isEmpty()) { + builder.startIf().string(conditionPrefix).end().startBlock(); + ifCount++; + } + + builder.tree(guardedStatements); + + builder.end(ifCount); + if (ifCount > 0 && elseStatements != null) { + builder.startElseBlock(); + builder.tree(elseStatements); + builder.end(); + } - startCallOperationMethod(body, guard.getGuardDeclaration()); + return builder.getRoot(); + } - if (needsCast) { - addValueParameterNamesWithCasts(context, body, specialization); - } else { - addValueParameterNames(body, specialization, null, false); - } - body.end().end(); // call + private static CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, + boolean onSpecialization) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; + if (guardedSpecialization.getGuards().length > 0) { + // Explicitly specified guards + for (SpecializationGuardData guard : guardedSpecialization.getGuards()) { + if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) { + builder.string(andOperator); + + startCallOperationMethod(builder, guard.getGuardDeclaration()); + addValueParameterNamesWithCasts(builder, valueSpecialization, guardedSpecialization); + + builder.end().end(); // call andOperator = " && "; } } } + + return builder.isEmpty() ? null : builder.getRoot(); + } + + private CodeTree createCasts(CodeTreeBuilder parent, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { + NodeData node = guardedSpecialization.getNode(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + // Implict guards based on method signature + for (NodeFieldData field : node.getFields()) { + ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName()); + ActualParameter valueParam = valueSpecialization.findParameter(field.getName()); + + CodeTree cast = createCast(parent, field, valueParam, guardedParam); + if (cast == null) { + continue; + } + builder.tree(cast); + } + + return builder.getRoot(); + } + + private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { + NodeData node = guardedSpecialization.getNode(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + // Implict guards based on method signature + String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; + for (NodeFieldData field : node.getFields()) { + ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName()); + ActualParameter valueParam = valueSpecialization.findParameter(field.getName()); + + CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam); + if (implicitGuard == null) { + continue; + } + + builder.string(andOperator); + builder.tree(implicitGuard); + andOperator = " && "; + } + + return builder.isEmpty() ? null : builder.getRoot(); + } + + private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { + NodeData node = field.getNodeData(); + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + TypeData targetType = target.getActualTypeData(node.getTypeSystem()); + TypeData sourceType = source.getActualTypeData(node.getTypeSystem()); + + if (targetType.equalsType(sourceType) || targetType.isGeneric()) { + return null; + } + + builder.startGroup(); + + if (field.isShortCircuit()) { + ActualParameter shortCircuit = target.getPreviousParameter(); + assert shortCircuit != null; + builder.string("("); + builder.string("!").string(valueName(shortCircuit)); + builder.string(" || "); + } + + startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getActualTypeData(node.getTypeSystem()))); + builder.string(valueName(field)); + builder.end().end(); // call + + if (field.isShortCircuit()) { + builder.string(")"); + } + + builder.end(); // group + + return builder.getRoot(); + } + + private CodeTree createCast(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { + NodeData node = field.getNodeData(); + TypeSystemData typeSystem = node.getTypeSystem(); + + TypeData sourceType = source.getActualTypeData(typeSystem); + TypeData targetType = target.getActualTypeData(typeSystem); + + if (targetType.equalsType(sourceType) || targetType.isGeneric()) { + return null; + } + + CodeTree condition = null; + if (field.isShortCircuit()) { + ActualParameter shortCircuit = target.getPreviousParameter(); + assert shortCircuit != null; + condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); + } + + CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), valueName(target)); + + return createLazyAssignment(parent, castValueName(field), target.getActualType(), condition, value); + } + + /** + * <pre> + * variant1 $condition != null + * + * $type $name = defaultValue($type); + * if ($condition) { + * $name = $value; + * } + * + * variant2 $condition != null + * $type $name = $value; + * </pre> + * + * . + */ + private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + if (condition == null) { + builder.declaration(type, name, value); + } else { + builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).getRoot()); + + builder.startIf().tree(condition).end(); + builder.startBlock(); + builder.startStatement(); + builder.string(name); + builder.string(" = "); + builder.tree(value); + builder.end(); // statement + builder.end(); // block + } + return builder.getRoot(); } @Override @@ -235,11 +423,7 @@ add(factory, node); } - if (node.getSpecializations() == null) { - return; - } - - if (node.needsFactory() || childTypes.size() > 0) { + if (node.needsFactory() || node.getNodeChildren().size() > 0) { add(new NodeFactoryFactory(context, childTypes), node); } } @@ -324,6 +508,15 @@ for (SpecializationData specialization : node.getSpecializations()) { add(new SpecializedNodeFactory(context), specialization); } + + TypeMirror nodeFactory = getContext().getEnvironment().getTypeUtils().getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType()); + clazz.getImplements().add(nodeFactory); + clazz.add(createCreateNodeMethod(node)); + clazz.add(createCreateNodeSpecializedMethod(node)); + clazz.add(createGetNodeClassMethod(node)); + clazz.add(createGetNodeSignaturesMethod(node)); + clazz.add(createGetInstanceMethod(node, createVisibility)); + clazz.add(createInstanceConstant(node, clazz.asType())); } for (NodeData childNode : childTypes.keySet()) { @@ -344,9 +537,236 @@ clazz.add(type); } } + + List<NodeData> children = node.getNodeChildren(); + if (node.getParent() == null && children.size() > 0) { + clazz.add(createGetFactories(node)); + } + + } + + private CodeExecutableElement createGetNodeClassMethod(NodeData node) { + Types types = getContext().getEnvironment().getTypeUtils(); + TypeMirror returnType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType()); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass"); + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn().typeLiteral(node.getNodeType()).end(); + return method; + } + + private CodeExecutableElement createGetNodeSignaturesMethod(NodeData node) { + Types types = getContext().getEnvironment().getTypeUtils(); + TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); + TypeMirror classType = getContext().getType(Class.class); + TypeMirror returnType = types.getDeclaredType(listType, types.getDeclaredType(listType, classType)); + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeSignatures"); + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn(); + builder.startStaticCall(getContext().getType(Arrays.class), "asList"); + List<ExecutableElement> constructors = findUserConstructors(node); + for (ExecutableElement constructor : constructors) { + builder.startGroup(); + builder.type(getContext().getType(Arrays.class)); + builder.string(".<").type(getContext().getType(Class.class)).string(">"); + builder.startCall("asList"); + for (VariableElement param : constructor.getParameters()) { + builder.typeLiteral(param.asType()); + } + builder.end(); + builder.end(); + } + builder.end(); + builder.end(); + return method; + } + + private CodeExecutableElement createCreateNodeMethod(NodeData node) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode"); + CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments"); + method.setVarArgs(true); + method.addParameter(arguments); + + CodeTreeBuilder builder = method.createBuilder(); + List<ExecutableElement> signatures = findUserConstructors(node); + boolean ifStarted = false; + + for (ExecutableElement element : signatures) { + ifStarted = builder.startIf(ifStarted); + builder.string("arguments.length == " + element.getParameters().size()); + + int index = 0; + for (VariableElement param : element.getParameters()) { + builder.string(" && "); + if (!param.asType().getKind().isPrimitive()) { + builder.string("(arguments[" + index + "] == null || "); + } + builder.string("arguments[" + index + "] instanceof "); + builder.type(Utils.boxType(getContext(), param.asType())); + if (!param.asType().getKind().isPrimitive()) { + builder.string(")"); + } + index++; + } + builder.end(); + builder.startBlock(); + + builder.startReturn().startCall("create"); + index = 0; + for (VariableElement param : element.getParameters()) { + builder.startGroup(); + builder.string("(").type(param.asType()).string(") "); + builder.string("arguments[").string(String.valueOf(index)).string("]"); + builder.end(); + index++; + } + builder.end().end(); + + builder.end(); // block + } + + builder.startElseBlock(); + builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)); + builder.doubleQuote("Invalid create signature."); + builder.end().end(); + builder.end(); // else block + return method; + } + + private CodeExecutableElement createCreateNodeSpecializedMethod(NodeData node) { + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNodeSpecialized"); + CodeVariableElement nodeParam = new CodeVariableElement(node.getNodeType(), "thisNode"); + CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Class.class), "types"); + method.addParameter(nodeParam); + method.addParameter(arguments); + method.setVarArgs(true); + + CodeTreeBuilder builder = method.createBuilder(); + if (!node.needsRewrites(getContext())) { + builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end(); + } else { + builder.startIf(); + builder.string("types.length == 1"); + builder.end(); + builder.startBlock(); + + builder.startReturn().startCall("createSpecialized"); + builder.string("thisNode"); + builder.string("types[0]"); + builder.end().end(); + + builder.end(); + builder.startElseBlock(); + builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)); + builder.doubleQuote("Invalid createSpecialized signature."); + builder.end().end(); + builder.end(); + } + + return method; + } + + private ExecutableElement createGetInstanceMethod(NodeData node, Modifier visibility) { + Types types = getContext().getEnvironment().getTypeUtils(); + TypeElement nodeFactoryType = Utils.fromTypeMirror(getContext().getType(NodeFactory.class)); + TypeMirror returnType = types.getDeclaredType(nodeFactoryType, node.getNodeType()); + + CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance"); + if (visibility != null) { + method.getModifiers().add(visibility); + } + method.getModifiers().add(Modifier.STATIC); + + String varName = instanceVarName(node); + + CodeTreeBuilder builder = method.createBuilder(); + builder.startIf(); + builder.string(varName).string(" == null"); + builder.end().startBlock(); + + builder.startStatement(); + builder.string(varName); + builder.string(" = "); + builder.startNew(factoryClassName(node)).end(); + builder.end(); + + builder.end(); + builder.startReturn().string(varName).end(); + return method; + } + + private String instanceVarName(NodeData node) { + if (node.getParent() != null) { + return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance"; + } else { + return "instance"; + } + } + + private CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) { + String varName = instanceVarName(node); + CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName); + var.getModifiers().add(Modifier.PRIVATE); + var.getModifiers().add(Modifier.STATIC); + return var; + } + + private ExecutableElement createGetFactories(NodeData node) { + List<NodeData> children = node.getNodeChildren(); + if (node.needsFactory()) { + children.add(node); + } + + List<TypeMirror> nodeTypesList = new ArrayList<>(); + for (NodeData child : children) { + nodeTypesList.add(child.getTemplateType().asType()); + } + TypeMirror commonNodeSuperType = Utils.getCommonSuperType(getContext(), nodeTypesList.toArray(new TypeMirror[nodeTypesList.size()])); + + Types types = getContext().getEnvironment().getTypeUtils(); + TypeMirror factoryType = getContext().getType(NodeFactory.class); + TypeMirror baseType; + if (children.size() == 1) { + baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), commonNodeSuperType); + } else { + baseType = types.getDeclaredType(Utils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null)); + } + TypeMirror listType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), baseType); + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories"); + + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn(); + builder.startStaticCall(getContext().getType(Arrays.class), "asList"); + + for (NodeData child : children) { + builder.startGroup(); + NodeData childNode = child; + List<NodeData> factories = new ArrayList<>(); + while (childNode.getParent() != null) { + factories.add(childNode); + childNode = childNode.getParent(); + } + Collections.reverse(factories); + for (NodeData nodeData : factories) { + builder.string(factoryClassName(nodeData)).string("."); + } + builder.string("getInstance()"); + builder.end(); + } + builder.end(); + builder.end(); + return method; } private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) { + List<ExecutableElement> constructors = findUserConstructors(node); + for (ExecutableElement constructor : constructors) { + clazz.add(createCreateMethod(node, createVisibility, constructor)); + } + } + + private List<ExecutableElement> findUserConstructors(NodeData node) { + List<ExecutableElement> constructors = new ArrayList<>(); for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(node.getNodeType()).getEnclosedElements())) { if (constructor.getModifiers().contains(PRIVATE)) { continue; @@ -356,9 +776,9 @@ if (constructor.getParameters().size() == 1 && typeEquals(constructor.getParameters().get(0).asType(), node.getNodeType())) { continue; } - - clazz.add(createCreateMethod(node, createVisibility, constructor)); + constructors.add(constructor); } + return constructors; } private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) { @@ -434,17 +854,12 @@ SpecializationData specialization = node.getSpecializations()[i]; body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeClassName(specialization)).string(".class)").end(); - if (specialization.isGeneric()) { - body.startIf().string("allowed").end().startBlock(); - } else { - body.startIf().string("allowed"); - emitGuards(getContext(), body, " && ", specialization, true, true); - body.end().startBlock(); - } - body.startReturn().startNew(nodeClassName(specialization)); - body.string(THIS_NODE_LOCAL_VAR_NAME); - body.end().end(); - body.end(); // block + CodeTreeBuilder guarded = new CodeTreeBuilder(body); + guarded.startReturn().startNew(nodeClassName(specialization)); + guarded.string(THIS_NODE_LOCAL_VAR_NAME); + guarded.end().end(); + + body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null)); } body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end(); @@ -488,24 +903,23 @@ } private void emitGeneratedGenericSpecialization(CodeTreeBuilder builder, SpecializationData current, SpecializationData next) { + CodeTreeBuilder invokeMethodBuilder = new CodeTreeBuilder(builder); + emitInvokeDoMethod(invokeMethodBuilder, current, 0); + CodeTree invokeMethod = invokeMethodBuilder.getRoot(); + if (next != null) { - builder.startIf(); - emitGuards(context, builder, "", current, false, true); - builder.end().startBlock(); + invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, false, invokeMethod, null); } - emitInvokeDoMethod(builder, current, 0); + builder.tree(invokeMethod); if (next != null) { builder.end(); - builder.startElseBlock(); builder.startReturn().startCall(generatedGenericMethodName(next)); builder.string(THIS_NODE_LOCAL_VAR_NAME); addValueParameterNames(builder, next, null, true); builder.end().end(); - - builder.end(); } } @@ -516,7 +930,7 @@ builder.startReturn(); startCallOperationMethod(builder, specialization); - addValueParameterNamesWithCasts(context, builder, specialization); + addValueParameterNamesWithCasts(builder, specialization.getNode().getGenericSpecialization(), specialization); builder.end().end(); // start call operation builder.end(); // return @@ -623,14 +1037,14 @@ builder.string("// ignore").newLine(); } else { builder.startReturn(); - builder.tree(castPrimaryExecute(node, castedType, CodeTreeBuilder.singleString("ex.getResult()"))); + builder.tree(createExpectType(node, castedType, CodeTreeBuilder.singleString("ex.getResult()"))); builder.end(); } builder.end(); if (!returnVoid) { builder.startReturn(); - builder.tree(castPrimaryExecute(node, castedType, CodeTreeBuilder.singleString("value"))); + builder.tree(createExpectType(node, castedType, CodeTreeBuilder.singleString("value"))); builder.end(); } } else { @@ -638,81 +1052,92 @@ builder.statement(primaryExecuteCall); } else { builder.startReturn(); - builder.tree(castPrimaryExecute(node, castedType, primaryExecuteCall)); + builder.tree(createExpectType(node, castedType, primaryExecuteCall)); builder.end(); } } } - private CodeTree castPrimaryExecute(NodeData node, ExecutableTypeData castedType, CodeTree value) { - if (castedType.getType().isVoid()) { + private CodeTree createExpectType(NodeData node, ExecutableTypeData castedType, CodeTree value) { + if (castedType == null) { return value; - } - if (castedType.getType().isGeneric()) { + } else if (castedType.getType().isVoid()) { + return value; + } else if (castedType.getType().isGeneric()) { return value; } CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); + String targetMethodName; if (castedType.hasUnexpectedValue(getContext())) { - startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.expectTypeMethodName(castedType.getType())); + targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(castedType.getType()); } else { - startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.asTypeMethodName(castedType.getType())); + targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(castedType.getType()); } + startCallTypeSystemMethod(getContext(), builder, node, targetMethodName); + builder.tree(value); builder.end().end(); return builder.getRoot(); } private void buildFunctionalExecuteMethod(CodeTreeBuilder builder, SpecializationData specialization) { - NodeData node = specialization.getNode(); - TypeSystemData typeSystem = node.getTypeSystem(); - - for (NodeFieldData field : node.getFields()) { - if (field.getExecutionKind() == ExecutionKind.IGNORE) { - continue; - } + if (specialization.isUninitialized()) { + builder.tree(createDeoptimize(builder)); + } - ActualParameter parameterType = specialization.findParameter(field.getName()); + builder.tree(createExecuteChildren(builder, specialization)); - if (parameterType.getActualTypeData(typeSystem).isGeneric()) { - buildGenericValueExecute(builder, specialization, field, null); - } else { - buildSpecializedValueExecute(builder, specialization, field); - } + if (specialization.isUninitialized()) { + builder.tree(createSpecializeCall(builder, specialization)); } - if (specialization.hasDynamicGuards()) { - builder.startIf(); - emitGuards(getContext(), builder, "", specialization, false, false); - builder.end().startBlock(); + CodeTree executeNode = createExecute(builder, specialization); + + SpecializationData next = specialization.findNextSpecialization(); + CodeTree returnSpecialized = null; + if (next != null) { + returnSpecialized = createReturnSpecializeAndExecute(builder, next, null); } + builder.tree(createGuardAndCast(builder, null, specialization, specialization, false, executeNode, returnSpecialized)); + } + + private CodeTree createDeoptimize(CodeTreeBuilder parent) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + builder.startStatement(); + builder.startStaticCall(getContext().getTruffleTypes().getTruffleIntrinsics(), "deoptimize").end(); + builder.end(); + return builder.getRoot(); + } + + private CodeTree createSpecializeCall(CodeTreeBuilder parent, SpecializationData specialization) { + NodeData node = specialization.getNode(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + emitSpecializationListeners(builder, node); + + builder.startStatement(); + builder.startCall("replace"); + if (node.needsRewrites(getContext())) { + builder.startCall(factoryClassName(node), "specialize"); + builder.string("this"); + builder.typeLiteral(builder.findMethod().getEnclosingElement().asType()); + addValueParameterNames(builder, specialization, null, false); + builder.end(); // call replace, call specialize + } else { + builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); + } + builder.end().end(); + return builder.getRoot(); + } + + private CodeTree createExecute(CodeTreeBuilder parent, SpecializationData specialization) { + NodeData node = specialization.getNode(); + CodeTreeBuilder builder = new CodeTreeBuilder(parent); if (specialization.getExceptions().length > 0) { builder.startTryBlock(); } - if (specialization.isUninitialized()) { - for (TemplateMethod listener : node.getSpecializationListeners()) { - builder.startStatement(); - startCallOperationMethod(builder, listener); - addValueParameterNames(builder, listener, null, false); - builder.end().end(); - builder.end(); // statement - } - - builder.startStatement(); - builder.startCall("replace"); - if (node.needsRewrites(getContext())) { - builder.startCall(factoryClassName(node), "specialize"); - builder.string("this"); - builder.typeLiteral(builder.getRoot().getEnclosingClass().asType()); - addValueParameterNames(builder, specialization, null, false); - builder.end(); // call replace, call specialize - } else { - builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); - } - builder.end().end(); - } - if ((specialization.isUninitialized() || specialization.isGeneric()) && node.needsRewrites(getContext())) { builder.startReturn().startCall(factoryClassName(node), generatedGenericMethodName(null)); builder.string("this"); @@ -734,20 +1159,44 @@ if (specialization.getExceptions().length > 0) { for (SpecializationThrowsData exception : specialization.getExceptions()) { builder.end().startCatchBlock(exception.getJavaClass(), "ex"); - buildThrowSpecialize(builder, specialization, exception.getTransitionTo(), null); + builder.tree(createReturnSpecializeAndExecute(parent, exception.getTransitionTo(), null)); } builder.end(); } - if (specialization.hasDynamicGuards()) { - builder.end().startElseBlock(); - buildThrowSpecialize(builder, specialization, specialization.findNextSpecialization(), null); - builder.end(); + return builder.getRoot(); + } + + private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + for (NodeFieldData field : specialization.getNode().getFields()) { + if (field.getExecutionKind() == ExecutionKind.IGNORE) { + continue; + } + + ActualParameter parameterType = specialization.findParameter(field.getName()); + + if (parameterType.getActualTypeData(specialization.getNode().getTypeSystem()).isGeneric()) { + buildGenericValueExecute(builder, specialization, field, null); + } else { + buildSpecializedValueExecute(builder, specialization, field); + } + } + return builder.getRoot(); + } + + private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { + for (TemplateMethod listener : node.getSpecializationListeners()) { + builder.startStatement(); + startCallOperationMethod(builder, listener); + addValueParameterNames(builder, listener, null, false); + builder.end().end(); + builder.end(); // statement } } private void buildGenericValueExecute(CodeTreeBuilder builder, SpecializationData specialization, NodeFieldData field, NodeFieldData exceptionSpec) { ActualParameter specParameter = specialization.findParameter(field.getName()); - + NodeData node = specialization.getNode(); boolean shortCircuit = startShortCircuit(builder, specialization, field, exceptionSpec); builder.startStatement(); @@ -756,9 +1205,9 @@ builder.string(" "); } - builder.string(valueName(specialization, specParameter)); + builder.string(valueName(specParameter)); builder.string(" = "); - ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext()); + ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext(), specParameter.getActualTypeData(node.getTypeSystem())); if (genericExecutableType == null) { throw new AssertionError("Must have generic executable type. Parser validation most likely failed. " + Arrays.toString(field.getNodeData().getExecutableTypes())); } @@ -792,7 +1241,7 @@ boolean shortCircuit = startShortCircuit(builder, specialization, field, null); if (!shortCircuit) { - builder.startStatement().type(param.getActualType()).string(" ").string(valueName(specialization, param)).end(); + builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end(); } ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem())); @@ -818,7 +1267,7 @@ execute = true; } } - buildThrowSpecialize(builder, specialization, specialization.findNextSpecialization(), param.getSpecification()); + builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param.getSpecification())); builder.end(); // catch block } @@ -844,7 +1293,7 @@ } } - builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(specialization, shortCircuitParam)).string(" = "); + builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex]; startCallOperationMethod(builder, shortCircuitData); @@ -853,7 +1302,7 @@ builder.end(); // statement - builder.declaration(parameter.getActualType(), valueName(specialization, parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); + builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); builder.startIf().string(shortCircuitParam.getSpecification().getName()).end(); builder.startBlock(); @@ -866,50 +1315,38 @@ } } - private void buildThrowSpecialize(CodeTreeBuilder builder, SpecializationData currentSpecialization, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) { - boolean canThrowUnexpected = Utils.canThrowType(builder.findMethod().getThrownTypes(), getContext().getTruffleTypes().getUnexpectedValueException()); - - CodeTreeBuilder specializeCall = CodeTreeBuilder.createBuilder(); - specializeCall.startCall("specialize"); + private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) { + CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); + specializeCall.startCall("specializeAndExecute"); specializeCall.string(nodeClassName(nextSpecialization) + ".class"); addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionSpec != null ? exceptionSpec.getName() : null, true); specializeCall.end().end(); - TypeData expectedType = currentSpecialization.getReturnType().getActualTypeData(currentSpecialization.getNode().getTypeSystem()); - if (canThrowUnexpected) { - builder.startReturn(); - startCallTypeSystemMethod(context, builder, currentSpecialization.getNode(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType)); - builder.tree(specializeCall.getRoot()); - builder.end().end(); - builder.end(); // return - } else { - builder.startReturn(); - if (!expectedType.isVoid() && !expectedType.isGeneric()) { - startCallTypeSystemMethod(context, builder, currentSpecialization.getNode(), TypeSystemCodeGenerator.asTypeMethodName(expectedType)); - builder.tree(specializeCall.getRoot()); - builder.end().end(); - } else { - builder.tree(specializeCall.getRoot()); - } - builder.end(); - } - + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + builder.startReturn(); + builder.tree(specializeCall.getRoot()); + builder.end(); + return builder.getRoot(); } private void buildSpecializeStateMethod(CodeTypeElement clazz, SpecializationData specialization) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), specialization.getNode().getTypeSystem().getGenericType(), "specialize"); + NodeData node = specialization.getNode(); + TypeData returnType = specialization.getReturnType().getActualTypeData(node.getTypeSystem()); + ExecutableTypeData returnExecutableType = node.findExecutableType(returnType); + boolean canThrowUnexpected = returnExecutableType == null ? true : returnExecutableType.hasUnexpectedValue(getContext()); + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), returnType.getPrimitiveType(), "specializeAndExecute"); method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); + if (canThrowUnexpected) { + method.addThrownType(getUnexpectedValueException()); + } addValueParameters(method, specialization.getNode().getGenericSpecialization(), true); clazz.add(method); CodeTreeBuilder builder = method.createBuilder(); - for (TemplateMethod listener : specialization.getNode().getSpecializationListeners()) { - builder.startStatement(); - startCallOperationMethod(builder, listener); - addValueParameterNames(builder, listener, null, false); - builder.end().end(); // call operation - builder.end(); // statement - } + + builder.tree(createDeoptimize(builder)); + emitSpecializationListeners(builder, specialization.getNode()); builder.startStatement(); builder.startCall("replace"); @@ -920,20 +1357,24 @@ builder.end(); // statement String generatedMethodName = generatedGenericMethodName(specialization.findNextSpecialization()); - ExecutableElement generatedGeneric = clazz.getEnclosingClass().getMethod(generatedMethodName); - CodeTreeBuilder genericBuilder = CodeTreeBuilder.createBuilder(); - genericBuilder.startCall(factoryClassName(specialization.getNode()), generatedMethodName); - genericBuilder.string("this"); - addValueParameterNames(genericBuilder, specialization.getNode().getGenericSpecialization(), null, true); - genericBuilder.end(); // call generated generic + CodeTreeBuilder genericExecute = CodeTreeBuilder.createBuilder(); + genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName); + genericExecute.string("this"); + addValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true); + genericExecute.end(); // call generated generic + + CodeTree genericInvocation = createExpectType(node, returnExecutableType, genericExecute.getRoot()); if (generatedGeneric != null && Utils.isVoid(generatedGeneric.getReturnType())) { - builder.declaration(generatedGeneric.getReturnType(), "genericResult", genericBuilder.getRoot()); - builder.startReturn().string("null").end(); + builder.statement(genericInvocation); + + if (!Utils.isVoid(builder.findMethod().asType())) { + builder.startReturn().defaultValue(returnType.getPrimitiveType()).end(); + } } else { - builder.startReturn().tree(genericBuilder.getRoot()).end(); + builder.startReturn().tree(genericInvocation).end(); } }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Mon Mar 04 10:00:49 2013 +0100 @@ -71,6 +71,17 @@ return !noSpecialization; } + public List<NodeData> getNodeChildren() { + List<NodeData> children = new ArrayList<>(); + for (NodeData child : getDeclaredChildren()) { + if (child.needsFactory()) { + children.add(child); + } + children.addAll(child.getNodeChildren()); + } + return children; + } + void setDeclaredChildren(List<NodeData> declaredChildren) { this.declaredChildren = declaredChildren; @@ -126,34 +137,17 @@ return executableTypes; } - public ExecutableTypeData findGenericExecutableType(ProcessorContext context) { + public ExecutableTypeData findGenericExecutableType(ProcessorContext context, TypeData type) { List<ExecutableTypeData> types = findGenericExecutableTypes(context); - if (types.isEmpty()) { - return null; - } else if (types.size() == 1) { - return types.get(0); - } else if (types.size() == 2) { - if (types.get(0).getType().isVoid()) { - return types.get(1); - } else if (types.get(1).getType().isVoid()) { - return types.get(0); + for (ExecutableTypeData availableType : types) { + if (Utils.typeEquals(availableType.getType().getBoxedType(), type.getBoxedType())) { + return availableType; } } - - ExecutableTypeData execType = null; - for (ExecutableTypeData type : types) { - TypeData returnType = type.getReturnType().getActualTypeData(getTypeSystem()); - if (returnType.isGeneric()) { - if (execType != null) { - return null; - } - execType = type; - } - } - return execType; + return null; } - private List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) { + public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) { List<ExecutableTypeData> types = new ArrayList<>(); for (ExecutableTypeData type : executableTypes) { if (!type.hasUnexpectedValue(context)) {
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Mon Mar 04 10:00:49 2013 +0100 @@ -52,6 +52,10 @@ this.executionKind = executionKind; } + public boolean isShortCircuit() { + return executionKind == ExecutionKind.SHORT_CIRCUIT; + } + public VariableElement getFieldElement() { return fieldElement; }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Mon Mar 04 10:00:49 2013 +0100 @@ -94,6 +94,7 @@ if (rootNode != null) { rootNode.setDeclaredChildren(children); } + return rootNode; } @@ -118,20 +119,24 @@ return null; // not a node } + if (type.getModifiers().contains(Modifier.PRIVATE)) { + return null; // not visible + } + List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(type)); List<TypeElement> typeHierarchy = findSuperClasses(new ArrayList<TypeElement>(), type); Collections.reverse(typeHierarchy); AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class); if (typeSystemMirror == null) { - log.error(originalType, "No @%s annotation found in type hierarchy.", TypeSystemReference.class.getSimpleName()); + log.error(type, "No @%s annotation found in type hierarchy.", TypeSystemReference.class.getSimpleName()); return null; } TypeMirror typeSytemType = Utils.getAnnotationValueType(typeSystemMirror, "value"); final TypeSystemData typeSystem = (TypeSystemData) context.getTemplate(typeSytemType, true); if (typeSystem == null) { - log.error(originalType, "The used type system '%s' is invalid.", Utils.getQualifiedName(typeSytemType)); + log.error(type, "The used type system '%s' is invalid.", Utils.getQualifiedName(typeSytemType)); return null; } @@ -146,8 +151,7 @@ nodeData.setExecutableTypes(executableTypes.toArray(new ExecutableTypeData[executableTypes.size()])); - parsedNodes.put(Utils.getQualifiedName(type), nodeData); // node fields will resolve node -// types, to avoid endless loops + parsedNodes.put(Utils.getQualifiedName(type), nodeData); NodeFieldData[] fields = parseFields(nodeData, elements, typeHierarchy); if (fields == null) { @@ -179,7 +183,7 @@ } if (specializations.size() > 1 && genericSpecialization == null) { - log.error(originalType, "Need a @%s method.", Generic.class.getSimpleName()); + log.error(type, "Need a @%s method.", Generic.class.getSimpleName()); return null; } @@ -435,9 +439,9 @@ // TODO redirect errors from resolve. context.getLog().error(errorElement, "Node type '%s' is invalid.", Utils.getQualifiedName(nodeType)); return null; - } else if (fieldNodeData.findGenericExecutableType(context) == null) { + } else if (fieldNodeData.findGenericExecutableTypes(context).isEmpty()) { // TODO better error handling for (no or multiple?) - context.getLog().error(errorElement, "No or multiple executable generic types found for node '%s'.", Utils.getQualifiedName(nodeType)); + context.getLog().error(errorElement, "No executable generic types found for node '%s'.", Utils.getQualifiedName(nodeType)); return null; } } @@ -612,13 +616,21 @@ return valid; } - private static boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) { + private boolean isGenericShortCutMethod(NodeData node, TemplateMethod method) { for (NodeFieldData field : node.getFields()) { ActualParameter parameter = method.findParameter(field.getName()); if (parameter == null) { continue; } - if (!Utils.typeEquals(node.getTypeSystem().getGenericType(), parameter.getActualType())) { + ExecutableTypeData found = null; + List<ExecutableTypeData> executableElements = field.getNodeData().findGenericExecutableTypes(context); + for (ExecutableTypeData executable : executableElements) { + if (executable.getType().equalsType(parameter.getActualTypeData(node.getTypeSystem()))) { + found = executable; + break; + } + } + if (found == null) { return false; } }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Mon Mar 04 10:00:49 2013 +0100 @@ -124,15 +124,4 @@ return false; } - public ActualParameter getPreviousParam(ActualParameter searchParam) { - ActualParameter prev = null; - for (ActualParameter param : getParameters()) { - if (param == searchParam) { - return prev; - } - prev = param; - } - return prev; - } - }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationMethodParser.java Mon Mar 04 10:00:49 2013 +0100 @@ -47,10 +47,6 @@ return specification; } - public MethodSpec getSpecification() { - return specification; - } - @Override public SpecializationData create(TemplateMethod method) { return parseSpecialization(method); @@ -157,17 +153,24 @@ private static boolean isGuardCompatible(SpecializationData specialization, GuardData guard) { Iterator<ActualParameter> guardParameters = Arrays.asList(guard.getParameters()).iterator(); for (ActualParameter param : specialization.getParameters()) { + if (param.getSpecification().isOptional()) { + continue; + } if (!guardParameters.hasNext()) { return false; } ActualParameter guardParam = guardParameters.next(); - if (!Utils.typeEquals(guardParam.getActualType(), param.getActualType())) { + if (!Utils.typeEquals(guardParam.getActualType(), param.getActualType()) && !guardParam.getSpecification().isOptional()) { return false; } } - if (guardParameters.hasNext()) { - return false; + while (guardParameters.hasNext()) { + ActualParameter param = guardParameters.next(); + if (!param.getSpecification().isOptional()) { + return false; + } } + return true; }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java Mon Mar 04 10:00:49 2013 +0100 @@ -30,16 +30,25 @@ private final ParameterSpec specification; private final TypeMirror actualType; + private TemplateMethod method; public ActualParameter(ParameterSpec specification, TypeMirror actualType) { this.specification = specification; this.actualType = actualType; } + void setMethod(TemplateMethod method) { + this.method = method; + } + public ParameterSpec getSpecification() { return specification; } + public TemplateMethod getMethod() { + return method; + } + public TypeMirror getActualType() { return actualType; } @@ -47,4 +56,8 @@ public TypeData getActualTypeData(TypeSystemData typeSystem) { return typeSystem.findTypeData(actualType); } + + public ActualParameter getPreviousParameter() { + return method.getPreviousParam(this); + } }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Mon Mar 04 10:00:49 2013 +0100 @@ -38,12 +38,10 @@ private final String name; private final TypeMirror[] allowedTypes; - private final TypeMirror valueType; private final boolean optional; private final Cardinality cardinality; - public ParameterSpec(String name, TypeMirror[] allowedTypes, TypeMirror valueType, boolean optional, Cardinality cardinality) { - this.valueType = valueType; + public ParameterSpec(String name, TypeMirror[] allowedTypes, boolean optional, Cardinality cardinality) { this.allowedTypes = allowedTypes; this.name = name; this.optional = optional; @@ -52,17 +50,17 @@ /** Type constructor. */ public ParameterSpec(String name, TypeMirror singleFixedType, boolean optional) { - this(name, new TypeMirror[]{singleFixedType}, singleFixedType, optional, Cardinality.ONE); + this(name, new TypeMirror[]{singleFixedType}, optional, Cardinality.ONE); } /** Type system value constructor. */ public ParameterSpec(String name, TypeSystemData typeSystem, boolean optional, Cardinality cardinality) { - this(name, typeSystem.getPrimitiveTypeMirrors(), typeSystem.getGenericType(), optional, cardinality); + this(name, typeSystem.getPrimitiveTypeMirrors(), optional, cardinality); } /** Node value constructor. */ public ParameterSpec(String name, NodeData nodeData, boolean optional, Cardinality cardinality) { - this(name, nodeTypeMirrors(nodeData), nodeData.getTypeSystem().getGenericType(), optional, cardinality); + this(name, nodeTypeMirrors(nodeData), optional, cardinality); } private static TypeMirror[] nodeTypeMirrors(NodeData nodeData) { @@ -103,7 +101,4 @@ return false; } - public TypeMirror getValueType() { - return valueType; - } }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Mon Mar 04 10:00:49 2013 +0100 @@ -40,15 +40,16 @@ this.markerAnnotation = markerAnnotation; this.returnType = returnType; this.parameters = parameters; + + if (parameters != null) { + for (ActualParameter param : parameters) { + param.setMethod(this); + } + } } public TemplateMethod(TemplateMethod method) { - this.template = method.template; - this.specification = method.specification; - this.method = method.method; - this.markerAnnotation = method.markerAnnotation; - this.returnType = method.returnType; - this.parameters = method.parameters; + this(method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters); } public Template getTemplate() { @@ -101,4 +102,15 @@ public String toString() { return getClass().getSimpleName() + " [method = " + method + "]"; } + + public ActualParameter getPreviousParam(ActualParameter searchParam) { + ActualParameter prev = null; + for (ActualParameter param : getParameters()) { + if (param == searchParam) { + return prev; + } + prev = param; + } + return prev; + } }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/GuardParser.java Mon Mar 04 10:00:49 2013 +0100 @@ -44,7 +44,6 @@ @Override public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { List<ParameterSpec> specs = new ArrayList<>(); - specs.add(new ParameterSpec("value1", typeSystem, false, Cardinality.ONE)); specs.add(new ParameterSpec("valueN", typeSystem, false, Cardinality.MULTIPLE)); ParameterSpec returnTypeSpec = new ParameterSpec("returnType", getContext().getType(boolean.class), false); return new MethodSpec(returnTypeSpec, specs);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java Mon Mar 04 10:00:49 2013 +0100 @@ -89,4 +89,8 @@ return getClass().getSimpleName() + "[" + Utils.getSimpleName(primitiveType) + "]"; } + public boolean equalsType(TypeData actualTypeData) { + return Utils.typeEquals(boxedType, actualTypeData.boxedType); + } + }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemParser.java Mon Mar 04 10:00:49 2013 +0100 @@ -162,10 +162,7 @@ continue; } - TypeMirror boxedType = primitiveType; - if (boxedType.getKind().isPrimitive()) { - boxedType = processingEnv.getTypeUtils().boxedClass((PrimitiveType) boxedType).asType(); - } + TypeMirror boxedType = Utils.boxType(context, primitiveType); if (Utils.typeEquals(boxedType, objectType)) { log.error(templateType, templateTypeAnnotation, annotationValue, "Types must not contain the generic type java.lang.Object.");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/TernaryTest.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,52 @@ +/* + * 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.truffle.sl.test; + +import org.junit.*; + +// @formatter:off +public class TernaryTest extends AbstractTest { + + private static String[] INPUT = new String[] { +"function main { " + +" print #(1 < 2) ? 1 : 2;" + +" print #(2 < 1) ? 100000000000000 : 1; ", +" print #(1 < 2) ? 100000000000000 : 1; ", +" print #(2 < 1) ? \"wrong\" : \"true\";", +" print #(2 < 1) ? \"wrong\" : 1;", +"} ", + }; + + private static String[] OUTPUT = new String[] { + "1", + "1", + "100000000000000", + "true", + "1", + }; + + @Test + public void test() { + executeSL(INPUT, OUTPUT, true); + } +}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Mon Mar 04 10:00:49 2013 +0100 @@ -127,4 +127,8 @@ StatementNode write = WriteLocalNodeFactory.create(slot, value); return new ReturnNode(write); } + + public TypedNode createTernary(TypedNode condition, TypedNode thenPart, TypedNode elsePart) { + return TernaryNodeFactory.create(condition, thenPart, elsePart); + } }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ConditionalNode.java Mon Mar 04 09:48:14 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +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.truffle.sl.nodes; - -import java.math.*; - -import com.oracle.truffle.api.codegen.*; - -@SuppressWarnings("unused") -@ExecuteChildren({"conditionNode", "ifPartNode", "elsePartNode"}) -public abstract class ConditionalNode extends TypedNode { - - @Child protected ConditionNode conditionNode; - - @Child protected TypedNode ifPartNode; - - @Child protected TypedNode elsePartNode; - - public ConditionalNode(ConditionNode condition, TypedNode ifPart, TypedNode elsePart) { - this.conditionNode = adoptChild(condition); - this.ifPartNode = adoptChild(ifPart); - this.elsePartNode = adoptChild(elsePart); - } - - public ConditionalNode(ConditionalNode condition) { - this(condition.conditionNode, condition.ifPartNode, condition.elsePartNode); - } - - @ShortCircuit("ifPartNode") - public boolean needsIfPart(boolean condition) { - return condition; - } - - @ShortCircuit("ifPartNode") - public boolean needsIfPart(Object condition) { - throw new RuntimeException("operation not defined for type " + condition.getClass().getSimpleName()); - } - - @ShortCircuit("elsePartNode") - public boolean needsElsePart(Object condition, boolean hasIfPart, Object ifPart) { - return !hasIfPart; - } - - @ShortCircuit("elsePartNode") - public boolean needsElsePart(boolean condition, boolean hasIfPart, int ifPart) { - return !hasIfPart; - } - - @ShortCircuit("elsePartNode") - public boolean needsElsePart(boolean condition, boolean hasIfPart, BigInteger ifPart) { - return !hasIfPart; - } - - @Specialization - public int doInteger(boolean condition, boolean hasIfPart, int ifPart, boolean hasElsePart, int elsePart) { - return hasIfPart ? ifPart : elsePart; - } - - @Specialization - public BigInteger doBigInteger(boolean condition, boolean hasIfPart, BigInteger ifPart, boolean hasElsePart, BigInteger elsePart) { - return hasIfPart ? ifPart : elsePart; - } - - @Generic - public Object doGeneric(boolean condition, boolean hasIfPart, Object ifPart, boolean hasElsePart, Object elsePart) { - return hasIfPart ? ifPart : elsePart; - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TernaryNode.java Mon Mar 04 10:00:49 2013 +0100 @@ -0,0 +1,73 @@ +/* + * 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.truffle.sl.nodes; + +import java.math.*; + +import com.oracle.truffle.api.codegen.*; + +@SuppressWarnings("unused") +@ExecuteChildren({"conditionNode", "ifPartNode", "elsePartNode"}) +public abstract class TernaryNode extends TypedNode { + + @Child protected ConditionNode conditionNode; + + @Child protected TypedNode ifPartNode; + + @Child protected TypedNode elsePartNode; + + public TernaryNode(ConditionNode condition, TypedNode ifPart, TypedNode elsePart) { + this.conditionNode = adoptChild(condition); + this.ifPartNode = adoptChild(ifPart); + this.elsePartNode = adoptChild(elsePart); + } + + public TernaryNode(TernaryNode condition) { + this(condition.conditionNode, condition.ifPartNode, condition.elsePartNode); + } + + @ShortCircuit("ifPartNode") + public boolean needsIfPart(boolean condition) { + return condition; + } + + @ShortCircuit("elsePartNode") + public boolean needsElsePart(boolean condition, boolean hasIfPart, Object ifPart) { + return !hasIfPart; + } + + @Specialization + public int doInteger(boolean condition, boolean hasIfPart, int ifPart, boolean hasElsePart, int elsePart) { + return hasIfPart ? ifPart : elsePart; + } + + @Specialization + public BigInteger doBigInteger(boolean condition, boolean hasIfPart, BigInteger ifPart, boolean hasElsePart, BigInteger elsePart) { + return hasIfPart ? ifPart : elsePart; + } + + @Generic + public Object doGeneric(boolean condition, boolean hasIfPart, Object ifPart, boolean hasElsePart, Object elsePart) { + return hasIfPart ? ifPart : elsePart; + } +}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Mon Mar 04 10:00:49 2013 +0100 @@ -21,10 +21,9 @@ * questions. */ -// The content of this file is automatically generated. DO NOT EDIT. + // The content of this file is automatically generated. DO NOT EDIT. package com.oracle.truffle.sl.parser; - import java.util.*; import com.oracle.truffle.sl.*; @@ -33,11 +32,11 @@ // Checkstyle: stop // @formatter:off public class Parser { - public static final int _EOF = 0; - public static final int _identifier = 1; - public static final int _stringLiteral = 2; - public static final int _numericLiteral = 3; - public static final int maxT = 25; + public static final int _EOF = 0; + public static final int _identifier = 1; + public static final int _stringLiteral = 2; + public static final int _numericLiteral = 3; + public static final int maxT = 28; static final boolean T = true; static final boolean x = false; @@ -50,7 +49,7 @@ public final Scanner scanner; public final Errors errors; private final NodeFactory factory; - + public Parser(Scanner scanner, NodeFactory factory) { this.scanner = scanner; this.factory = factory; @@ -121,226 +120,255 @@ } } - void SimpleLanguage() { - Function(); - while (la.kind == 4) { - Function(); - } - } - - void Function() { - Expect(4); - factory.startFunction(); - Expect(1); - String name = t.val; - StatementNode body = Block(); - factory.createFunction(body, name); - } - - StatementNode Block() { - StatementNode result; - List<StatementNode> statements = new ArrayList<>(); - Expect(5); - while (StartOf(1)) { - StatementNode statement = Statement(); - statements.add(statement); - } - Expect(6); - result = factory.createBlock(statements); - return result; - } - - StatementNode Statement() { - StatementNode result; - result = null; - if (la.kind == 7) { - result = WhileStatement(); - } else if (la.kind == 1) { - result = AssignmentStatement(); - } else if (la.kind == 12) { - result = OutputStatement(); - } else if (la.kind == 13) { - result = ReturnStatement(); - } else SynErr(26); - return result; - } - - StatementNode WhileStatement() { - StatementNode result; - Expect(7); - Expect(8); - ConditionNode condition = Expression(); - Expect(9); - StatementNode body = Block(); - result = factory.createWhile(condition, body); - return result; - } - - StatementNode AssignmentStatement() { - StatementNode result; - Expect(1); - String name = t.val; - Expect(10); - TypedNode rvalue = Expression(); - Expect(11); - result = factory.createAssignment(name, rvalue); - return result; - } - - StatementNode OutputStatement() { - StatementNode result; - List<TypedNode> expressions = new ArrayList<>(); - Expect(12); - while (StartOf(2)) { - TypedNode value = Expression(); - expressions.add(value); - } - Expect(11); - result = factory.createPrint(expressions); - return result; - } - - StatementNode ReturnStatement() { - StatementNode result; - Expect(13); - TypedNode value = Expression(); - Expect(11); - result = factory.createReturn(value); - return result; - } - - TypedNode Expression() { - TypedNode result; - result = ValueExpression(); - if (StartOf(3)) { - switch (la.kind) { - case 14: { - Get(); - break; - } - case 15: { - Get(); - break; - } - case 16: { - Get(); - break; - } - case 17: { - Get(); - break; - } - case 18: { - Get(); - break; - } - case 19: { - Get(); - break; - } - } - String op = t.val; - TypedNode right = ValueExpression(); - result = factory.createBinary(op, result, right); - } - return result; - } - - TypedNode ValueExpression() { - TypedNode result; - result = Term(); - while (la.kind == 20 || la.kind == 21) { - if (la.kind == 20) { - Get(); - } else { - Get(); - } - String op = t.val; - TypedNode right = Term(); - result = factory.createBinary(op, result, right); - } - return result; - } - - TypedNode Term() { - TypedNode result; - result = Factor(); - while (la.kind == 22 || la.kind == 23) { - if (la.kind == 22) { - Get(); - } else { - Get(); - } - String op = t.val; - TypedNode right = Factor(); - result = factory.createBinary(op, result, right); - } - return result; - } - - TypedNode Factor() { - TypedNode result; - result = null; - if (la.kind == 24) { - result = TimeRef(); - } else if (la.kind == 1) { - result = VariableRef(); - } else if (la.kind == 2) { - result = StringLiteral(); - } else if (la.kind == 3) { - result = NumericLiteral(); - } else if (la.kind == 8) { - Get(); - result = Expression(); - Expect(9); - } else SynErr(27); - return result; - } - - TypedNode TimeRef() { - TypedNode result; - Expect(24); - result = factory.createTime(); - return result; - } - - TypedNode VariableRef() { - TypedNode result; - Expect(1); - result = factory.createLocal(t.val); - return result; - } - - TypedNode StringLiteral() { - TypedNode result; - Expect(2); - result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); - return result; - } - - TypedNode NumericLiteral() { - TypedNode result; - Expect(3); - result = factory.createNumericLiteral(t.val); - return result; - } - + void SimpleLanguage() { + Function(); + while (la.kind == 4) { + Function(); + } + } + + void Function() { + Expect(4); + factory.startFunction(); + Expect(1); + String name = t.val; + StatementNode body = Block(); + factory.createFunction(body, name); + } + + StatementNode Block() { + StatementNode result; + List<StatementNode> statements = new ArrayList<>(); + Expect(5); + while (StartOf(1)) { + StatementNode statement = Statement(); + statements.add(statement); + } + Expect(6); + result = factory.createBlock(statements); + return result; + } + + StatementNode Statement() { + StatementNode result; + result = null; + if (la.kind == 7) { + result = WhileStatement(); + } else if (la.kind == 1) { + result = AssignmentStatement(); + } else if (la.kind == 12) { + result = OutputStatement(); + } else if (la.kind == 13) { + result = ReturnStatement(); + } else SynErr(29); + return result; + } + + StatementNode WhileStatement() { + StatementNode result; + Expect(7); + Expect(8); + ConditionNode condition = Expression(); + Expect(9); + StatementNode body = Block(); + result = factory.createWhile(condition, body); + return result; + } + + StatementNode AssignmentStatement() { + StatementNode result; + Expect(1); + String name = t.val; + Expect(10); + TypedNode rvalue = Expression(); + Expect(11); + result = factory.createAssignment(name, rvalue); + return result; + } + + StatementNode OutputStatement() { + StatementNode result; + List<TypedNode> expressions = new ArrayList<>(); + Expect(12); + while (StartOf(2)) { + TypedNode value = Expression(); + expressions.add(value); + } + Expect(11); + result = factory.createPrint(expressions); + return result; + } + + StatementNode ReturnStatement() { + StatementNode result; + Expect(13); + TypedNode value = Expression(); + Expect(11); + result = factory.createReturn(value); + return result; + } + + TypedNode Expression() { + TypedNode result; + result = ValueExpression(); + if (StartOf(3)) { + switch (la.kind) { + case 14: { + Get(); + break; + } + case 15: { + Get(); + break; + } + case 16: { + Get(); + break; + } + case 17: { + Get(); + break; + } + case 18: { + Get(); + break; + } + case 19: { + Get(); + break; + } + } + String op = t.val; + TypedNode right = ValueExpression(); + result = factory.createBinary(op, result, right); + } + return result; + } + + TypedNode ValueExpression() { + TypedNode result; + result = Term(); + while (la.kind == 20 || la.kind == 21) { + if (la.kind == 20) { + Get(); + } else { + Get(); + } + String op = t.val; + TypedNode right = Term(); + result = factory.createBinary(op, result, right); + } + return result; + } + + TypedNode Term() { + TypedNode result; + result = Factor(); + while (la.kind == 22 || la.kind == 23) { + if (la.kind == 22) { + Get(); + } else { + Get(); + } + String op = t.val; + TypedNode right = Factor(); + result = factory.createBinary(op, result, right); + } + return result; + } + + TypedNode Factor() { + TypedNode result; + result = null; + switch (la.kind) { + case 27: { + result = TimeRef(); + break; + } + case 1: { + result = VariableRef(); + break; + } + case 2: { + result = StringLiteral(); + break; + } + case 3: { + result = NumericLiteral(); + break; + } + case 24: { + result = Ternary(); + break; + } + case 8: { + Get(); + result = Expression(); + Expect(9); + break; + } + default: SynErr(30); break; + } + return result; + } + + TypedNode TimeRef() { + TypedNode result; + Expect(27); + result = factory.createTime(); + return result; + } + + TypedNode VariableRef() { + TypedNode result; + Expect(1); + result = factory.createLocal(t.val); + return result; + } + + TypedNode StringLiteral() { + TypedNode result; + Expect(2); + result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); + return result; + } + + TypedNode NumericLiteral() { + TypedNode result; + Expect(3); + result = factory.createNumericLiteral(t.val); + return result; + } + + TypedNode Ternary() { + TypedNode result; + TypedNode condition, thenPart, elsePart; + Expect(24); + condition = Expression(); + Expect(25); + thenPart = Expression(); + Expect(26); + elsePart = Expression(); + result = factory.createTernary(condition, thenPart, elsePart); + return result; + } + public void Parse() { la = new Token(); la.val = ""; Get(); - SimpleLanguage(); - Expect(0); + SimpleLanguage(); + Expect(0); } private static final boolean[][] set = { - {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, - {x,T,x,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x}, - {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x,x, x,x,x} + {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, + {x,T,x,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, + {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,T, x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x} }; @@ -388,35 +416,38 @@ public void SynErr(int line, int col, int n) { String s; - switch (n) { - case 0: s = "EOF expected"; break; - case 1: s = "identifier expected"; break; - case 2: s = "stringLiteral expected"; break; - case 3: s = "numericLiteral expected"; break; - case 4: s = "\"function\" expected"; break; - case 5: s = "\"{\" expected"; break; - case 6: s = "\"}\" expected"; break; - case 7: s = "\"while\" expected"; break; - case 8: s = "\"(\" expected"; break; - case 9: s = "\")\" expected"; break; - case 10: s = "\"=\" expected"; break; - case 11: s = "\";\" expected"; break; - case 12: s = "\"print\" expected"; break; - case 13: s = "\"return\" expected"; break; - case 14: s = "\"<\" expected"; break; - case 15: s = "\">\" expected"; break; - case 16: s = "\"<=\" expected"; break; - case 17: s = "\">=\" expected"; break; - case 18: s = "\"==\" expected"; break; - case 19: s = "\"!=\" expected"; break; - case 20: s = "\"+\" expected"; break; - case 21: s = "\"-\" expected"; break; - case 22: s = "\"*\" expected"; break; - case 23: s = "\"/\" expected"; break; - case 24: s = "\"time\" expected"; break; - case 25: s = "??? expected"; break; - case 26: s = "invalid Statement"; break; - case 27: s = "invalid Factor"; break; + switch (n) { + case 0: s = "EOF expected"; break; + case 1: s = "identifier expected"; break; + case 2: s = "stringLiteral expected"; break; + case 3: s = "numericLiteral expected"; break; + case 4: s = "\"function\" expected"; break; + case 5: s = "\"{\" expected"; break; + case 6: s = "\"}\" expected"; break; + case 7: s = "\"while\" expected"; break; + case 8: s = "\"(\" expected"; break; + case 9: s = "\")\" expected"; break; + case 10: s = "\"=\" expected"; break; + case 11: s = "\";\" expected"; break; + case 12: s = "\"print\" expected"; break; + case 13: s = "\"return\" expected"; break; + case 14: s = "\"<\" expected"; break; + case 15: s = "\">\" expected"; break; + case 16: s = "\"<=\" expected"; break; + case 17: s = "\">=\" expected"; break; + case 18: s = "\"==\" expected"; break; + case 19: s = "\"!=\" expected"; break; + case 20: s = "\"+\" expected"; break; + case 21: s = "\"-\" expected"; break; + case 22: s = "\"*\" expected"; break; + case 23: s = "\"/\" expected"; break; + case 24: s = "\"#\" expected"; break; + case 25: s = "\"?\" expected"; break; + case 26: s = "\":\" expected"; break; + case 27: s = "\"time\" expected"; break; + case 28: s = "??? expected"; break; + case 29: s = "invalid Statement"; break; + case 30: s = "invalid Factor"; break; default: s = "error " + n; break;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java Mon Mar 04 10:00:49 2013 +0100 @@ -311,8 +311,8 @@ static final char EOL = '\n'; static final int eofSym = 0; - static final int maxT = 25; - static final int noSym = 25; + static final int maxT = 28; + static final int noSym = 28; public Buffer buffer; // scanner buffer @@ -339,27 +339,30 @@ for (int i = 65; i <= 90; ++i) start.set(i, 1); for (int i = 97; i <= 122; ++i) start.set(i, 1); for (int i = 49; i <= 57; ++i) start.set(i, 4); - start.set(34, 2); - start.set(48, 5); - start.set(123, 6); - start.set(125, 7); - start.set(40, 8); - start.set(41, 9); - start.set(61, 20); - start.set(59, 10); - start.set(60, 21); - start.set(62, 22); - start.set(33, 14); - start.set(43, 16); - start.set(45, 17); - start.set(42, 18); - start.set(47, 19); + start.set(34, 2); + start.set(48, 5); + start.set(123, 6); + start.set(125, 7); + start.set(40, 8); + start.set(41, 9); + start.set(61, 23); + start.set(59, 10); + start.set(60, 24); + start.set(62, 25); + start.set(33, 14); + start.set(43, 16); + start.set(45, 17); + start.set(42, 18); + start.set(47, 19); + start.set(35, 20); + start.set(63, 21); + start.set(58, 22); start.set(Buffer.EOF, -1); literals.put("function", new Integer(4)); literals.put("while", new Integer(7)); literals.put("print", new Integer(12)); literals.put("return", new Integer(13)); - literals.put("time", new Integer(24)); + literals.put("time", new Integer(27)); } @@ -425,7 +428,7 @@ tval = newBuf; } if (ch != Buffer.EOF) { - tval[tlen++] = (char)ch; + tval[tlen++] = (char)ch; NextCh(); } @@ -484,9 +487,9 @@ } Token NextToken() { - while (ch == ' ' || + while (ch == ' ' || ch >= 9 && ch <= 10 || ch == 13 - ) NextCh(); + ) NextCh(); if (ch == '/' && Comment0() ||ch == '/' && Comment1()) return NextToken(); int recKind = noSym; int recEnd = pos; @@ -515,60 +518,66 @@ } // NextCh already done case 1: recEnd = pos; recKind = 1; - if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;} + if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;} else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;} case 2: - if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;} - else if (ch == '"') {AddCh(); state = 3; break;} + if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;} + else if (ch == '"') {AddCh(); state = 3; break;} else {state = 0; break;} - case 3: + case 3: {t.kind = 2; break loop;} case 4: recEnd = pos; recKind = 3; - if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;} + if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;} else {t.kind = 3; break loop;} - case 5: + case 5: {t.kind = 3; break loop;} - case 6: + case 6: {t.kind = 5; break loop;} - case 7: + case 7: {t.kind = 6; break loop;} - case 8: + case 8: {t.kind = 8; break loop;} - case 9: + case 9: {t.kind = 9; break loop;} - case 10: + case 10: {t.kind = 11; break loop;} - case 11: + case 11: {t.kind = 16; break loop;} - case 12: + case 12: {t.kind = 17; break loop;} - case 13: + case 13: {t.kind = 18; break loop;} case 14: - if (ch == '=') {AddCh(); state = 15; break;} + if (ch == '=') {AddCh(); state = 15; break;} else {state = 0; break;} - case 15: + case 15: {t.kind = 19; break loop;} - case 16: + case 16: {t.kind = 20; break loop;} - case 17: + case 17: {t.kind = 21; break loop;} - case 18: + case 18: {t.kind = 22; break loop;} - case 19: + case 19: {t.kind = 23; break loop;} - case 20: + case 20: + {t.kind = 24; break loop;} + case 21: + {t.kind = 25; break loop;} + case 22: + {t.kind = 26; break loop;} + case 23: recEnd = pos; recKind = 10; - if (ch == '=') {AddCh(); state = 13; break;} + if (ch == '=') {AddCh(); state = 13; break;} else {t.kind = 10; break loop;} - case 21: + case 24: recEnd = pos; recKind = 14; - if (ch == '=') {AddCh(); state = 11; break;} + if (ch == '=') {AddCh(); state = 11; break;} else {t.kind = 14; break loop;} - case 22: + case 25: recEnd = pos; recKind = 15; - if (ch == '=') {AddCh(); state = 12; break;} + if (ch == '=') {AddCh(); state = 12; break;} else {t.kind = 15; break loop;} }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg Mon Mar 04 09:48:14 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg Mon Mar 04 10:00:49 2013 +0100 @@ -131,11 +131,19 @@ | NumericLiteral<out result> | + Ternary<out result> +| "(" Expression<out result> ")" -) +) . -TimeRef<out TypedNode result> +Ternary<out TypedNode result> (. TypedNode condition, thenPart, elsePart; .) += +"#" Expression<out condition> "?" Expression<out thenPart> ":" Expression<out elsePart> + (. result = factory.createTernary(condition, thenPart, elsePart); .) +. + +TimeRef<out TypedNode result> = "time" (. result = factory.createTime(); .) .
--- a/mx/eclipse-settings/org.eclipse.jdt.core.prefs Mon Mar 04 09:48:14 2013 +0100 +++ b/mx/eclipse-settings/org.eclipse.jdt.core.prefs Mon Mar 04 10:00:49 2013 +0100 @@ -132,7 +132,7 @@ org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=48 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 @@ -140,7 +140,7 @@ org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 -org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=48 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 @@ -149,7 +149,7 @@ org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=48 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
--- a/mx/projects Mon Mar 04 09:48:14 2013 +0100 +++ b/mx/projects Mon Mar 04 10:00:49 2013 +0100 @@ -62,6 +62,13 @@ project@com.oracle.graal.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.amd64@javaCompliance=1.7 +# graal.ptx +project@com.oracle.graal.ptx@subDir=graal +project@com.oracle.graal.ptx@sourceDirs=src +project@com.oracle.graal.ptx@dependencies=com.oracle.graal.api.code +project@com.oracle.graal.ptx@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.ptx@javaCompliance=1.7 + # graal.sparc project@com.oracle.graal.sparc@subDir=graal project@com.oracle.graal.sparc@sourceDirs=src @@ -137,6 +144,13 @@ project@com.oracle.graal.lir.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.lir.amd64@javaCompliance=1.7 +# graal.lir.ptx +project@com.oracle.graal.lir.ptx@subDir=graal +project@com.oracle.graal.lir.ptx@sourceDirs=src +project@com.oracle.graal.lir.ptx@dependencies=com.oracle.graal.asm.ptx,com.oracle.graal.lir +project@com.oracle.graal.lir.ptx@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.lir.ptx@javaCompliance=1.7 + # graal.lir.sparc project@com.oracle.graal.lir.sparc@subDir=graal project@com.oracle.graal.lir.sparc@sourceDirs=src @@ -221,6 +235,20 @@ project@com.oracle.graal.compiler.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.amd64@javaCompliance=1.7 +# graal.compiler.ptx +project@com.oracle.graal.compiler.ptx@subDir=graal +project@com.oracle.graal.compiler.ptx@sourceDirs=src +project@com.oracle.graal.compiler.ptx@dependencies=com.oracle.graal.compiler,com.oracle.graal.lir.ptx +project@com.oracle.graal.compiler.ptx@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.compiler.ptx@javaCompliance=1.7 + +# graal.compiler.ptx.test +project@com.oracle.graal.compiler.ptx.test@subDir=graal +project@com.oracle.graal.compiler.ptx.test@sourceDirs=src +project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.compiler.ptx,com.oracle.graal.compiler.test +project@com.oracle.graal.compiler.ptx.test@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.compiler.ptx.test@javaCompliance=1.7 + # graal.compiler.sparc project@com.oracle.graal.compiler.sparc@subDir=graal project@com.oracle.graal.compiler.sparc@sourceDirs=src @@ -297,6 +325,13 @@ project@com.oracle.graal.asm.amd64.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.asm.amd64.test@javaCompliance=1.7 +# graal.asm.ptx +project@com.oracle.graal.asm.ptx@subDir=graal +project@com.oracle.graal.asm.ptx@sourceDirs=src +project@com.oracle.graal.asm.ptx@dependencies=com.oracle.graal.asm,com.oracle.graal.ptx +project@com.oracle.graal.asm.ptx@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.asm.ptx@javaCompliance=1.7 + # graal.asm.sparc project@com.oracle.graal.asm.sparc@subDir=graal project@com.oracle.graal.asm.sparc@sourceDirs=src
--- a/mxtool/mx.py Mon Mar 04 09:48:14 2013 +0100 +++ b/mxtool/mx.py Mon Mar 04 10:00:49 2013 +0100 @@ -2492,6 +2492,25 @@ """(re)generate Eclipse and NetBeans project configurations""" eclipseinit(args, suite) netbeansinit(args, suite) + fsckprojects([]) + +def fsckprojects(args): + """find directories corresponding to deleted Java projects and delete them""" + for suite in suites(): + projectDirs = [p.dir for p in suite.projects] + for root, dirnames, files in os.walk(suite.dir): + currentDir = join(suite.dir, root) + if currentDir in projectDirs: + # don't traverse subdirs of an existing project + dirnames[:] = [] + else: + projectConfigFiles = frozenset(['.classpath', 'nbproject']) + indicators = projectConfigFiles.intersection(files) + if len(indicators) != 0: + response = raw_input(currentDir + ' looks like a removed project -- delete it? [yn]: ') + if 'y' == response: + shutil.rmtree(currentDir) + log('Deleted ' + currentDir) def javadoc(args, parser=None, docDir='javadoc', includeDeps=True): """generate javadoc for some/all Java projects""" @@ -2944,6 +2963,7 @@ 'eclipseinit': [eclipseinit, ''], 'eclipseformat': [eclipseformat, ''], 'findclass': [findclass, ''], + 'fsckprojects': [fsckprojects, ''], 'help': [help_, '[command]'], 'ideclean': [ideclean, ''], 'ideinit': [ideinit, ''],
--- a/src/cpu/x86/vm/graalRuntime_x86.cpp Mon Mar 04 09:48:14 2013 +0100 +++ b/src/cpu/x86/vm/graalRuntime_x86.cpp Mon Mar 04 10:00:49 2013 +0100 @@ -638,9 +638,9 @@ OopMapSet* oop_maps = new OopMapSet(); OopMap* oop_map = NULL; switch (id) { - case graal_handle_exception_nofpu_id: + case handle_exception_nofpu_id: // At this point all registers MAY be live. - oop_map = save_live_registers(sasm, 1 /*thread*/, id == graal_handle_exception_nofpu_id); + oop_map = save_live_registers(sasm, 1 /*thread*/, id == handle_exception_nofpu_id); break; default: ShouldNotReachHere(); } @@ -712,9 +712,9 @@ __ movptr(Address(rbp, 1*BytesPerWord), rax); switch (id) { - case graal_handle_exception_nofpu_id: + case handle_exception_nofpu_id: // Restore the registers that were saved at the beginning. - restore_live_registers(sasm, id == graal_handle_exception_nofpu_id); + restore_live_registers(sasm, id == handle_exception_nofpu_id); break; default: ShouldNotReachHere(); } @@ -824,7 +824,7 @@ OopMapSet* oop_maps = NULL; switch (id) { - case graal_new_instance_id: + case new_instance_id: { Register klass = rdx; // Incoming Register obj = rax; // Result @@ -844,7 +844,7 @@ break; - case graal_new_array_id: + case new_array_id: { Register length = rbx; // Incoming Register klass = rdx; // Incoming @@ -869,7 +869,7 @@ } break; - case graal_new_multi_array_id: + case new_multi_array_id: { GraalStubFrame f(sasm, "new_multi_array", dont_gc_arguments); // rax,: klass // rbx,: rank @@ -886,7 +886,7 @@ } break; - case graal_register_finalizer_id: + case register_finalizer_id: { __ set_info("register_finalizer", dont_gc_arguments); @@ -927,13 +927,13 @@ } break; - case graal_handle_exception_nofpu_id: + case handle_exception_nofpu_id: { GraalStubFrame f(sasm, "handle_exception", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case graal_slow_subtype_check_id: + case slow_subtype_check_id: { // Typical calling sequence: // __ push(klass_RInfo); // object klass or other subclass @@ -990,7 +990,7 @@ } break; - case graal_unwind_exception_call_id: { + case unwind_exception_call_id: { // remove the frame from the stack __ movptr(rsp, rbp); __ pop(rbp); @@ -1004,7 +1004,7 @@ __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(rax, noreg, (address)graal_create_null_exception, 0); + int call_offset = __ call_RT(rax, noreg, (address)create_null_exception, 0); oop_maps->add_gc_map(call_offset, oop_map); __ leave(); } @@ -1018,7 +1018,7 @@ break; } - case graal_OSR_migration_end_id: { + case OSR_migration_end_id: { __ enter(); save_live_registers(sasm, 0); __ movptr(c_rarg0, j_rarg0); @@ -1029,39 +1029,39 @@ break; } - case graal_set_deopt_info_id: { + case set_deopt_info_id: { __ movptr(Address(r15_thread, JavaThread::graal_deopt_info_offset()), rscratch1); __ ret(0); break; } - case graal_create_null_pointer_exception_id: { + case create_null_pointer_exception_id: { __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(rax, noreg, (address)graal_create_null_exception, 0); + int call_offset = __ call_RT(rax, noreg, (address)create_null_exception, 0); oop_maps->add_gc_map(call_offset, oop_map); __ leave(); __ ret(0); break; } - case graal_create_out_of_bounds_exception_id: { + case create_out_of_bounds_exception_id: { __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(rax, noreg, (address)graal_create_out_of_bounds_exception, j_rarg0); + int call_offset = __ call_RT(rax, noreg, (address)create_out_of_bounds_exception, j_rarg0); oop_maps->add_gc_map(call_offset, oop_map); __ leave(); __ ret(0); break; } - case graal_vm_error_id: { + case vm_error_id: { __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(noreg, noreg, (address)graal_vm_error, j_rarg0, j_rarg1, j_rarg2); + int call_offset = __ call_RT(noreg, noreg, (address)vm_error, j_rarg0, j_rarg1, j_rarg2); oop_maps->add_gc_map(call_offset, oop_map); restore_live_registers(sasm); __ leave(); @@ -1069,11 +1069,11 @@ break; } - case graal_log_printf_id: { + case log_printf_id: { __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(noreg, noreg, (address)graal_log_printf, j_rarg0, j_rarg1, j_rarg2, j_rarg3); + int call_offset = __ call_RT(noreg, noreg, (address)log_printf, j_rarg0, j_rarg1, j_rarg2, j_rarg3); oop_maps->add_gc_map(call_offset, oop_map); restore_live_registers(sasm); __ leave(); @@ -1081,11 +1081,11 @@ break; } - case graal_log_primitive_id: { + case log_primitive_id: { __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(noreg, noreg, (address)graal_log_primitive, j_rarg0, j_rarg1, j_rarg2); + int call_offset = __ call_RT(noreg, noreg, (address)log_primitive, j_rarg0, j_rarg1, j_rarg2); oop_maps->add_gc_map(call_offset, oop_map); restore_live_registers(sasm); __ leave(); @@ -1093,11 +1093,11 @@ break; } - case graal_log_object_id: { + case log_object_id: { __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(noreg, noreg, (address)graal_log_object, j_rarg0, j_rarg1); + int call_offset = __ call_RT(noreg, noreg, (address)log_object, j_rarg0, j_rarg1); oop_maps->add_gc_map(call_offset, oop_map); restore_live_registers(sasm); __ leave(); @@ -1105,7 +1105,7 @@ break; } - case graal_verify_oop_id: { + case verify_oop_id: { // We use enter & leave so that a better stack trace is produced in the hs_err file __ enter(); __ verify_oop(r13, "Graal verify oop"); @@ -1114,7 +1114,7 @@ break; } - case graal_arithmetic_frem_id: { + case arithmetic_frem_id: { __ subptr(rsp, 8); __ movflt(Address(rsp, 0), xmm1); __ fld_s(Address(rsp, 0)); @@ -1135,7 +1135,7 @@ __ ret(0); break; } - case graal_arithmetic_drem_id: { + case arithmetic_drem_id: { __ subptr(rsp, 8); __ movdbl(Address(rsp, 0), xmm1); __ fld_d(Address(rsp, 0)); @@ -1156,15 +1156,15 @@ __ ret(0); break; } - case graal_monitorenter_id: { + case monitorenter_id: { Register obj = j_rarg0; Register lock = j_rarg1; { - GraalStubFrame f(sasm, "graal_monitorenter", dont_gc_arguments); + GraalStubFrame f(sasm, "monitorenter", dont_gc_arguments); OopMap* map = save_live_registers(sasm, 2, save_fpu_registers); // Called with store_parameter and not C abi - int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_monitorenter), obj, lock); + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), obj, lock); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, map); @@ -1173,17 +1173,17 @@ __ ret(0); break; } - case graal_monitorexit_id: { + case monitorexit_id: { Register obj = j_rarg0; Register lock = j_rarg1; { - GraalStubFrame f(sasm, "graal_monitorexit", dont_gc_arguments); + GraalStubFrame f(sasm, "monitorexit", dont_gc_arguments); OopMap* map = save_live_registers(sasm, 2, save_fpu_registers); // note: really a leaf routine but must setup last java sp // => use call_RT for now (speed can be improved by // doing last java sp setup manually) - int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_monitorexit), obj, lock); + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit), obj, lock); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, map); @@ -1193,12 +1193,12 @@ break; } - case graal_identity_hash_code_id: { + case identity_hash_code_id: { Register obj = j_rarg0; // Incoming __ set_info("identity_hash_code", dont_gc_arguments); __ enter(); OopMap* map = save_live_registers(sasm, 1); - int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_identity_hash_code), obj); + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, identity_hash_code), obj); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, map); restore_live_registers_except_rax(sasm); @@ -1206,14 +1206,14 @@ __ ret(0); break; } - case graal_thread_is_interrupted_id: { + case thread_is_interrupted_id: { Register thread = j_rarg0; Register clear_interrupted = j_rarg1; __ set_info("identity_hash_code", dont_gc_arguments); __ enter(); OopMap* map = save_live_registers(sasm, 1); - int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_thread_is_interrupted), thread, clear_interrupted); + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, thread_is_interrupted), thread, clear_interrupted); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, map); restore_live_registers_except_rax(sasm);
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java Mon Mar 04 09:48:14 2013 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java Mon Mar 04 10:00:49 2013 +0100 @@ -45,7 +45,6 @@ Set<Connection> connectionsToRemove = new HashSet<>(); for (Figure f : d.getFigures()) { final String prop = f.getProperties().get("probability"); - if (prop == null) { figuresToRemove.add(f); } @@ -54,7 +53,15 @@ for (Figure f : d.getFigures()) { Properties p = f.getProperties(); - int predCount = Integer.parseInt(p.get("predecessorCount")); + int predCount; + String predCountString = p.get("predecessorCount"); + if (predCountString != null) { + predCount = Integer.parseInt(predCountString); + } else if (Boolean.parseBoolean(p.get("hasPredecessor"))) { + predCount = 1; + } else { + predCount = 0; + } for (InputSlot is : f.getInputSlots()) { if (is.getPosition() >= predCount && !"EndNode".equals(is.getProperties().get("class"))) { for (Connection c : is.getConnections()) {
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java Mon Mar 04 09:48:14 2013 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java Mon Mar 04 10:00:49 2013 +0100 @@ -58,7 +58,10 @@ for (Figure f : figures) { Properties p = f.getProperties(); int predCount; - if (Boolean.parseBoolean(p.get("hasPredecessor"))) { + String predCountString = p.get("predecessorCount"); + if (predCountString != null) { + predCount = Integer.parseInt(predCountString); + } else if (Boolean.parseBoolean(p.get("hasPredecessor"))) { predCount = 1; } else { predCount = 0;
--- a/src/share/vm/classfile/systemDictionary.hpp Mon Mar 04 09:48:14 2013 +0100 +++ b/src/share/vm/classfile/systemDictionary.hpp Mon Mar 04 10:00:49 2013 +0100 @@ -186,6 +186,7 @@ do_klass(GraalBitMap_klass, java_util_BitSet, Opt) \ /* graal.hotspot */ \ do_klass(HotSpotCompilationResult_klass, com_oracle_graal_hotspot_HotSpotCompilationResult, Opt) \ + do_klass(HotSpotRuntimeCallTarget_klass, com_oracle_graal_hotspot_HotSpotRuntimeCallTarget, Opt) \ do_klass(HotSpotCodeInfo_klass, com_oracle_graal_hotspot_meta_HotSpotCodeInfo, Opt) \ do_klass(HotSpotInstalledCode_klass, com_oracle_graal_hotspot_meta_HotSpotInstalledCode, Opt) \ do_klass(HotSpotJavaType_klass, com_oracle_graal_hotspot_meta_HotSpotJavaType, Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp Mon Mar 04 09:48:14 2013 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Mon Mar 04 10:00:49 2013 +0100 @@ -295,6 +295,7 @@ template(com_oracle_graal_hotspot_HotSpotKlassOop, "com/oracle/graal/hotspot/HotSpotKlassOop") \ template(com_oracle_graal_hotspot_HotSpotOptions, "com/oracle/graal/hotspot/HotSpotOptions") \ template(com_oracle_graal_hotspot_HotSpotCompilationResult, "com/oracle/graal/hotspot/HotSpotCompilationResult") \ + template(com_oracle_graal_hotspot_HotSpotRuntimeCallTarget, "com/oracle/graal/hotspot/HotSpotRuntimeCallTarget") \ template(com_oracle_graal_hotspot_bridge_VMToCompiler, "com/oracle/graal/hotspot/bridge/VMToCompiler") \ template(com_oracle_graal_hotspot_meta_HotSpotCodeInfo, "com/oracle/graal/hotspot/meta/HotSpotCodeInfo") \ template(com_oracle_graal_hotspot_meta_HotSpotInstalledCode, "com/oracle/graal/hotspot/meta/HotSpotInstalledCode") \
--- a/src/share/vm/graal/graalCodeInstaller.cpp Mon Mar 04 09:48:14 2013 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Mon Mar 04 10:00:49 2013 +0100 @@ -29,7 +29,6 @@ #include "graal/graalCodeInstaller.hpp" #include "graal/graalJavaAccess.hpp" #include "graal/graalCompilerToVM.hpp" -#include "graal/graalVmIds.hpp" #include "graal/graalRuntime.hpp" #include "asm/register.hpp" #include "classfile/vmSymbols.hpp" @@ -209,7 +208,7 @@ return new ConstantOopWriteValue(JNIHandles::make_local(obj)); } } else if (type == T_ADDRESS) { - return new ConstantLongValue(prim); + ShouldNotReachHere(); } tty->print("%i", type); } else if (value->is_a(VirtualObject::klass())) { @@ -362,7 +361,7 @@ const char* cname = java_lang_String::as_utf8_string(_name); blob = BufferBlob::create(strdup(cname), &buffer); // this is leaking strings... but only a limited number of stubs will be created IF_TRACE_graal_3 Disassembler::decode((CodeBlob*) blob); - id = VmIds::addStub(blob->code_begin()); + id = (jlong)blob->code_begin(); } void CodeInstaller::initialize_fields(oop comp_result, methodHandle method) { @@ -606,7 +605,7 @@ oop hotspot_method = NULL; // JavaMethod oop global_stub = NULL; - if (target_klass->is_subclass_of(SystemDictionary::Long_klass())) { + if (target_klass->is_subclass_of(SystemDictionary::HotSpotRuntimeCallTarget_klass())) { global_stub = target; } else { hotspot_method = target; @@ -659,21 +658,20 @@ } if (global_stub != NULL) { - assert(java_lang_boxing_object::is_instance(global_stub, T_LONG), "global_stub needs to be of type Long"); - + jlong global_stub_destination = HotSpotRuntimeCallTarget::address(global_stub); if (inst->is_call()) { // NOTE: for call without a mov, the offset must fit a 32-bit immediate // see also CompilerToVM.getMaxCallTargetOffset() NativeCall* call = nativeCall_at((address) (inst)); - call->set_destination(VmIds::getStub(global_stub)); + call->set_destination((address) global_stub_destination); _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); } else if (inst->is_mov_literal64()) { NativeMovConstReg* mov = nativeMovConstReg_at((address) (inst)); - mov->set_data((intptr_t) VmIds::getStub(global_stub)); + mov->set_data((intptr_t) global_stub_destination); _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand); } else { NativeJump* jump = nativeJump_at((address) (inst)); - jump->set_jump_destination(VmIds::getStub(global_stub)); + jump->set_jump_destination((address) global_stub_destination); _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); } TRACE_graal_3("relocating (stub) at %p", inst);
--- a/src/share/vm/graal/graalCompiler.cpp Mon Mar 04 09:48:14 2013 +0100 +++ b/src/share/vm/graal/graalCompiler.cpp Mon Mar 04 10:00:49 2013 +0100 @@ -28,7 +28,6 @@ #include "graal/graalJavaAccess.hpp" #include "graal/graalVMToCompiler.hpp" #include "graal/graalCompilerToVM.hpp" -#include "graal/graalVmIds.hpp" #include "graal/graalEnv.hpp" #include "graal/graalRuntime.hpp" #include "runtime/arguments.hpp" @@ -188,7 +187,7 @@ } Handle GraalCompiler::get_JavaType(Symbol* klass_name, TRAPS) { - return VMToCompiler::createUnresolvedJavaType(VmIds::toString<Handle>(klass_name, THREAD), THREAD); + return VMToCompiler::createUnresolvedJavaType(java_lang_String::create_from_symbol(klass_name, THREAD), THREAD); } Handle GraalCompiler::get_JavaTypeFromSignature(Symbol* signature, KlassHandle loading_klass, TRAPS) { @@ -255,12 +254,12 @@ } Handle GraalCompiler::get_JavaType(KlassHandle klass, TRAPS) { - Handle name = VmIds::toString<Handle>(klass->name(), THREAD); + Handle name = java_lang_String::create_from_symbol(klass->name(), THREAD); return createHotSpotResolvedObjectType(klass, name, CHECK_NULL); } Handle GraalCompiler::get_JavaField(int offset, int flags, Symbol* field_name, Handle field_holder, Handle field_type, TRAPS) { - Handle name = VmIds::toString<Handle>(field_name, CHECK_NULL); + Handle name = java_lang_String::create_from_symbol(field_name, CHECK_NULL); return VMToCompiler::createJavaField(field_holder, name, field_type, offset, flags, false, CHECK_NULL); }
--- a/src/share/vm/graal/graalCompilerToVM.cpp Mon Mar 04 09:48:14 2013 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon Mar 04 10:00:49 2013 +0100 @@ -37,7 +37,6 @@ #include "graal/graalJavaAccess.hpp" #include "graal/graalCodeInstaller.hpp" #include "graal/graalVMToCompiler.hpp" -#include "graal/graalVmIds.hpp" Method* getMethodFromHotSpotMethod(oop hotspot_method) { @@ -120,7 +119,7 @@ C2V_VMENTRY(jstring, getSignature, (JNIEnv *env, jobject, jlong metaspace_method)) Method* method = asMethod(metaspace_method); assert(method != NULL && method->signature() != NULL, "signature required"); - return VmIds::toString<jstring>(method->signature(), THREAD); + return (jstring)JNIHandles::make_local(java_lang_String::create_from_symbol(method->signature(), THREAD)()); C2V_END C2V_VMENTRY(jobjectArray, initializeExceptionHandlers, (JNIEnv *, jobject, jlong metaspace_method, jobjectArray java_handlers)) @@ -271,7 +270,7 @@ C2V_VMENTRY(void, initializeMethod,(JNIEnv *, jobject, jlong metaspace_method, jobject hotspot_method)) methodHandle method = asMethod(metaspace_method); - Handle name = VmIds::toString<Handle>(method->name(), CHECK); + Handle name = java_lang_String::create_from_symbol(method->name(), CHECK); InstanceKlass::cast(HotSpotResolvedJavaMethod::klass())->initialize(CHECK); HotSpotResolvedJavaMethod::set_name(hotspot_method, name()); HotSpotResolvedJavaMethod::set_codeSize(hotspot_method, method->code_size()); @@ -323,8 +322,8 @@ C2V_VMENTRY(jobject, lookupType, (JNIEnv *env, jobject, jstring jname, jobject accessingClass, jboolean eagerResolve)) ResourceMark rm; - Symbol* nameSymbol = VmIds::toSymbol(jname); Handle name = JNIHandles::resolve(jname); + Symbol* nameSymbol = java_lang_String::as_symbol(name, THREAD); assert(nameSymbol != NULL, "name to symbol creation failed"); oop result = NULL; @@ -432,8 +431,8 @@ return JNIHandles::make_local(THREAD, VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD)); } else { // Get the method's name and signature. - Handle name = VmIds::toString<Handle>(cp->name_ref_at(index), CHECK_NULL); - Handle signature = VmIds::toString<Handle>(cp->signature_ref_at(index), CHECK_NULL); + Handle name = java_lang_String::create_from_symbol(cp->name_ref_at(index), CHECK_NULL); + Handle signature = java_lang_String::create_from_symbol(cp->signature_ref_at(index), CHECK_NULL); int holder_index = cp->klass_ref_index_at(index); Handle type = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL); return JNIHandles::make_local(THREAD, VMToCompiler::createUnresolvedJavaMethod(name, signature, type, THREAD)); @@ -514,8 +513,8 @@ assert(JNIHandles::resolve(resolved_type) != NULL, ""); Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(resolved_type)); - Symbol* name_symbol = VmIds::toSymbol(name); - Symbol* signature_symbol = VmIds::toSymbol(signature); + Symbol* name_symbol = java_lang_String::as_symbol(JNIHandles::resolve(name), THREAD); + Symbol* signature_symbol = java_lang_String::as_symbol(JNIHandles::resolve(signature), THREAD); methodHandle method = klass->lookup_method(name_symbol, signature_symbol); if (method.is_null()) { if (TraceGraal >= 3) { @@ -551,7 +550,7 @@ Handle type = GraalCompiler::get_JavaTypeFromSignature(fs.signature(), k, Thread::current()); int flags = fs.access_flags().as_int(); bool internal = fs.access_flags().is_internal(); - Handle name = VmIds::toString<Handle>(fs.name(), Thread::current()); + Handle name = java_lang_String::create_from_symbol(fs.name(), Thread::current()); Handle field = VMToCompiler::createJavaField(JNIHandles::resolve(klass), name, type, fs.offset(), flags, internal, Thread::current()); fields.append(field()); } @@ -598,6 +597,7 @@ #define set_boolean(name, value) do { env->SetBooleanField(config, getFieldID(env, config, name, "Z"), value); } while (0) #define set_int(name, value) do { env->SetIntField(config, getFieldID(env, config, name, "I"), value); } while (0) #define set_long(name, value) do { env->SetLongField(config, getFieldID(env, config, name, "J"), value); } while (0) +#define set_stub(name, value) do { set_long(name, (jlong) value); } while (0) #define set_object(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "Ljava/lang/Object;"), value); } while (0) #define set_int_array(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "[I"), value); } while (0) @@ -615,7 +615,6 @@ set_boolean("useAESIntrinsics", UseAESIntrinsics); set_boolean("useTLAB", UseTLAB); set_int("codeEntryAlignment", CodeEntryAlignment); - set_int("vmPageSize", os::vm_page_size()); set_int("stackShadowPages", StackShadowPages); set_int("hubOffset", oopDesc::klass_offset_in_bytes()); set_int("markOffset", oopDesc::mark_offset_in_bytes()); @@ -707,41 +706,41 @@ set_int("layoutHelperHeaderSizeMask", Klass::_lh_header_size_mask); set_int("layoutHelperOffset", in_bytes(Klass::layout_helper_offset())); - set_long("debugStub", VmIds::addStub((address)warning)); - set_long("instanceofStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_slow_subtype_check_id))); - set_long("newInstanceStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_instance_id))); - set_long("newArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_array_id))); - set_long("newMultiArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_multi_array_id))); - set_long("identityHashCodeStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_identity_hash_code_id))); - set_long("threadIsInterruptedStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_thread_is_interrupted_id))); - set_long("inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub())); - set_long("handleExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_handle_exception_nofpu_id))); - set_long("handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack())); - set_long("monitorEnterStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorenter_id))); - set_long("monitorExitStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorexit_id))); - set_long("verifyOopStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_verify_oop_id))); - set_long("vmErrorStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_vm_error_id))); - set_long("deoptimizeStub", VmIds::addStub(SharedRuntime::deopt_blob()->uncommon_trap())); - set_long("unwindExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_unwind_exception_call_id))); - set_long("osrMigrationEndStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_OSR_migration_end_id))); - set_long("registerFinalizerStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_register_finalizer_id))); - set_long("setDeoptInfoStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_set_deopt_info_id))); - set_long("createNullPointerExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_null_pointer_exception_id))); - set_long("createOutOfBoundsExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_out_of_bounds_exception_id))); - set_long("javaTimeMillisStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeMillis))); - set_long("javaTimeNanosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeNanos))); - set_long("arithmeticFremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_frem_id))); - set_long("arithmeticDremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_drem_id))); - set_long("arithmeticSinStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dsin))); - set_long("arithmeticCosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dcos))); - set_long("arithmeticTanStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dtan))); - set_long("logPrimitiveStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_primitive_id))); - set_long("logObjectStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_object_id))); - set_long("logPrintfStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_printf_id))); - set_long("aescryptEncryptBlockStub", VmIds::addStub(StubRoutines::aescrypt_encryptBlock())); - set_long("aescryptDecryptBlockStub", VmIds::addStub(StubRoutines::aescrypt_decryptBlock())); - set_long("cipherBlockChainingEncryptAESCryptStub", VmIds::addStub(StubRoutines::cipherBlockChaining_encryptAESCrypt())); - set_long("cipherBlockChainingDecryptAESCryptStub", VmIds::addStub(StubRoutines::cipherBlockChaining_decryptAESCrypt())); + set_stub("debugStub", (address)warning); + set_stub("instanceofStub", GraalRuntime::entry_for(GraalRuntime::slow_subtype_check_id)); + set_stub("newInstanceStub", GraalRuntime::entry_for(GraalRuntime::new_instance_id)); + set_stub("newArrayStub", GraalRuntime::entry_for(GraalRuntime::new_array_id)); + set_stub("newMultiArrayStub", GraalRuntime::entry_for(GraalRuntime::new_multi_array_id)); + set_stub("identityHashCodeStub", GraalRuntime::entry_for(GraalRuntime::identity_hash_code_id)); + set_stub("threadIsInterruptedStub", GraalRuntime::entry_for(GraalRuntime::thread_is_interrupted_id)); + set_stub("inlineCacheMissStub", SharedRuntime::get_ic_miss_stub()); + set_stub("handleExceptionStub", GraalRuntime::entry_for(GraalRuntime::handle_exception_nofpu_id)); + set_stub("handleDeoptStub", SharedRuntime::deopt_blob()->unpack()); + set_stub("monitorEnterStub", GraalRuntime::entry_for(GraalRuntime::monitorenter_id)); + set_stub("monitorExitStub", GraalRuntime::entry_for(GraalRuntime::monitorexit_id)); + set_stub("verifyOopStub", GraalRuntime::entry_for(GraalRuntime::verify_oop_id)); + set_stub("vmErrorStub", GraalRuntime::entry_for(GraalRuntime::vm_error_id)); + set_stub("deoptimizeStub", SharedRuntime::deopt_blob()->uncommon_trap()); + set_stub("unwindExceptionStub", GraalRuntime::entry_for(GraalRuntime::unwind_exception_call_id)); + set_stub("osrMigrationEndStub", GraalRuntime::entry_for(GraalRuntime::OSR_migration_end_id)); + set_stub("registerFinalizerStub", GraalRuntime::entry_for(GraalRuntime::register_finalizer_id)); + set_stub("setDeoptInfoStub", GraalRuntime::entry_for(GraalRuntime::set_deopt_info_id)); + set_stub("createNullPointerExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_null_pointer_exception_id)); + set_stub("createOutOfBoundsExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_out_of_bounds_exception_id)); + set_stub("javaTimeMillisStub", CAST_FROM_FN_PTR(address, os::javaTimeMillis)); + set_stub("javaTimeNanosStub", CAST_FROM_FN_PTR(address, os::javaTimeNanos)); + set_stub("arithmeticFremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_frem_id)); + set_stub("arithmeticDremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_drem_id)); + set_stub("arithmeticSinStub", CAST_FROM_FN_PTR(address, SharedRuntime::dsin)); + set_stub("arithmeticCosStub", CAST_FROM_FN_PTR(address, SharedRuntime::dcos)); + set_stub("arithmeticTanStub", CAST_FROM_FN_PTR(address, SharedRuntime::dtan)); + set_stub("logPrimitiveStub", GraalRuntime::entry_for(GraalRuntime::log_primitive_id)); + set_stub("logObjectStub", GraalRuntime::entry_for(GraalRuntime::log_object_id)); + set_stub("logPrintfStub", GraalRuntime::entry_for(GraalRuntime::log_printf_id)); + set_stub("aescryptEncryptBlockStub", StubRoutines::aescrypt_encryptBlock()); + set_stub("aescryptDecryptBlockStub", StubRoutines::aescrypt_decryptBlock()); + set_stub("cipherBlockChainingEncryptAESCryptStub", StubRoutines::cipherBlockChaining_encryptAESCrypt()); + set_stub("cipherBlockChainingDecryptAESCryptStub", StubRoutines::cipherBlockChaining_decryptAESCrypt()); set_int("deoptReasonNone", Deoptimization::Reason_none); set_int("deoptReasonNullCheck", Deoptimization::Reason_null_check);
--- a/src/share/vm/graal/graalJavaAccess.hpp Mon Mar 04 09:48:14 2013 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Mon Mar 04 10:00:49 2013 +0100 @@ -88,6 +88,9 @@ oop_field(HotSpotCompilationResult, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;") \ oop_field(HotSpotCompilationResult, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;") \ end_class \ + start_class(HotSpotRuntimeCallTarget) \ + long_field(HotSpotRuntimeCallTarget, address) \ + end_class \ start_class(ExceptionHandler) \ int_field(ExceptionHandler, startBCI) \ int_field(ExceptionHandler, endBCI) \ @@ -122,7 +125,7 @@ int_field(CompilationResult_Site, pcOffset) \ end_class \ start_class(CompilationResult_Call) \ - oop_field(CompilationResult_Call, target, "Ljava/lang/Object;") \ + oop_field(CompilationResult_Call, target, "Lcom/oracle/graal/api/meta/InvokeTarget;") \ oop_field(CompilationResult_Call, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;") \ end_class \ start_class(CompilationResult_DataPatch) \
--- a/src/share/vm/graal/graalRuntime.cpp Mon Mar 04 09:48:14 2013 +0100 +++ b/src/share/vm/graal/graalRuntime.cpp Mon Mar 04 10:00:49 2013 +0100 @@ -127,16 +127,16 @@ // Make sure that stubs that need oopmaps have them switch (id) { // These stubs don't need to have an oopmap - case graal_slow_subtype_check_id: + case slow_subtype_check_id: #if defined(SPARC) || defined(PPC) - case graal_handle_exception_nofpu_id: // Unused on sparc + case handle_exception_nofpu_id: // Unused on sparc #endif - case graal_verify_oop_id: - case graal_unwind_exception_call_id: - case graal_OSR_migration_end_id: - case graal_arithmetic_frem_id: - case graal_arithmetic_drem_id: - case graal_set_deopt_info_id: + case verify_oop_id: + case unwind_exception_call_id: + case OSR_migration_end_id: + case arithmetic_frem_id: + case arithmetic_drem_id: + case set_deopt_info_id: break; // All other stubs should have oopmaps @@ -442,17 +442,17 @@ return continuation; } -JRT_ENTRY(void, GraalRuntime::graal_create_null_exception(JavaThread* thread)) +JRT_ENTRY(void, GraalRuntime::create_null_exception(JavaThread* thread)) thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_NullPointerException(), NULL)()); JRT_END -JRT_ENTRY(void, GraalRuntime::graal_create_out_of_bounds_exception(JavaThread* thread, jint index)) +JRT_ENTRY(void, GraalRuntime::create_out_of_bounds_exception(JavaThread* thread, jint index)) char message[jintAsStringSize]; sprintf(message, "%d", index); thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message)()); JRT_END -JRT_ENTRY_NO_ASYNC(void, GraalRuntime::graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock)) +JRT_ENTRY_NO_ASYNC(void, GraalRuntime::monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock)) if (TraceGraal >= 3) { char type[O_BUFLEN]; obj->klass()->name()->as_C_string(type, O_BUFLEN); @@ -484,7 +484,7 @@ JRT_END -JRT_LEAF(void, GraalRuntime::graal_monitorexit(JavaThread* thread, oopDesc* obj, BasicLock* lock)) +JRT_LEAF(void, GraalRuntime::monitorexit(JavaThread* thread, oopDesc* obj, BasicLock* lock)) assert(thread == JavaThread::current(), "threads must correspond"); assert(thread->last_Java_sp(), "last_Java_sp must be set"); // monitorexit is non-blocking (leaf routine) => no exceptions can be thrown @@ -516,7 +516,7 @@ } JRT_END -JRT_ENTRY(void, GraalRuntime::graal_log_object(JavaThread* thread, oop obj, jint flags)) +JRT_ENTRY(void, GraalRuntime::log_object(JavaThread* thread, oop obj, jint flags)) bool string = mask_bits_are_true(flags, LOG_OBJECT_STRING); bool address = mask_bits_are_true(flags, LOG_OBJECT_ADDRESS); bool newline = mask_bits_are_true(flags, LOG_OBJECT_NEWLINE); @@ -538,7 +538,7 @@ } JRT_END -JRT_ENTRY(void, GraalRuntime::graal_vm_error(JavaThread* thread, oop where, oop format, jlong value)) +JRT_ENTRY(void, GraalRuntime::vm_error(JavaThread* thread, oop where, oop format, jlong value)) ResourceMark rm; assert(where == NULL || java_lang_String::is_instance(where), "must be"); const char *error_msg = where == NULL ? "<internal Graal error>" : java_lang_String::as_utf8_string(where); @@ -552,14 +552,14 @@ report_vm_error(__FILE__, __LINE__, error_msg, detail_msg); JRT_END -JRT_ENTRY(void, GraalRuntime::graal_log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3)) +JRT_ENTRY(void, GraalRuntime::log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3)) ResourceMark rm; assert(format != NULL && java_lang_String::is_instance(format), "must be"); char *buf = java_lang_String::as_utf8_string(format); tty->print(buf, v1, v2, v3); JRT_END -JRT_ENTRY(void, GraalRuntime::graal_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline)) +JRT_ENTRY(void, GraalRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline)) union { jlong l; jdouble d; @@ -582,11 +582,11 @@ } JRT_END -JRT_ENTRY(jint, GraalRuntime::graal_identity_hash_code(JavaThread* thread, oop obj)) +JRT_ENTRY(jint, GraalRuntime::identity_hash_code(JavaThread* thread, oop obj)) return (jint) obj->identity_hash(); JRT_END -JRT_ENTRY(jboolean, GraalRuntime::graal_thread_is_interrupted(JavaThread* thread, oop receiver, jboolean clear_interrupted)) +JRT_ENTRY(jboolean, GraalRuntime::thread_is_interrupted(JavaThread* thread, oop receiver, jboolean clear_interrupted)) // Ensure that the C++ Thread and OSThread structures aren't freed before we operate Handle receiverHandle(thread, receiver); MutexLockerEx ml(thread->threadObj() == receiver ? NULL : Threads_lock);
--- a/src/share/vm/graal/graalRuntime.hpp Mon Mar 04 09:48:14 2013 +0100 +++ b/src/share/vm/graal/graalRuntime.hpp Mon Mar 04 10:00:49 2013 +0100 @@ -81,28 +81,28 @@ // runtime routines needed by code code generated // by Graal. #define GRAAL_STUBS(stub, last_entry) \ - stub(graal_register_finalizer) \ - stub(graal_new_instance) \ - stub(graal_new_array) \ - stub(graal_new_multi_array) \ - stub(graal_handle_exception_nofpu) /* optimized version that does not preserve fpu registers */ \ - stub(graal_slow_subtype_check) \ - stub(graal_unwind_exception_call) \ - stub(graal_OSR_migration_end) \ - stub(graal_arithmetic_frem) \ - stub(graal_arithmetic_drem) \ - stub(graal_monitorenter) \ - stub(graal_monitorexit) \ - stub(graal_verify_oop) \ - stub(graal_vm_error) \ - stub(graal_set_deopt_info) \ - stub(graal_create_null_pointer_exception) \ - stub(graal_create_out_of_bounds_exception) \ - stub(graal_log_object) \ - stub(graal_log_printf) \ - stub(graal_log_primitive) \ - stub(graal_identity_hash_code) \ - stub(graal_thread_is_interrupted) \ + stub(register_finalizer) \ + stub(new_instance) \ + stub(new_array) \ + stub(new_multi_array) \ + stub(handle_exception_nofpu) /* optimized version that does not preserve fpu registers */ \ + stub(slow_subtype_check) \ + stub(unwind_exception_call) \ + stub(OSR_migration_end) \ + stub(arithmetic_frem) \ + stub(arithmetic_drem) \ + stub(monitorenter) \ + stub(monitorexit) \ + stub(verify_oop) \ + stub(vm_error) \ + stub(set_deopt_info) \ + stub(create_null_pointer_exception) \ + stub(create_out_of_bounds_exception) \ + stub(log_object) \ + stub(log_printf) \ + stub(log_primitive) \ + stub(identity_hash_code) \ + stub(thread_is_interrupted) \ last_entry(number_of_ids) #define DECLARE_STUB_ID(x) x ## _id , @@ -140,16 +140,16 @@ static address exception_handler_for_pc(JavaThread* thread); - static void graal_create_null_exception(JavaThread* thread); - static void graal_create_out_of_bounds_exception(JavaThread* thread, jint index); - static void graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock); - static void graal_monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock); - static void graal_vm_error(JavaThread* thread, oop where, oop format, jlong value); - static void graal_log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3); - static void graal_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline); + static void create_null_exception(JavaThread* thread); + static void create_out_of_bounds_exception(JavaThread* thread, jint index); + static void monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock); + static void monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock); + static void vm_error(JavaThread* thread, oop where, oop format, jlong value); + static void log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3); + static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline); - static jint graal_identity_hash_code(JavaThread* thread, oopDesc* objd); - static jboolean graal_thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupte); + static jint identity_hash_code(JavaThread* thread, oopDesc* objd); + static jboolean thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupte); // Note: Must be kept in sync with constants in com.oracle.graal.snippets.Log enum { @@ -157,7 +157,7 @@ LOG_OBJECT_STRING = 0x02, LOG_OBJECT_ADDRESS = 0x04 }; - static void graal_log_object(JavaThread* thread, oop msg, jint flags); + static void log_object(JavaThread* thread, oop msg, jint flags); public: // initialization
--- a/src/share/vm/graal/graalVmIds.cpp Mon Mar 04 09:48:14 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +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. - */ - -#include "precompiled.hpp" -#include "graal/graalVmIds.hpp" -#include "ci/ciUtilities.hpp" - -// VmIds implementation - -jlong VmIds::addStub(address stub) { - return (jlong)stub; -} - -address VmIds::getStub(jlong id) { - return (address)id; -} -
--- a/src/share/vm/graal/graalVmIds.hpp Mon Mar 04 09:48:14 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +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. - */ - -#ifndef SHARE_VM_GRAAL_GRAAL_VM_IDS_HPP -#define SHARE_VM_GRAAL_GRAAL_VM_IDS_HPP - -#include "memory/allocation.hpp" -#include "utilities/growableArray.hpp" -#include "oops/oop.hpp" -#include "runtime/handles.hpp" -#include "runtime/thread.hpp" -#include "classfile/javaClasses.hpp" -#include "runtime/jniHandles.hpp" - -class VmIds : public AllStatic { - -public: - // Adds a stub address, and returns the corresponding vmId (which is of type STUB) - static jlong addStub(address stub); - - // Returns the stub address with the given vmId - static address getStub(jlong id); - - // Returns the stub address with the given vmId taken from a java.lang.Long - static address getStub(oop id); - - // Helper function to convert a symbol to a java.lang.String object - template <typename T> static T toString(Symbol* symbol, TRAPS); - - // Helper function to convert a java.lang.String object to a symbol (this will return NULL if the symbol doesn't exist in the system) - static Symbol* toSymbol(jstring string); - - // Helper function to get the contents of a java.lang.Long - static jlong getBoxedLong(oop obj); -}; - -inline address VmIds::getStub(oop obj) { - return getStub(getBoxedLong(obj)); -} - -template <> inline Handle VmIds::toString<Handle>(Symbol* symbol, TRAPS) { - return java_lang_String::create_from_symbol(symbol, THREAD); -} - -template <> inline oop VmIds::toString<oop>(Symbol* symbol, TRAPS) { - return toString<Handle>(symbol, THREAD)(); -} - -template <> inline jstring VmIds::toString<jstring>(Symbol* symbol, TRAPS) { - return (jstring)JNIHandles::make_local(toString<oop>(symbol, THREAD)); -} - -template <> inline jobject VmIds::toString<jobject>(Symbol* symbol, TRAPS) { - return JNIHandles::make_local(toString<oop>(symbol, THREAD)); -} - -inline Symbol* VmIds::toSymbol(jstring string) { - return java_lang_String::as_symbol(JNIHandles::resolve(string), Thread::current()); -} - -inline jlong VmIds::getBoxedLong(oop obj) { - assert(obj->is_oop(true), "cannot unbox null or non-oop"); - return obj->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG)); -} - -#endif // SHARE_VM_GRAAL_GRAAL_VM_IDS_HPP
--- a/src/share/vm/runtime/globals.hpp Mon Mar 04 09:48:14 2013 +0100 +++ b/src/share/vm/runtime/globals.hpp Mon Mar 04 10:00:49 2013 +0100 @@ -3588,7 +3588,7 @@ product(uintx, SharedDummyBlockSize, 0, \ "Size of dummy block used to shift heap addresses (in bytes)") \ \ - diagnostic(bool, EnableInvokeDynamic, false, \ + diagnostic(bool, EnableInvokeDynamic, true, \ "support JSR 292 (method handles, invokedynamic, " \ "anonymous classes") \ \