Mercurial > hg > graal-compiler
changeset 14062:09d41e2f8dc7
Merge.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Fri, 28 Feb 2014 16:19:10 +0100 |
parents | a3cd3403a958 (current diff) 692452c4cfb6 (diff) |
children | 60637fc3fa8c |
files | graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/GraphKit.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java |
diffstat | 109 files changed, 1788 insertions(+), 1304 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java Fri Feb 28 16:19:10 2014 +0100 @@ -30,7 +30,6 @@ import com.oracle.graal.api.code.CompilationResult.ConstantData; import com.oracle.graal.api.code.CompilationResult.RawData; import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.Buffer; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.asm.test.*; @@ -41,12 +40,12 @@ CodeGenTest test = new CodeGenTest() { @Override - public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { + public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { AMD64Assembler asm = new AMD64Assembler(target, registerConfig); Register ret = registerConfig.getReturnRegister(Kind.Int); asm.movl(ret, 8472); asm.ret(0); - return asm.codeBuffer; + return asm.close(true); } }; assertReturn("intStub", test, 8472); @@ -57,13 +56,13 @@ CodeGenTest test = new CodeGenTest() { @Override - public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { + public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig); Register ret = registerConfig.getReturnRegister(Kind.Double); - compResult.recordDataReference(asm.codeBuffer.position(), new ConstantData(Constant.forDouble(84.72), 8)); + compResult.recordDataReference(asm.position(), new ConstantData(Constant.forDouble(84.72), 8)); asm.movdbl(ret, asm.getPlaceholder()); asm.ret(0); - return asm.codeBuffer; + return asm.close(true); } }; assertReturn("doubleStub", test, 84.72); @@ -74,16 +73,16 @@ CodeGenTest test = new CodeGenTest() { @Override - public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { + public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig); Register ret = registerConfig.getReturnRegister(Kind.Double); byte[] rawBytes = new byte[8]; ByteBuffer.wrap(rawBytes).order(ByteOrder.nativeOrder()).putDouble(84.72); - compResult.recordDataReference(asm.codeBuffer.position(), new RawData(rawBytes, 8)); + compResult.recordDataReference(asm.position(), new RawData(rawBytes, 8)); asm.movdbl(ret, asm.getPlaceholder()); asm.ret(0); - return asm.codeBuffer; + return asm.close(true); } }; assertReturn("doubleStub", test, 84.72);
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Fri Feb 28 16:19:10 2014 +0100 @@ -34,7 +34,7 @@ /** * This class implements an assembler that can encode most X86 instructions. */ -public class AMD64Assembler extends AbstractAssembler { +public class AMD64Assembler extends Assembler { private static final int MinEncodingNeedsRex = 8; @@ -746,7 +746,7 @@ public void jcc(ConditionFlag cc, int jumpTarget, boolean forceDisp32) { int shortSize = 2; int longSize = 6; - long disp = jumpTarget - codeBuffer.position(); + long disp = jumpTarget - position(); if (!forceDisp32 && isByte(disp - shortSize)) { // 0111 tttn #8-bit disp emitByte(0x70 | cc.getValue()); @@ -769,7 +769,7 @@ // is the same however, seems to be rather unlikely case. // Note: use jccb() if label to be bound is very close to get // an 8-bit displacement - l.addPatchAt(codeBuffer.position()); + l.addPatchAt(position()); emitByte(0x0F); emitByte(0x80 | cc.getValue()); emitInt(0); @@ -781,13 +781,13 @@ if (l.isBound()) { int shortSize = 2; int entry = l.position(); - assert isByte(entry - (codeBuffer.position() + shortSize)) : "Dispacement too large for a short jmp"; - long disp = entry - codeBuffer.position(); + assert isByte(entry - (position() + shortSize)) : "Dispacement too large for a short jmp"; + long disp = entry - position(); // 0111 tttn #8-bit disp emitByte(0x70 | cc.getValue()); emitByte((int) ((disp - shortSize) & 0xFF)); } else { - l.addPatchAt(codeBuffer.position()); + l.addPatchAt(position()); emitByte(0x70 | cc.getValue()); emitByte(0); } @@ -796,7 +796,7 @@ public final void jmp(int jumpTarget, boolean forceDisp32) { int shortSize = 2; int longSize = 5; - long disp = jumpTarget - codeBuffer.position(); + long disp = jumpTarget - position(); if (!forceDisp32 && isByte(disp - shortSize)) { emitByte(0xEB); emitByte((int) ((disp - shortSize) & 0xFF)); @@ -816,7 +816,7 @@ // the forward jump will not run beyond 256 bytes, use jmpb to // force an 8-bit displacement. - l.addPatchAt(codeBuffer.position()); + l.addPatchAt(position()); emitByte(0xE9); emitInt(0); } @@ -832,13 +832,13 @@ if (l.isBound()) { int shortSize = 2; int entry = l.position(); - assert isByte((entry - codeBuffer.position()) + shortSize) : "Dispacement too large for a short jmp"; - long offs = entry - codeBuffer.position(); + assert isByte((entry - position()) + shortSize) : "Dispacement too large for a short jmp"; + long offs = entry - position(); emitByte(0xEB); emitByte((int) ((offs - shortSize) & 0xFF)); } else { - l.addPatchAt(codeBuffer.position()); + l.addPatchAt(position()); emitByte(0xEB); emitByte(0); } @@ -2446,21 +2446,21 @@ @Override protected final void patchJumpTarget(int branch, int branchTarget) { - int op = codeBuffer.getByte(branch); + int op = getByte(branch); assert op == 0xE8 // call || op == 0x00 // jump table entry || op == 0xE9 // jmp || op == 0xEB // short jmp || (op & 0xF0) == 0x70 // short jcc - || op == 0x0F && (codeBuffer.getByte(branch + 1) & 0xF0) == 0x80 // jcc + || op == 0x0F && (getByte(branch + 1) & 0xF0) == 0x80 // jcc : "Invalid opcode at patch point branch=" + branch + ", branchTarget=" + branchTarget + ", op=" + op; if (op == 0x00) { - int offsetToJumpTableBase = codeBuffer.getShort(branch + 1); + int offsetToJumpTableBase = getShort(branch + 1); int jumpTableBase = branch - offsetToJumpTableBase; int imm32 = branchTarget - jumpTableBase; - codeBuffer.emitInt(imm32, branch); + emitInt(imm32, branch); } else if (op == 0xEB || (op & 0xF0) == 0x70) { // short offset operators (jmp and jcc) @@ -2472,7 +2472,7 @@ if (!NumUtil.isByte(imm8)) { throw new InternalError("branch displacement out of range: " + imm8); } - codeBuffer.emitByte(imm8, branch + 1); + emitByte(imm8, branch + 1); } else { @@ -2482,7 +2482,7 @@ } int imm32 = branchTarget - (branch + 4 + off); - codeBuffer.emitInt(imm32, branch + off); + emitInt(imm32, branch + off); } } @@ -2492,8 +2492,8 @@ @Override public void align(int modulus) { - if (codeBuffer.position() % modulus != 0) { - nop(modulus - (codeBuffer.position() % modulus)); + if (position() % modulus != 0) { + nop(modulus - (position() % modulus)); } }
--- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/AbstractHSAILAssembler.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/AbstractHSAILAssembler.java Fri Feb 28 16:19:10 2014 +0100 @@ -28,7 +28,7 @@ /** * The platform-dependent base class for the HSAIL assembler. */ -public abstract class AbstractHSAILAssembler extends AbstractAssembler { +public abstract class AbstractHSAILAssembler extends Assembler { public AbstractHSAILAssembler(TargetDescription target) { super(target);
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/AbstractPTXAssembler.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/AbstractPTXAssembler.java Fri Feb 28 16:19:10 2014 +0100 @@ -28,7 +28,7 @@ /** * The platform-dependent base class for the PTX assembler. */ -public abstract class AbstractPTXAssembler extends AbstractAssembler { +public abstract class AbstractPTXAssembler extends Assembler { public AbstractPTXAssembler(TargetDescription target) { super(target);
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Fri Feb 28 16:19:10 2014 +0100 @@ -33,7 +33,7 @@ /** * This class implements an assembler that can encode most SPARC instructions. */ -public abstract class SPARCAssembler extends AbstractAssembler { +public abstract class SPARCAssembler extends Assembler { /** * Constructs an assembler for the SPARC architecture. @@ -89,7 +89,7 @@ } public static Fmt00a read(SPARCAssembler masm, int pos) { - final int inst = masm.codeBuffer.getInt(pos); + final int inst = masm.getInt(pos); // Make sure it's the right instruction: final int op = (inst & OP_MASK) >> OP_SHIFT; @@ -105,7 +105,7 @@ public void write(SPARCAssembler masm, int pos) { verify(); - masm.codeBuffer.emitInt(getInstructionBits(), pos); + masm.emitInt(getInstructionBits(), pos); } public void emit(SPARCAssembler masm) { @@ -253,7 +253,7 @@ } public static Fmt00c read(SPARCAssembler masm, int pos) { - final int inst = masm.codeBuffer.getInt(pos); + final int inst = masm.getInt(pos); // Make sure it's the right instruction: final int op = (inst & OP_MASK) >> OP_SHIFT; @@ -274,13 +274,13 @@ public void write(SPARCAssembler masm, int pos) { verify(); - masm.codeBuffer.emitInt(getInstructionBits(), pos); + masm.emitInt(getInstructionBits(), pos); } public void emit(SPARCAssembler masm) { if (label != null) { final int pos = label.isBound() ? label.position() : patchUnbound(masm, label); - final int disp = pos - masm.codeBuffer.position(); + final int disp = pos - masm.position(); setDisp19(disp); } verify(); @@ -288,7 +288,7 @@ } private static int patchUnbound(SPARCAssembler masm, Label label) { - label.addPatchAt(masm.codeBuffer.position()); + label.addPatchAt(masm.position()); return 0; } @@ -370,7 +370,7 @@ } public static Fmt01 read(SPARCAssembler masm, int pos) { - final int inst = masm.codeBuffer.getInt(pos); + final int inst = masm.getInt(pos); // Make sure it's the right instruction: final int op = (inst & OP_MASK) >> OP_SHIFT; @@ -386,7 +386,7 @@ public void write(SPARCAssembler masm, int pos) { verify(); - masm.codeBuffer.emitInt(getInstructionBits(), pos); + masm.emitInt(getInstructionBits(), pos); } public void emit(SPARCAssembler masm) { @@ -550,7 +550,7 @@ } public static Fmt10 read(SPARCAssembler masm, int pos) { - final int inst = masm.codeBuffer.getInt(pos); + final int inst = masm.getInt(pos); // Make sure it's the right instruction: final int op = (inst & OP_MASK) >> OP_SHIFT; @@ -571,7 +571,7 @@ public void write(SPARCAssembler masm, int pos) { verify(); - masm.codeBuffer.emitInt(getInstructionBits(), pos); + masm.emitInt(getInstructionBits(), pos); } public void emit(SPARCAssembler masm) { @@ -696,7 +696,7 @@ } public static Fmt11 read(SPARCAssembler masm, int pos) { - final int inst = masm.codeBuffer.getInt(pos); + final int inst = masm.getInt(pos); // Make sure it's the right instruction: final int op = (inst & OP_MASK) >> OP_SHIFT; @@ -716,7 +716,7 @@ public void write(SPARCAssembler masm, int pos) { verify(); - masm.codeBuffer.emitInt(getInstructionBits(), pos); + masm.emitInt(getInstructionBits(), pos); } public void emit(SPARCAssembler masm) { @@ -832,7 +832,7 @@ } public static Fmt10c read(SPARCAssembler masm, int pos) { - final int inst = masm.codeBuffer.getInt(pos); + final int inst = masm.getInt(pos); // Make sure it's the right instruction: final int op = (inst & OP_MASK) >> OP_SHIFT; @@ -852,7 +852,7 @@ public void write(SPARCAssembler masm, int pos) { verify(); - masm.codeBuffer.emitInt(getInstructionBits(), pos); + masm.emitInt(getInstructionBits(), pos); } public void emit(SPARCAssembler masm) {
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java Fri Feb 28 16:19:10 2014 +0100 @@ -42,8 +42,8 @@ @Override public void align(int modulus) { - if (codeBuffer.position() % modulus != 0) { - final int count = modulus - (codeBuffer.position() % modulus); + if (position() % modulus != 0) { + final int count = modulus - (position() % modulus); for (int i = 0; i < count; i++) { new Nop().emit(this); } @@ -364,7 +364,7 @@ int lo = (int) (value & ~0); // This is the same logic as MacroAssembler::internal_set. - final int startPc = masm.codeBuffer.position(); + final int startPc = masm.position(); if (hi == 0 && lo >= 0) { new Sethi(hi22(lo), dst).emit(masm); @@ -399,7 +399,7 @@ } // Pad out the instruction sequence so it can be patched later. if (forceRelocatable) { - while (masm.codeBuffer.position() < (startPc + (INSTRUCTION_SIZE * 4))) { + while (masm.position() < (startPc + (INSTRUCTION_SIZE * 4))) { new Nop().emit(masm); } }
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Fri Feb 28 16:19:10 2014 +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.asm.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.runtime.*; import com.oracle.graal.test.*; @@ -40,8 +39,7 @@ protected final CodeCacheProvider codeCache; public interface CodeGenTest { - - Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc); + byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc); } public AssemblerTest() { @@ -60,8 +58,8 @@ CallingConvention cc = CodeUtil.getCallingConvention(codeCache, CallingConvention.Type.JavaCallee, method, false); CompilationResult compResult = new CompilationResult(); - Buffer codeBuffer = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); - compResult.setTargetCode(codeBuffer.close(true), codeBuffer.position()); + byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); + compResult.setTargetCode(targetCode, targetCode.length); InstalledCode code = codeCache.addMethod(method, compResult, null);
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java Wed Feb 26 13:09:16 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.asm; - -import java.nio.*; -import java.util.*; - -import com.oracle.graal.api.code.*; - -/** - * The platform-independent base class for the assembler. - */ -public abstract class AbstractAssembler { - - public final TargetDescription target; - public final Buffer codeBuffer; - - public AbstractAssembler(TargetDescription target) { - this.target = target; - - if (target.arch.getByteOrder() == ByteOrder.BIG_ENDIAN) { - this.codeBuffer = new Buffer.BigEndian(); - } else { - this.codeBuffer = new Buffer.LittleEndian(); - } - } - - public void bind(Label l) { - assert !l.isBound() : "can bind label only once"; - l.bind(codeBuffer.position()); - l.patchInstructions(this); - } - - public abstract void align(int modulus); - - public abstract void jmp(Label l); - - protected abstract void patchJumpTarget(int branch, int jumpTarget); - - private Map<Label, String> nameMap; - - /** - * Creates a name for a label. - * - * @param l the label for which a name is being created - * @param id a label identifier that is unique with the scope of this assembler - * @return a label name in the form of "L123" - */ - protected String createLabelName(Label l, int id) { - return "L" + id; - } - - /** - * Gets a name for a label, creating it if it does not yet exist. By default, the returned name - * is only unique with the scope of this assembler. - */ - public String nameOf(Label l) { - if (nameMap == null) { - nameMap = new HashMap<>(); - } - String name = nameMap.get(l); - if (name == null) { - name = createLabelName(l, nameMap.size()); - nameMap.put(l, name); - } - return name; - } - - protected final void emitByte(int x) { - codeBuffer.emitByte(x); - } - - protected final void emitShort(int x) { - codeBuffer.emitShort(x); - } - - protected final void emitInt(int x) { - codeBuffer.emitInt(x); - } - - 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 CompilationResultBuilder to convert a {@link StackSlot} to an - * {@link AbstractAddress}. - */ - public abstract AbstractAddress makeAddress(Register base, int displacement); - - /** - * Returns a target specific placeholder address that can be used for code patching. - */ - public abstract AbstractAddress getPlaceholder(); -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Assembler.java Fri Feb 28 16:19:10 2014 +0100 @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.asm; + +import java.nio.*; +import java.util.*; + +import com.oracle.graal.api.code.*; + +/** + * The platform-independent base class for the assembler. + */ +public abstract class Assembler { + + public final TargetDescription target; + + /** + * Backing code buffer. + */ + private final Buffer codeBuffer; + + public Assembler(TargetDescription target) { + this.target = target; + if (target.arch.getByteOrder() == ByteOrder.BIG_ENDIAN) { + this.codeBuffer = new Buffer.BigEndian(); + } else { + this.codeBuffer = new Buffer.LittleEndian(); + } + } + + /** + * Returns the current position of the underlying code buffer. + * + * @return current position in code buffer + */ + public int position() { + return codeBuffer.position(); + } + + public final void emitByte(int x) { + codeBuffer.emitByte(x); + } + + public final void emitShort(int x) { + codeBuffer.emitShort(x); + } + + public final void emitInt(int x) { + codeBuffer.emitInt(x); + } + + public final void emitLong(long x) { + codeBuffer.emitLong(x); + } + + public final void emitByte(int b, int pos) { + codeBuffer.emitByte(b, pos); + } + + public final void emitShort(int b, int pos) { + codeBuffer.emitShort(b, pos); + } + + public final void emitInt(int b, int pos) { + codeBuffer.emitInt(b, pos); + } + + public final void emitLong(long b, int pos) { + codeBuffer.emitLong(b, pos); + } + + public final int getByte(int pos) { + return codeBuffer.getByte(pos); + } + + public final int getShort(int pos) { + return codeBuffer.getShort(pos); + } + + public final int getInt(int pos) { + return codeBuffer.getInt(pos); + } + + private static final String NEWLINE = System.getProperty("line.separator"); + + /** + * Some GPU architectures have a text based encoding. + */ + public final void emitString(String x) { + emitString0("\t"); // XXX REMOVE ME pretty-printing + emitString0(x); + emitString0(NEWLINE); + } + + // XXX for pretty-printing + public final void emitString0(String x) { + codeBuffer.emitBytes(x.getBytes(), 0, x.length()); + } + + public void emitString(String s, int pos) { + codeBuffer.emitBytes(s.getBytes(), pos); + } + + /** + * Closes this assembler. No extra data can be written to this assembler after this call. + * + * @param trimmedCopy if {@code true}, then a copy of the underlying byte array up to (but not + * including) {@code position()} is returned + * @return the data in this buffer or a trimmed copy if {@code trimmedCopy} is {@code true} + */ + public byte[] close(boolean trimmedCopy) { + return codeBuffer.close(trimmedCopy); + } + + public void bind(Label l) { + assert !l.isBound() : "can bind label only once"; + l.bind(position()); + l.patchInstructions(this); + } + + public abstract void align(int modulus); + + public abstract void jmp(Label l); + + protected abstract void patchJumpTarget(int branch, int jumpTarget); + + private Map<Label, String> nameMap; + + /** + * Creates a name for a label. + * + * @param l the label for which a name is being created + * @param id a label identifier that is unique with the scope of this assembler + * @return a label name in the form of "L123" + */ + protected String createLabelName(Label l, int id) { + return "L" + id; + } + + /** + * Gets a name for a label, creating it if it does not yet exist. By default, the returned name + * is only unique with the scope of this assembler. + */ + public String nameOf(Label l) { + if (nameMap == null) { + nameMap = new HashMap<>(); + } + String name = nameMap.get(l); + if (name == null) { + name = createLabelName(l, nameMap.size()); + nameMap.put(l, name); + } + return name; + } + + /** + * This is used by the CompilationResultBuilder to convert a {@link StackSlot} to an + * {@link AbstractAddress}. + */ + public abstract AbstractAddress makeAddress(Register base, int displacement); + + /** + * Returns a target specific placeholder address that can be used for code patching. + */ + public abstract AbstractAddress getPlaceholder(); +}
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java Fri Feb 28 16:19:10 2014 +0100 @@ -28,7 +28,7 @@ * Code buffer management for the assembler. Support for little endian and big endian architectures * is implemented using subclasses. */ -public abstract class Buffer { +abstract class Buffer { protected byte[] data; protected int position; @@ -105,19 +105,6 @@ 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; @@ -140,10 +127,6 @@ 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.asm/src/com/oracle/graal/asm/Label.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Label.java Fri Feb 28 16:19:10 2014 +0100 @@ -34,8 +34,7 @@ /** * References to instructions that jump to this unresolved label. These instructions need to be - * patched when the label is bound using the {@link #patchInstructions(AbstractAssembler)} - * method. + * patched when the label is bound using the {@link #patchInstructions(Assembler)} method. */ private ArrayList<Integer> patchPositions = null; @@ -82,7 +81,7 @@ patchPositions.add(branchLocation); } - protected void patchInstructions(AbstractAssembler masm) { + protected void patchInstructions(Assembler masm) { assert isBound() : "Label should be bound"; if (patchPositions != null) { int target = position;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Fri Feb 28 16:19:10 2014 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.schedule.*; @@ -278,7 +279,7 @@ @SuppressWarnings("unused") public static void testNewNodeSnippet() { - new IntegerAddNode(Kind.Int, null, null); + new IntegerAddNode(new IntegerStamp(32, false, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0xFFFFFFFF), null, null); } /**
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Fri Feb 28 16:19:10 2014 +0100 @@ -70,7 +70,7 @@ /** * Creates the assembler used to emit the machine code. */ - protected abstract AbstractAssembler createAssembler(FrameMap frameMap); + protected abstract Assembler createAssembler(FrameMap frameMap); /** * Creates the object used to fill in the details of a given compilation result.
--- a/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java Fri Feb 28 16:19:10 2014 +0100 @@ -111,7 +111,7 @@ AMD64Assembler asm = new AMD64Assembler(target, registerConfig); gen.generateCode(asm); - byte[] expectedCode = asm.codeBuffer.close(true); + byte[] expectedCode = asm.close(true); // Only compare up to expectedCode.length bytes to ignore // padding instructions adding during code installation
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Feb 28 16:19:10 2014 +0100 @@ -98,9 +98,9 @@ disp -= frameSize; } crb.blockComment("[stack overflow check]"); - int pos = asm.codeBuffer.position(); + int pos = asm.position(); asm.movq(new AMD64Address(rsp, -disp), AMD64.rax); - assert i > 0 || !isVerifiedEntryPoint || asm.codeBuffer.position() - pos >= PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE; + assert i > 0 || !isVerifiedEntryPoint || asm.position() - pos >= PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE; } } } @@ -141,14 +141,14 @@ asm.nop(PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE); } } else { - int verifiedEntryPointOffset = asm.codeBuffer.position(); + int verifiedEntryPointOffset = asm.position(); if (!isStub && pagesToBang > 0) { emitStackOverflowCheck(crb, pagesToBang, false, true); - assert asm.codeBuffer.position() - verifiedEntryPointOffset >= PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE; + assert asm.position() - verifiedEntryPointOffset >= PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE; } - if (!isStub && asm.codeBuffer.position() == verifiedEntryPointOffset) { + if (!isStub && asm.position() == verifiedEntryPointOffset) { asm.subqWide(rsp, frameSize); - assert asm.codeBuffer.position() - verifiedEntryPointOffset >= PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE; + assert asm.position() - verifiedEntryPointOffset >= PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE; } else { asm.decrementq(rsp, frameSize); } @@ -174,7 +174,7 @@ CalleeSaveLayout csl = crb.frameMap.registerConfig.getCalleeSaveLayout(); if (csl != null && csl.size != 0) { - crb.compilationResult.setRegisterRestoreEpilogueOffset(asm.codeBuffer.position()); + crb.compilationResult.setRegisterRestoreEpilogueOffset(asm.position()); // saved all registers, restore all registers int frameToCSA = crb.frameMap.offsetToCalleeSaveArea(); asm.restore(csl, frameToCSA); @@ -187,7 +187,7 @@ } @Override - protected AbstractAssembler createAssembler(FrameMap frameMap) { + protected Assembler createAssembler(FrameMap frameMap) { return new AMD64MacroAssembler(getTarget(), frameMap.registerConfig); } @@ -206,7 +206,7 @@ boolean omitFrame = CanOmitFrame.getValue() && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall(); Stub stub = gen.getStub(); - AbstractAssembler masm = createAssembler(frameMap); + Assembler masm = createAssembler(frameMap); HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame); CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult); crb.setFrameSize(frameMap.frameSize());
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Fri Feb 28 16:19:10 2014 +0100 @@ -133,12 +133,12 @@ encodeKlassPointer(masm, asRegister(scratch), heapBaseReg, encoding); } if (state != null) { - crb.recordImplicitException(masm.codeBuffer.position(), state); + crb.recordImplicitException(masm.position(), state); } masm.movl(address.toAddress(), asRegister(scratch)); } if (state != null) { - crb.recordImplicitException(masm.codeBuffer.position(), state); + crb.recordImplicitException(masm.position(), state); } masm.movl(address.toAddress(), asRegister(scratch)); }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Fri Feb 28 16:19:10 2014 +0100 @@ -81,7 +81,7 @@ // This move will be patched to load the safepoint page from a data segment // co-located with the immutable code. asm.movq(scratch, (AMD64Address) crb.recordDataReferenceInCode(pollingPageAddress, alignment)); - final int pos = asm.codeBuffer.position(); + final int pos = asm.position(); crb.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR); if (state != null) { crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); @@ -90,14 +90,14 @@ } else if (isPollingPageFar(config)) { asm.movq(scratch, config.safepointPollingAddress); crb.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR); - final int pos = asm.codeBuffer.position(); + final int pos = asm.position(); if (state != null) { crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); } asm.testl(rax, new AMD64Address(scratch)); } else { crb.recordMark(atReturn ? MARK_POLL_RETURN_NEAR : MARK_POLL_NEAR); - final int pos = asm.codeBuffer.position(); + final int pos = asm.position(); if (state != null) { crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Fri Feb 28 16:19:10 2014 +0100 @@ -58,7 +58,6 @@ public class HSAILHotSpotBackend extends HotSpotBackend { private Map<String, String> paramTypeMap = new HashMap<>(); - private Buffer codeBuffer; private final boolean deviceInitialized; public HSAILHotSpotBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) { @@ -193,14 +192,6 @@ return new HSAILHotSpotLIRGenerator(graph, getProviders(), getRuntime().getConfig(), frameMap, cc, lir); } - public String getPartialCodeString() { - if (codeBuffer == null) { - return ""; - } - byte[] data = codeBuffer.copyData(0, codeBuffer.position()); - return (data == null ? "" : new String(data)); - } - class HotSpotFrameContext implements FrameContext { public boolean hasFrame() { @@ -219,14 +210,14 @@ } @Override - protected AbstractAssembler createAssembler(FrameMap frameMap) { + protected Assembler createAssembler(FrameMap frameMap) { return new HSAILAssembler(getTarget()); } @Override public CompilationResultBuilder newCompilationResultBuilder(LIRGenerator lirGen, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { FrameMap frameMap = lirGen.frameMap; - AbstractAssembler masm = createAssembler(frameMap); + Assembler masm = createAssembler(frameMap); HotSpotFrameContext frameContext = new HotSpotFrameContext(); CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult); crb.setFrameSize(frameMap.frameSize()); @@ -237,9 +228,9 @@ public void emitCode(CompilationResultBuilder crb, LIRGenerator lirGen, ResolvedJavaMethod method) { assert method != null : lirGen.getGraph() + " is not associated with a method"; // Emit the prologue. - codeBuffer = crb.asm.codeBuffer; - codeBuffer.emitString0("version 0:95: $full : $large;"); - codeBuffer.emitString(""); + Assembler asm = crb.asm; + asm.emitString0("version 0:95: $full : $large;"); + asm.emitString(""); Signature signature = method.getSignature(); int sigParamCount = signature.getParameterCount(false); @@ -284,10 +275,10 @@ } } - codeBuffer.emitString0("// " + (isStatic ? "static" : "instance") + " method " + method); - codeBuffer.emitString(""); - codeBuffer.emitString0("kernel &run ("); - codeBuffer.emitString(""); + asm.emitString0("// " + (isStatic ? "static" : "instance") + " method " + method); + asm.emitString(""); + asm.emitString0("kernel &run ("); + asm.emitString(""); FrameMap frameMap = crb.frameMap; RegisterConfig regConfig = frameMap.registerConfig; @@ -322,9 +313,9 @@ if (i != totalParamCount - 1) { str += ","; } - codeBuffer.emitString(str); + asm.emitString(str); } - codeBuffer.emitString(") {"); + asm.emitString(") {"); /* * End of parameters start of prolog code. Emit the load instructions for loading of the @@ -332,7 +323,7 @@ * loaded up front but will be loaded as needed. */ for (int i = 0; i < nonConstantParamCount; i++) { - codeBuffer.emitString("ld_kernarg_" + paramHsailSizes[i] + " " + HSAIL.mapRegister(cc.getArgument(i)) + ", [" + paramNames[i] + "];"); + asm.emitString("ld_kernarg_" + paramHsailSizes[i] + " " + HSAIL.mapRegister(cc.getArgument(i)) + ", [" + paramNames[i] + "];"); } /* @@ -340,16 +331,16 @@ * the register as if it were the last of the nonConstant parameters. */ String workItemReg = "$s" + Integer.toString(asRegister(cc.getArgument(nonConstantParamCount)).encoding()); - codeBuffer.emitString("workitemabsid_u32 " + workItemReg + ", 0;"); + asm.emitString("workitemabsid_u32 " + workItemReg + ", 0;"); /* * Note the logic used for this spillseg size is to leave space and then go back and patch * in the correct size once we have generated all the instructions. This should probably be * done in a more robust way by implementing something like codeBuffer.insertString. */ - int spillsegDeclarationPosition = codeBuffer.position() + 1; + int spillsegDeclarationPosition = asm.position() + 1; String spillsegTemplate = "align 4 spill_u8 %spillseg[123456];"; - codeBuffer.emitString(spillsegTemplate); + asm.emitString(spillsegTemplate); // Emit object array load prologue here. if (isObjectLambda) { boolean useCompressedOops = getRuntime().getConfig().useCompressedOops; @@ -359,37 +350,37 @@ // so tempReg can be the next higher $d register String tmpReg = "$d" + (asRegister(cc.getArgument(nonConstantParamCount - 1)).encoding() + 1); // Convert gid to long. - codeBuffer.emitString("cvt_u64_s32 " + tmpReg + ", " + workItemReg + "; // Convert gid to long"); + asm.emitString("cvt_u64_s32 " + tmpReg + ", " + workItemReg + "; // Convert gid to long"); // Adjust index for sizeof ref. Where to pull this size from? - codeBuffer.emitString("mul_u64 " + tmpReg + ", " + tmpReg + ", " + (useCompressedOops ? 4 : 8) + "; // Adjust index for sizeof ref"); + asm.emitString("mul_u64 " + tmpReg + ", " + tmpReg + ", " + (useCompressedOops ? 4 : 8) + "; // Adjust index for sizeof ref"); // Adjust for actual data start. - codeBuffer.emitString("add_u64 " + tmpReg + ", " + tmpReg + ", " + arrayElementsOffset + "; // Adjust for actual elements data start"); + asm.emitString("add_u64 " + tmpReg + ", " + tmpReg + ", " + arrayElementsOffset + "; // Adjust for actual elements data start"); // Add to array ref ptr. - codeBuffer.emitString("add_u64 " + tmpReg + ", " + tmpReg + ", " + iterationObjArgReg + "; // Add to array ref ptr"); + asm.emitString("add_u64 " + tmpReg + ", " + tmpReg + ", " + iterationObjArgReg + "; // Add to array ref ptr"); // Load the object into the parameter reg. if (useCompressedOops) { // Load u32 into the d 64 reg since it will become an object address - codeBuffer.emitString("ld_global_u32 " + tmpReg + ", " + "[" + tmpReg + "]" + "; // Load compressed ptr from array"); + asm.emitString("ld_global_u32 " + tmpReg + ", " + "[" + tmpReg + "]" + "; // Load compressed ptr from array"); long narrowOopBase = getRuntime().getConfig().narrowOopBase; long narrowOopShift = getRuntime().getConfig().narrowOopShift; if (narrowOopBase == 0 && narrowOopShift == 0) { // No more calculation to do, mov to target register - codeBuffer.emitString("mov_b64 " + iterationObjArgReg + ", " + tmpReg + "; // no shift or base addition"); + asm.emitString("mov_b64 " + iterationObjArgReg + ", " + tmpReg + "; // no shift or base addition"); } else { if (narrowOopBase == 0) { - codeBuffer.emitString("shl_u64 " + iterationObjArgReg + ", " + tmpReg + ", " + narrowOopShift + "; // do narrowOopShift"); + asm.emitString("shl_u64 " + iterationObjArgReg + ", " + tmpReg + ", " + narrowOopShift + "; // do narrowOopShift"); } else if (narrowOopShift == 0) { - codeBuffer.emitString("add_u64 " + iterationObjArgReg + ", " + tmpReg + ", " + narrowOopBase + "; // add narrowOopBase"); + asm.emitString("add_u64 " + iterationObjArgReg + ", " + tmpReg + ", " + narrowOopBase + "; // add narrowOopBase"); } else { - codeBuffer.emitString("mad_u64 " + iterationObjArgReg + ", " + tmpReg + ", " + (1 << narrowOopShift) + ", " + narrowOopBase + "; // shift and add narrowOopBase"); + asm.emitString("mad_u64 " + iterationObjArgReg + ", " + tmpReg + ", " + (1 << narrowOopShift) + ", " + narrowOopBase + "; // shift and add narrowOopBase"); } } } else { - codeBuffer.emitString("ld_global_u64 " + iterationObjArgReg + ", " + "[" + tmpReg + "]" + "; // Load from array element into parameter reg"); + asm.emitString("ld_global_u64 " + iterationObjArgReg + ", " + "[" + tmpReg + "]" + "; // Load from array element into parameter reg"); } } // Prologue done, Emit code for the LIR. @@ -405,9 +396,10 @@ } else { spillsegStringFinal = spillsegTemplate.replace("123456", String.format("%6d", maxStackSize)); } - codeBuffer.emitString(spillsegStringFinal, spillsegDeclarationPosition); + asm.emitString(spillsegStringFinal, spillsegDeclarationPosition); + // Emit the epilogue. - codeBuffer.emitString0("};"); - codeBuffer.emitString(""); + asm.emitString0("};"); + asm.emitString(""); } }
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Fri Feb 28 16:19:10 2014 +0100 @@ -261,24 +261,24 @@ LIRInstruction op; - void emitDeclarations(Buffer codeBuffer) { + void emitDeclarations(Assembler asm) { for (Integer i : unsigned8) { - codeBuffer.emitString(".reg .u8 %r" + i.intValue() + ";"); + asm.emitString(".reg .u8 %r" + i.intValue() + ";"); } for (Integer i : signed32) { - codeBuffer.emitString(".reg .s32 %r" + i.intValue() + ";"); + asm.emitString(".reg .s32 %r" + i.intValue() + ";"); } for (Integer i : signed64) { - codeBuffer.emitString(".reg .s64 %r" + i.intValue() + ";"); + asm.emitString(".reg .s64 %r" + i.intValue() + ";"); } for (Integer i : unsigned64) { - codeBuffer.emitString(".reg .u64 %r" + i.intValue() + ";"); + asm.emitString(".reg .u64 %r" + i.intValue() + ";"); } for (Integer i : float32) { - codeBuffer.emitString(".reg .f32 %r" + i.intValue() + ";"); + asm.emitString(".reg .f32 %r" + i.intValue() + ";"); } for (Integer i : float64) { - codeBuffer.emitString(".reg .f64 %r" + i.intValue() + ";"); + asm.emitString(".reg .f64 %r" + i.intValue() + ";"); } } @@ -360,7 +360,7 @@ // - has no incoming arguments passed on the stack // - has no instructions with debug info FrameMap frameMap = lirGen.frameMap; - AbstractAssembler masm = createAssembler(frameMap); + Assembler masm = createAssembler(frameMap); PTXFrameContext frameContext = new PTXFrameContext(); CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult); crb.setFrameSize(0); @@ -368,7 +368,7 @@ } @Override - protected AbstractAssembler createAssembler(FrameMap frameMap) { + protected Assembler createAssembler(FrameMap frameMap) { return new PTXMacroAssembler(getTarget(), frameMap.registerConfig); } @@ -384,13 +384,13 @@ // facilitate seemless PTX code generation subsequently. assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method"; final String name = codeCacheOwner.getName(); - Buffer codeBuffer = crb.asm.codeBuffer; + Assembler asm = crb.asm; // Emit initial boiler-plate directives. - codeBuffer.emitString(".version 3.0"); - codeBuffer.emitString(".target sm_30"); - codeBuffer.emitString0(".entry " + name + " ("); - codeBuffer.emitString(""); + asm.emitString(".version 3.0"); + asm.emitString(".target sm_30"); + asm.emitString0(".entry " + name + " ("); + asm.emitString(""); // Get the start block Block startBlock = lirGen.lir.cfg.getStartBlock(); @@ -413,8 +413,8 @@ } // Start emiting body of the PTX kernel. - codeBuffer.emitString0(") {"); - codeBuffer.emitString(""); + asm.emitString0(") {"); + asm.emitString(""); } // Emit .reg space declarations @@ -422,7 +422,6 @@ assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method"; - Buffer codeBuffer = crb.asm.codeBuffer; RegisterAnalysis registerAnalysis = new RegisterAnalysis(); for (Block b : lirGen.lir.codeEmittingOrder()) { @@ -437,19 +436,21 @@ } } - registerAnalysis.emitDeclarations(codeBuffer); + Assembler asm = crb.asm; + registerAnalysis.emitDeclarations(asm); // emit predicate register declaration int maxPredRegNum = ((PTXLIRGenerator) lirGen).getNextPredRegNumber(); if (maxPredRegNum > 0) { - codeBuffer.emitString(".reg .pred %p<" + maxPredRegNum + ">;"); + asm.emitString(".reg .pred %p<" + maxPredRegNum + ">;"); } } @Override public void emitCode(CompilationResultBuilder crb, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) { assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method"; - Buffer codeBuffer = crb.asm.codeBuffer; + Assembler asm = crb.asm; + // Emit the prologue emitKernelEntry(crb, lirGen, codeCacheOwner); @@ -460,8 +461,7 @@ e.printStackTrace(); // TODO : Better error handling needs to be done once // all types of parameters are handled. - codeBuffer.setPosition(0); - codeBuffer.close(false); + asm.close(false); return; } // Emit code for the LIR @@ -471,14 +471,13 @@ e.printStackTrace(); // TODO : Better error handling needs to be done once // all types of parameters are handled. - codeBuffer.setPosition(0); - codeBuffer.close(false); + asm.close(false); return; } // Emit the epilogue - codeBuffer.emitString0("}"); - codeBuffer.emitString(""); + asm.emitString0("}"); + asm.emitString(""); } /**
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Fri Feb 28 16:19:10 2014 +0100 @@ -40,7 +40,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.java.*; import com.oracle.graal.lir.ptx.*; import com.oracle.graal.nodes.*; @@ -238,7 +237,7 @@ int javaParameterOffset = javaParameterOffsetsInKernelParametersBuffer[javaParametersIndex]; LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, javaParameter.kind(), javaParameterOffset, getGraph()); append(new WriteNode(buf, javaParameter, location, BarrierType.NONE, false, false)); - updateDimArg(method, providers, sig, sigIndex++, args, javaParameter); + updateDimArg(method, sig, sigIndex++, args, javaParameter); } if (returnKind != Kind.Void) { LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, bufSize - wordSize, getGraph()); @@ -325,7 +324,7 @@ * Updates the {@code dimX}, {@code dimY} or {@code dimZ} argument passed to the kernel if * {@code javaParameter} is annotated with {@link ParallelOver}. */ - private void updateDimArg(ResolvedJavaMethod method, HotSpotProviders providers, Signature sig, int sigIndex, Map<LaunchArg, ValueNode> launchArgs, ParameterNode javaParameter) { + private void updateDimArg(ResolvedJavaMethod method, Signature sig, int sigIndex, Map<LaunchArg, ValueNode> launchArgs, ParameterNode javaParameter) { if (sigIndex >= 0) { ParallelOver parallelOver = getParameterAnnotation(ParallelOver.class, sigIndex, method); if (parallelOver != null && sig.getParameterType(sigIndex, method.getDeclaringClass()).equals(providers.getMetaAccess().lookupJavaType(int[].class))) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Fri Feb 28 16:19:10 2014 +0100 @@ -147,7 +147,7 @@ } @Override - protected AbstractAssembler createAssembler(FrameMap frameMap) { + protected Assembler createAssembler(FrameMap frameMap) { return new SPARCMacroAssembler(getTarget(), frameMap.registerConfig); } @@ -158,7 +158,7 @@ assert gen.deoptimizationRescueSlot == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; Stub stub = gen.getStub(); - AbstractAssembler masm = createAssembler(frameMap); + Assembler masm = createAssembler(frameMap); // On SPARC we always use stack frames. HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, frameContext, compilationResult);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Fri Feb 28 16:19:10 2014 +0100 @@ -59,7 +59,7 @@ } public static void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { - final int pos = masm.codeBuffer.position(); + final int pos = masm.position(); new Setx(config.safepointPollingAddress, scratch).emit(masm); crb.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR); if (state != null) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Fri Feb 28 16:19:10 2014 +0100 @@ -30,6 +30,7 @@ import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.phases.common.InliningUtil.*; +import java.io.*; import java.lang.reflect.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; @@ -52,9 +53,14 @@ public class CompilationTask implements Runnable, Comparable { + // Keep static finals in a group with withinEnqueue as the last one. CompilationTask can be + // called from within it's own clinit so it needs to be careful about accessing state. Once + // withinEnqueue is non-null we assume that CompilationTask is fully initialized. + private static final AtomicLong uniqueTaskIds = new AtomicLong(); + private static final DebugMetric BAILOUTS = Debug.metric("Bailouts"); - public static final ThreadLocal<Boolean> withinEnqueue = new ThreadLocal<Boolean>() { + private static final ThreadLocal<Boolean> withinEnqueue = new ThreadLocal<Boolean>() { @Override protected Boolean initialValue() { @@ -62,6 +68,22 @@ } }; + public static final boolean isWithinEnqueue() { + // It's possible this can be called before the <clinit> has completed so check for null + return withinEnqueue == null || withinEnqueue.get(); + } + + public static class BeginEnqueue implements Closeable { + public BeginEnqueue() { + assert !withinEnqueue.get(); + withinEnqueue.set(Boolean.TRUE); + } + + public void close() { + withinEnqueue.set(Boolean.FALSE); + } + } + private enum CompilationStatus { Queued, Running, Finished } @@ -74,8 +96,6 @@ private StructuredGraph graph; - private static final AtomicLong uniqueTaskIds = new AtomicLong(); - /** * A long representing the sequence number of this task. Used for sorting the compile queue. */
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Fri Feb 28 16:19:10 2014 +0100 @@ -248,14 +248,10 @@ // Compile until the queue is empty. int z = 0; while (true) { - try { - assert !CompilationTask.withinEnqueue.get(); - CompilationTask.withinEnqueue.set(Boolean.TRUE); + try (CompilationTask.BeginEnqueue beginEnqueue = new CompilationTask.BeginEnqueue()) { if (compileQueue.getCompletedTaskCount() >= Math.max(3, compileQueue.getTaskCount())) { break; } - } finally { - CompilationTask.withinEnqueue.set(Boolean.FALSE); } Thread.sleep(100); @@ -325,9 +321,7 @@ } public void shutdownCompiler() throws Exception { - try { - assert !CompilationTask.withinEnqueue.get(); - CompilationTask.withinEnqueue.set(Boolean.TRUE); + try (CompilationTask.BeginEnqueue beginEnqueue = new CompilationTask.BeginEnqueue()) { // We have to use a privileged action here because shutting down the compiler might be // called from user code which very likely contains unprivileged frames. AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { @@ -336,8 +330,6 @@ return null; } }); - } finally { - CompilationTask.withinEnqueue.set(Boolean.FALSE); } printDebugValues(ResetDebugValuesAfterBootstrap.getValue() ? "application" : null, false); @@ -537,7 +529,7 @@ return; } - if (CompilationTask.withinEnqueue.get()) { + if (CompilationTask.isWithinEnqueue()) { // This is required to avoid deadlocking a compiler thread. The issue is that a // java.util.concurrent.BlockingQueue is used to implement the compilation worker // queues. If a compiler thread triggers a compilation, then it may be blocked trying @@ -547,8 +539,7 @@ // Don't allow blocking compiles from CompilerThreads boolean block = blocking && !(Thread.currentThread() instanceof CompilerThread); - CompilationTask.withinEnqueue.set(Boolean.TRUE); - try { + try (CompilationTask.BeginEnqueue beginEnqueue = new CompilationTask.BeginEnqueue()) { if (method.tryToQueueForCompilation()) { assert method.isQueuedForCompilation(); @@ -565,8 +556,6 @@ // The compile queue was already shut down. } } - } finally { - CompilationTask.withinEnqueue.set(Boolean.FALSE); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Fri Feb 28 16:19:10 2014 +0100 @@ -336,7 +336,7 @@ ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE, false)); ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph); ReadNode read = graph.add(new ReadNode(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE, false)); - IntegerAddNode add = graph.unique(new IntegerAddNode(Kind.Long, read, counter.getIncrement())); + IntegerAddNode add = graph.unique(new IntegerAddNode(StampFactory.forKind(Kind.Long), read, counter.getIncrement())); WriteNode write = graph.add(new WriteNode(readArray, add, location, BarrierType.NONE, false)); graph.addBeforeFixed(counter, thread);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Fri Feb 28 16:19:10 2014 +0100 @@ -27,7 +27,7 @@ import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.hotspot.meta.HotSpotHostForeignCallsProvider.*; +import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; import static com.oracle.graal.nodes.java.ArrayLengthNode.*; @@ -97,325 +97,40 @@ @Override public void lower(Node n, LoweringTool tool) { - HotSpotVMConfig config = runtime.getConfig(); StructuredGraph graph = (StructuredGraph) n.graph(); - Kind wordKind = runtime.getTarget().wordKind; if (n instanceof ArrayLengthNode) { - ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; - ValueNode array = arrayLengthNode.array(); - ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt(), - BarrierType.NONE, false)); - arrayLengthRead.setGuard(createNullCheck(array, arrayLengthNode, tool)); - graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead); + lowerArrayLengthNode((ArrayLengthNode) n, tool); } else if (n instanceof Invoke) { - Invoke invoke = (Invoke) n; - if (invoke.callTarget() instanceof MethodCallTargetNode) { - - MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); - NodeInputList<ValueNode> parameters = callTarget.arguments(); - ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0); - GuardingNode receiverNullCheck = null; - if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !ObjectStamp.isObjectNonNull(receiver)) { - receiverNullCheck = createNullCheck(receiver, invoke.asNode(), tool); - invoke.setGuard(receiverNullCheck); - } - JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass()); - - LoweredCallTargetNode loweredCallTarget = null; - if (callTarget.invokeKind() == InvokeKind.Virtual && InlineVTableStubs.getValue() && (AlwaysInlineVTableStubs.getValue() || invoke.isPolymorphic())) { - - HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); - if (!hsMethod.getDeclaringClass().isInterface()) { - if (hsMethod.isInVirtualMethodTable()) { - int vtableEntryOffset = hsMethod.vtableEntryOffset(); - assert vtableEntryOffset > 0; - FloatingReadNode hub = createReadHub(graph, wordKind, receiver, receiverNullCheck); - - ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, hub, hsMethod); - // We use LocationNode.ANY_LOCATION for the reads that access the - // compiled code entry as HotSpot does not guarantee they are final - // values. - ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), - StampFactory.forKind(wordKind), BarrierType.NONE, false)); - - loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), - CallingConvention.Type.JavaCall)); - - graph.addBeforeFixed(invoke.asNode(), metaspaceMethod); - graph.addAfterFixed(metaspaceMethod, compiledEntry); - } - } - } - - if (loweredCallTarget == null) { - loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall, - callTarget.invokeKind())); - } - callTarget.replaceAndDelete(loweredCallTarget); - } + lowerInvoke((Invoke) n, tool, graph); } else if (n instanceof LoadFieldNode) { - LoadFieldNode loadField = (LoadFieldNode) n; - HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field(); - ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : loadField.object(); - assert loadField.kind() != Kind.Illegal; - BarrierType barrierType = getFieldLoadBarrierType(field); - ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field, false), loadField.stamp(), barrierType, (loadField.kind() == Kind.Object))); - graph.replaceFixedWithFixed(loadField, memoryRead); - memoryRead.setGuard(createNullCheck(object, memoryRead, tool)); - - if (loadField.isVolatile()) { - MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); - graph.addBeforeFixed(memoryRead, preMembar); - MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ)); - graph.addAfterFixed(memoryRead, postMembar); - } + lowerLoadFieldNode((LoadFieldNode) n, tool); } else if (n instanceof StoreFieldNode) { - StoreFieldNode storeField = (StoreFieldNode) n; - HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field(); - ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : storeField.object(); - BarrierType barrierType = getFieldStoreBarrierType(storeField); - WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field, false), barrierType, storeField.field().getKind() == Kind.Object)); - memoryWrite.setStateAfter(storeField.stateAfter()); - graph.replaceFixedWithFixed(storeField, memoryWrite); - memoryWrite.setGuard(createNullCheck(object, memoryWrite, tool)); - FixedWithNextNode last = memoryWrite; - FixedWithNextNode first = memoryWrite; - - if (storeField.isVolatile()) { - MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); - graph.addBeforeFixed(first, preMembar); - MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE)); - graph.addAfterFixed(last, postMembar); - } + lowerStoreFieldNode((StoreFieldNode) n, tool); } else if (n instanceof CompareAndSwapNode) { - // Separate out GC barrier semantics - CompareAndSwapNode cas = (CompareAndSwapNode) n; - LocationNode location = IndexedLocationNode.create(cas.getLocationIdentity(), cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1); - LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, cas.expected(), cas.newValue(), getCompareAndSwapBarrier(cas), - cas.expected().kind() == Kind.Object)); - atomicNode.setStateAfter(cas.stateAfter()); - graph.replaceFixedWithFixed(cas, atomicNode); + lowerCompareAndSwapNode((CompareAndSwapNode) n); } else if (n instanceof LoadIndexedNode) { - LoadIndexedNode loadIndexed = (LoadIndexedNode) n; - Kind elementKind = loadIndexed.elementKind(); - LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index(), false); - ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), BarrierType.NONE, elementKind == Kind.Object)); - memoryRead.setGuard(createBoundsCheck(loadIndexed, tool)); - graph.replaceFixedWithFixed(loadIndexed, memoryRead); + lowerLoadIndexedNode((LoadIndexedNode) n, tool); } else if (n instanceof StoreIndexedNode) { - StoreIndexedNode storeIndexed = (StoreIndexedNode) n; - GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool); - Kind elementKind = storeIndexed.elementKind(); - LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index(), false); - ValueNode value = storeIndexed.value(); - ValueNode array = storeIndexed.array(); - - CheckCastNode checkcastNode = null; - CheckCastDynamicNode checkcastDynamicNode = null; - if (elementKind == Kind.Object && !ObjectStamp.isObjectAlwaysNull(value)) { - // Store check! - ResolvedJavaType arrayType = ObjectStamp.typeOrNull(array); - if (arrayType != null && ObjectStamp.isExactType(array)) { - ResolvedJavaType elementType = arrayType.getComponentType(); - if (!MetaUtil.isJavaLangObject(elementType)) { - checkcastNode = graph.add(new CheckCastNode(elementType, value, null, true)); - graph.addBeforeFixed(storeIndexed, checkcastNode); - value = checkcastNode; - } - } else { - FloatingReadNode arrayClass = createReadHub(graph, wordKind, array, boundsCheck); - LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph); - /* - * Anchor the read of the element klass to the cfg, because it is only valid - * when arrayClass is an object class, which might not be the case in other - * parts of the compiled method. - */ - FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(storeIndexed))); - checkcastDynamicNode = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true)); - graph.addBeforeFixed(storeIndexed, checkcastDynamicNode); - value = checkcastDynamicNode; - } - } - BarrierType barrierType = getArrayStoreBarrierType(storeIndexed); - WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType, elementKind == Kind.Object)); - memoryWrite.setGuard(boundsCheck); - memoryWrite.setStateAfter(storeIndexed.stateAfter()); - graph.replaceFixedWithFixed(storeIndexed, memoryWrite); - - // Lower the associated checkcast node. - if (checkcastNode != null) { - checkcastNode.lower(tool); - } else if (checkcastDynamicNode != null) { - checkcastDynamicSnippets.lower(checkcastDynamicNode, tool); - } + lowerStoreIndexedNode((StoreIndexedNode) n, tool); } else if (n instanceof UnsafeLoadNode) { - UnsafeLoadNode load = (UnsafeLoadNode) n; - if (load.getGuardingCondition() != null) { - boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); - ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition())); - LocationNode location = createLocation(load); - ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), valueAnchorNode, BarrierType.NONE, compressible)); - load.replaceAtUsages(memoryRead); - graph.replaceFixedWithFixed(load, valueAnchorNode); - graph.addAfterFixed(valueAnchorNode, memoryRead); - } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) { - assert load.kind() != Kind.Illegal; - boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); - if (addReadBarrier(load)) { - unsafeLoadSnippets.lower(load, tool); - } else { - LocationNode location = createLocation(load); - ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), BarrierType.NONE, compressible)); - // An unsafe read must not float outside its block otherwise - // it may float above an explicit null check on its object. - memoryRead.setGuard(AbstractBeginNode.prevBegin(load)); - graph.replaceFixedWithFixed(load, memoryRead); - } - } + lowerUnsafeLoadNode((UnsafeLoadNode) n, tool); } else if (n instanceof UnsafeStoreNode) { - UnsafeStoreNode store = (UnsafeStoreNode) n; - LocationNode location = createLocation(store); - ValueNode object = store.object(); - BarrierType barrierType = getUnsafeStoreBarrierType(store); - WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType, store.value().kind() == Kind.Object)); - write.setStateAfter(store.stateAfter()); - graph.replaceFixedWithFixed(store, write); + lowerUnsafeStoreNode((UnsafeStoreNode) n); } else if (n instanceof LoadHubNode) { - if (graph.getGuardsStage().ordinal() >= StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) { - LoadHubNode loadHub = (LoadHubNode) n; - assert loadHub.kind() == wordKind; - ValueNode object = loadHub.object(); - GuardingNode guard = loadHub.getGuard(); - FloatingReadNode hub = createReadHub(graph, wordKind, object, guard); - graph.replaceFloating(loadHub, hub); - } + lowerLoadHubNode((LoadHubNode) n); } else if (n instanceof LoadMethodNode) { - LoadMethodNode loadMethodNode = (LoadMethodNode) n; - ResolvedJavaMethod method = loadMethodNode.getMethod(); - ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, loadMethodNode.getHub(), method); - graph.replaceFixed(loadMethodNode, metaspaceMethod); + lowerLoadMethodNode((LoadMethodNode) n); } else if (n instanceof StoreHubNode) { - StoreHubNode storeHub = (StoreHubNode) n; - WriteNode hub = createWriteHub(graph, wordKind, storeHub.getObject(), storeHub.getValue()); - graph.replaceFixed(storeHub, hub); + lowerStoreHubNode((StoreHubNode) n, graph); } else if (n instanceof CommitAllocationNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - CommitAllocationNode commit = (CommitAllocationNode) n; - ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()]; - BitSet omittedValues = new BitSet(); - int valuePos = 0; - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); - int entryCount = virtual.entryCount(); - FixedWithNextNode newObject; - if (virtual instanceof VirtualInstanceNode) { - newObject = graph.add(new NewInstanceNode(virtual.type(), true)); - } else { - newObject = graph.add(new NewArrayNode(((VirtualArrayNode) virtual).componentType(), ConstantNode.forInt(entryCount, graph), true)); - } - graph.addBeforeFixed(commit, newObject); - allocations[objIndex] = newObject; - for (int i = 0; i < entryCount; i++) { - ValueNode value = commit.getValues().get(valuePos); - if (value instanceof VirtualObjectNode) { - value = allocations[commit.getVirtualObjects().indexOf(value)]; - } - if (value == null) { - omittedValues.set(valuePos); - } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { - // Constant.illegal is always the defaultForKind, so it is skipped - Kind valueKind = value.kind(); - Kind entryKind = virtual.entryKind(i); - - // Truffle requires some leniency in terms of what can be put where: - Kind accessKind = valueKind.getStackKind() == entryKind.getStackKind() ? entryKind : valueKind; - assert valueKind.getStackKind() == entryKind.getStackKind() || - (valueKind == Kind.Long || valueKind == Kind.Double || (valueKind == Kind.Int && virtual instanceof VirtualArrayNode)); - ConstantLocationNode location; - BarrierType barrierType; - if (virtual instanceof VirtualInstanceNode) { - ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i); - location = ConstantLocationNode.create(INIT_LOCATION, accessKind, ((HotSpotResolvedJavaField) field).offset(), graph); - barrierType = (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.IMPRECISE : BarrierType.NONE; - } else { - location = ConstantLocationNode.create(INIT_LOCATION, accessKind, getArrayBaseOffset(entryKind) + i * getScalingFactor(entryKind), graph); - barrierType = (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.PRECISE : BarrierType.NONE; - } - WriteNode write = new WriteNode(newObject, value, location, barrierType, entryKind == Kind.Object); - graph.addAfterFixed(newObject, graph.add(write)); - } - valuePos++; - - } - } - valuePos = 0; - - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); - int entryCount = virtual.entryCount(); - ValueNode newObject = allocations[objIndex]; - for (int i = 0; i < entryCount; i++) { - if (omittedValues.get(valuePos)) { - ValueNode value = commit.getValues().get(valuePos); - assert value instanceof VirtualObjectNode; - ValueNode allocValue = allocations[commit.getVirtualObjects().indexOf(value)]; - if (!(allocValue.isConstant() && allocValue.asConstant().isDefaultForKind())) { - assert virtual.entryKind(i) == Kind.Object && allocValue.kind() == Kind.Object; - WriteNode write; - if (virtual instanceof VirtualInstanceNode) { - VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; - write = new WriteNode(newObject, allocValue, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i), true), BarrierType.IMPRECISE, true); - } else { - write = new WriteNode(newObject, allocValue, createArrayLocation(graph, virtual.entryKind(i), ConstantNode.forInt(i, graph), true), BarrierType.PRECISE, true); - } - graph.addBeforeFixed(commit, graph.add(write)); - } - } - valuePos++; - } - } - - finishAllocatedObjects(tool, commit, allocations); - graph.removeFixed(commit); - } + lowerCommitAllocationNode((CommitAllocationNode) n, tool); } else if (n instanceof OSRStartNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - OSRStartNode osrStart = (OSRStartNode) n; - StartNode newStart = graph.add(new StartNode()); - ParameterNode buffer = graph.unique(new ParameterNode(0, StampFactory.forKind(wordKind))); - ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(foreignCalls, OSR_MIGRATION_END, buffer)); - migrationEnd.setStateAfter(osrStart.stateAfter()); - - newStart.setNext(migrationEnd); - FixedNode next = osrStart.next(); - osrStart.setNext(null); - migrationEnd.setNext(next); - graph.setStart(newStart); - - // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block) - int localsOffset = (graph.method().getMaxLocals() - 1) * 8; - for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) { - int size = FrameStateBuilder.stackSlots(osrLocal.kind()); - int offset = localsOffset - (osrLocal.index() + size - 1) * 8; - IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.kind(), offset, ConstantNode.forLong(0, graph), graph, 1); - ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), BarrierType.NONE, false)); - osrLocal.replaceAndDelete(load); - graph.addBeforeFixed(migrationEnd, load); - } - osrStart.replaceAtUsages(newStart); - osrStart.safeDelete(); - } + lowerOSRStartNode((OSRStartNode) n); } else if (n instanceof DynamicCounterNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { - BenchmarkCounters.lower((DynamicCounterNode) n, registers, runtime.getConfig(), wordKind); - } + lowerDynamicCounterNode((DynamicCounterNode) n); } else if (n instanceof DeferredForeignCallNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FLOATING_GUARDS) { - DeferredForeignCallNode deferred = (DeferredForeignCallNode) n; - ForeignCallNode foreignCallNode = graph.add(new ForeignCallNode(foreignCalls, deferred.getDescriptor(), deferred.getArguments())); - graph.replaceFixedWithFixed(deferred, foreignCallNode); - } + lowerDeferredForeignCallNode((DeferredForeignCallNode) n); } else if (n instanceof CheckCastDynamicNode) { checkcastDynamicSnippets.lower((CheckCastDynamicNode) n, tool); } else if (n instanceof InstanceOfNode) { @@ -480,8 +195,355 @@ } else if (n instanceof DeoptimizeNode || n instanceof UnwindNode) { /* No lowering, we generate LIR directly for these nodes. */ } else { - assert false : "Node implementing Lowerable not handled: " + n; - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("Node implementing Lowerable not handled: " + n); + } + } + + private void lowerArrayLengthNode(ArrayLengthNode arrayLengthNode, LoweringTool tool) { + StructuredGraph graph = arrayLengthNode.graph(); + ValueNode array = arrayLengthNode.array(); + ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(ARRAY_LENGTH_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, graph), + StampFactory.positiveInt(), BarrierType.NONE, false)); + arrayLengthRead.setGuard(createNullCheck(array, arrayLengthNode, tool)); + graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead); + } + + private void lowerInvoke(Invoke invoke, LoweringTool tool, StructuredGraph graph) { + if (invoke.callTarget() instanceof MethodCallTargetNode) { + MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); + NodeInputList<ValueNode> parameters = callTarget.arguments(); + ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0); + GuardingNode receiverNullCheck = null; + if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !ObjectStamp.isObjectNonNull(receiver)) { + receiverNullCheck = createNullCheck(receiver, invoke.asNode(), tool); + invoke.setGuard(receiverNullCheck); + } + JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass()); + + LoweredCallTargetNode loweredCallTarget = null; + if (callTarget.invokeKind() == InvokeKind.Virtual && InlineVTableStubs.getValue() && (AlwaysInlineVTableStubs.getValue() || invoke.isPolymorphic())) { + + HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); + if (!hsMethod.getDeclaringClass().isInterface()) { + if (hsMethod.isInVirtualMethodTable()) { + int vtableEntryOffset = hsMethod.vtableEntryOffset(); + assert vtableEntryOffset > 0; + Kind wordKind = runtime.getTarget().wordKind; + FloatingReadNode hub = createReadHub(graph, wordKind, receiver, receiverNullCheck); + + ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, hub, hsMethod); + // We use LocationNode.ANY_LOCATION for the reads that access the + // compiled code entry as HotSpot does not guarantee they are final + // values. + ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, runtime.getConfig().methodCompiledEntryOffset, graph), + StampFactory.forKind(wordKind), BarrierType.NONE, false)); + + loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), + CallingConvention.Type.JavaCall)); + + graph.addBeforeFixed(invoke.asNode(), metaspaceMethod); + graph.addAfterFixed(metaspaceMethod, compiledEntry); + } + } + } + + if (loweredCallTarget == null) { + loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall, + callTarget.invokeKind())); + } + callTarget.replaceAndDelete(loweredCallTarget); + } + } + + private void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) { + StructuredGraph graph = loadField.graph(); + HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field(); + ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : loadField.object(); + assert loadField.kind() != Kind.Illegal; + BarrierType barrierType = getFieldLoadBarrierType(field); + ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field, false), loadField.stamp(), barrierType, (loadField.kind() == Kind.Object))); + graph.replaceFixedWithFixed(loadField, memoryRead); + memoryRead.setGuard(createNullCheck(object, memoryRead, tool)); + + if (loadField.isVolatile()) { + MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); + graph.addBeforeFixed(memoryRead, preMembar); + MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ)); + graph.addAfterFixed(memoryRead, postMembar); + } + } + + private void lowerStoreFieldNode(StoreFieldNode storeField, LoweringTool tool) { + StructuredGraph graph = storeField.graph(); + HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field(); + ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : storeField.object(); + BarrierType barrierType = getFieldStoreBarrierType(storeField); + WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field, false), barrierType, storeField.field().getKind() == Kind.Object)); + memoryWrite.setStateAfter(storeField.stateAfter()); + graph.replaceFixedWithFixed(storeField, memoryWrite); + memoryWrite.setGuard(createNullCheck(object, memoryWrite, tool)); + FixedWithNextNode last = memoryWrite; + FixedWithNextNode first = memoryWrite; + + if (storeField.isVolatile()) { + MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + graph.addBeforeFixed(first, preMembar); + MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE)); + graph.addAfterFixed(last, postMembar); + } + } + + private static void lowerCompareAndSwapNode(CompareAndSwapNode cas) { + // Separate out GC barrier semantics + StructuredGraph graph = cas.graph(); + LocationNode location = IndexedLocationNode.create(cas.getLocationIdentity(), cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1); + LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, cas.expected(), cas.newValue(), getCompareAndSwapBarrier(cas), + cas.expected().kind() == Kind.Object)); + atomicNode.setStateAfter(cas.stateAfter()); + graph.replaceFixedWithFixed(cas, atomicNode); + } + + private void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) { + StructuredGraph graph = loadIndexed.graph(); + Kind elementKind = loadIndexed.elementKind(); + LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index(), false); + ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), BarrierType.NONE, elementKind == Kind.Object)); + memoryRead.setGuard(createBoundsCheck(loadIndexed, tool)); + graph.replaceFixedWithFixed(loadIndexed, memoryRead); + } + + private void lowerStoreIndexedNode(StoreIndexedNode storeIndexed, LoweringTool tool) { + StructuredGraph graph = storeIndexed.graph(); + GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool); + Kind elementKind = storeIndexed.elementKind(); + LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index(), false); + ValueNode value = storeIndexed.value(); + ValueNode array = storeIndexed.array(); + + CheckCastNode checkcastNode = null; + CheckCastDynamicNode checkcastDynamicNode = null; + if (elementKind == Kind.Object && !ObjectStamp.isObjectAlwaysNull(value)) { + // Store check! + ResolvedJavaType arrayType = ObjectStamp.typeOrNull(array); + if (arrayType != null && ObjectStamp.isExactType(array)) { + ResolvedJavaType elementType = arrayType.getComponentType(); + if (!MetaUtil.isJavaLangObject(elementType)) { + checkcastNode = graph.add(new CheckCastNode(elementType, value, null, true)); + graph.addBeforeFixed(storeIndexed, checkcastNode); + value = checkcastNode; + } + } else { + Kind wordKind = runtime.getTarget().wordKind; + FloatingReadNode arrayClass = createReadHub(graph, wordKind, array, boundsCheck); + LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, runtime.getConfig().arrayClassElementOffset, graph); + /* + * Anchor the read of the element klass to the cfg, because it is only valid when + * arrayClass is an object class, which might not be the case in other parts of the + * compiled method. + */ + FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(storeIndexed))); + checkcastDynamicNode = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true)); + graph.addBeforeFixed(storeIndexed, checkcastDynamicNode); + value = checkcastDynamicNode; + } + } + BarrierType barrierType = getArrayStoreBarrierType(storeIndexed); + WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType, elementKind == Kind.Object)); + memoryWrite.setGuard(boundsCheck); + memoryWrite.setStateAfter(storeIndexed.stateAfter()); + graph.replaceFixedWithFixed(storeIndexed, memoryWrite); + + // Lower the associated checkcast node. + if (checkcastNode != null) { + checkcastNode.lower(tool); + } else if (checkcastDynamicNode != null) { + checkcastDynamicSnippets.lower(checkcastDynamicNode, tool); + } + } + + private void lowerUnsafeLoadNode(UnsafeLoadNode load, LoweringTool tool) { + StructuredGraph graph = load.graph(); + if (load.getGuardingCondition() != null) { + boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); + ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition())); + LocationNode location = createLocation(load); + ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), valueAnchorNode, BarrierType.NONE, compressible)); + load.replaceAtUsages(memoryRead); + graph.replaceFixedWithFixed(load, valueAnchorNode); + graph.addAfterFixed(valueAnchorNode, memoryRead); + } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) { + assert load.kind() != Kind.Illegal; + boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); + if (addReadBarrier(load)) { + unsafeLoadSnippets.lower(load, tool); + } else { + LocationNode location = createLocation(load); + ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), BarrierType.NONE, compressible)); + // An unsafe read must not float outside its block otherwise + // it may float above an explicit null check on its object. + memoryRead.setGuard(AbstractBeginNode.prevBegin(load)); + graph.replaceFixedWithFixed(load, memoryRead); + } + } + } + + private static void lowerUnsafeStoreNode(UnsafeStoreNode store) { + StructuredGraph graph = store.graph(); + LocationNode location = createLocation(store); + ValueNode object = store.object(); + BarrierType barrierType = getUnsafeStoreBarrierType(store); + WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType, store.value().kind() == Kind.Object)); + write.setStateAfter(store.stateAfter()); + graph.replaceFixedWithFixed(store, write); + } + + private void lowerLoadHubNode(LoadHubNode loadHub) { + StructuredGraph graph = loadHub.graph(); + if (graph.getGuardsStage().ordinal() >= StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) { + Kind wordKind = runtime.getTarget().wordKind; + assert loadHub.kind() == wordKind; + ValueNode object = loadHub.object(); + GuardingNode guard = loadHub.getGuard(); + FloatingReadNode hub = createReadHub(graph, wordKind, object, guard); + graph.replaceFloating(loadHub, hub); + } + } + + private void lowerLoadMethodNode(LoadMethodNode loadMethodNode) { + StructuredGraph graph = loadMethodNode.graph(); + ResolvedJavaMethod method = loadMethodNode.getMethod(); + ReadNode metaspaceMethod = createReadVirtualMethod(graph, runtime.getTarget().wordKind, loadMethodNode.getHub(), method); + graph.replaceFixed(loadMethodNode, metaspaceMethod); + } + + private void lowerStoreHubNode(StoreHubNode storeHub, StructuredGraph graph) { + WriteNode hub = createWriteHub(graph, runtime.getTarget().wordKind, storeHub.getObject(), storeHub.getValue()); + graph.replaceFixed(storeHub, hub); + } + + private void lowerCommitAllocationNode(CommitAllocationNode commit, LoweringTool tool) { + StructuredGraph graph = commit.graph(); + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { + ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()]; + BitSet omittedValues = new BitSet(); + int valuePos = 0; + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); + int entryCount = virtual.entryCount(); + FixedWithNextNode newObject; + if (virtual instanceof VirtualInstanceNode) { + newObject = graph.add(new NewInstanceNode(virtual.type(), true)); + } else { + newObject = graph.add(new NewArrayNode(((VirtualArrayNode) virtual).componentType(), ConstantNode.forInt(entryCount, graph), true)); + } + graph.addBeforeFixed(commit, newObject); + allocations[objIndex] = newObject; + for (int i = 0; i < entryCount; i++) { + ValueNode value = commit.getValues().get(valuePos); + if (value instanceof VirtualObjectNode) { + value = allocations[commit.getVirtualObjects().indexOf(value)]; + } + if (value == null) { + omittedValues.set(valuePos); + } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { + // Constant.illegal is always the defaultForKind, so it is skipped + Kind valueKind = value.kind(); + Kind entryKind = virtual.entryKind(i); + + // Truffle requires some leniency in terms of what can be put where: + Kind accessKind = valueKind.getStackKind() == entryKind.getStackKind() ? entryKind : valueKind; + assert valueKind.getStackKind() == entryKind.getStackKind() || + (valueKind == Kind.Long || valueKind == Kind.Double || (valueKind == Kind.Int && virtual instanceof VirtualArrayNode)); + ConstantLocationNode location; + BarrierType barrierType; + if (virtual instanceof VirtualInstanceNode) { + ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i); + location = ConstantLocationNode.create(INIT_LOCATION, accessKind, ((HotSpotResolvedJavaField) field).offset(), graph); + barrierType = (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.IMPRECISE : BarrierType.NONE; + } else { + location = ConstantLocationNode.create(INIT_LOCATION, accessKind, getArrayBaseOffset(entryKind) + i * getScalingFactor(entryKind), graph); + barrierType = (entryKind == Kind.Object && !useDeferredInitBarriers()) ? BarrierType.PRECISE : BarrierType.NONE; + } + WriteNode write = new WriteNode(newObject, value, location, barrierType, entryKind == Kind.Object); + graph.addAfterFixed(newObject, graph.add(write)); + } + valuePos++; + + } + } + valuePos = 0; + + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); + int entryCount = virtual.entryCount(); + ValueNode newObject = allocations[objIndex]; + for (int i = 0; i < entryCount; i++) { + if (omittedValues.get(valuePos)) { + ValueNode value = commit.getValues().get(valuePos); + assert value instanceof VirtualObjectNode; + ValueNode allocValue = allocations[commit.getVirtualObjects().indexOf(value)]; + if (!(allocValue.isConstant() && allocValue.asConstant().isDefaultForKind())) { + assert virtual.entryKind(i) == Kind.Object && allocValue.kind() == Kind.Object; + WriteNode write; + if (virtual instanceof VirtualInstanceNode) { + VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; + write = new WriteNode(newObject, allocValue, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i), true), BarrierType.IMPRECISE, true); + } else { + write = new WriteNode(newObject, allocValue, createArrayLocation(graph, virtual.entryKind(i), ConstantNode.forInt(i, graph), true), BarrierType.PRECISE, true); + } + graph.addBeforeFixed(commit, graph.add(write)); + } + } + valuePos++; + } + } + + finishAllocatedObjects(tool, commit, allocations); + graph.removeFixed(commit); + } + } + + private void lowerOSRStartNode(OSRStartNode osrStart) { + StructuredGraph graph = osrStart.graph(); + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { + StartNode newStart = graph.add(new StartNode()); + ParameterNode buffer = graph.unique(new ParameterNode(0, StampFactory.forKind(runtime.getTarget().wordKind))); + ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(foreignCalls, OSR_MIGRATION_END, buffer)); + migrationEnd.setStateAfter(osrStart.stateAfter()); + + newStart.setNext(migrationEnd); + FixedNode next = osrStart.next(); + osrStart.setNext(null); + migrationEnd.setNext(next); + graph.setStart(newStart); + + // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block) + int localsOffset = (graph.method().getMaxLocals() - 1) * 8; + for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) { + int size = FrameStateBuilder.stackSlots(osrLocal.kind()); + int offset = localsOffset - (osrLocal.index() + size - 1) * 8; + IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.kind(), offset, ConstantNode.forLong(0, graph), graph, 1); + ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), BarrierType.NONE, false)); + osrLocal.replaceAndDelete(load); + graph.addBeforeFixed(migrationEnd, load); + } + osrStart.replaceAtUsages(newStart); + osrStart.safeDelete(); + } + } + + private void lowerDynamicCounterNode(DynamicCounterNode n) { + StructuredGraph graph = n.graph(); + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { + BenchmarkCounters.lower(n, registers, runtime.getConfig(), runtime.getTarget().wordKind); + } + } + + private void lowerDeferredForeignCallNode(DeferredForeignCallNode deferred) { + StructuredGraph graph = deferred.graph(); + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FLOATING_GUARDS) { + ForeignCallNode foreignCallNode = graph.add(new ForeignCallNode(foreignCalls, deferred.getDescriptor(), deferred.getArguments())); + graph.replaceFixedWithFixed(deferred, foreignCallNode); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -22,31 +22,18 @@ */ package com.oracle.graal.hotspot.replacements; -import java.lang.reflect.Modifier; -import java.util.Arrays; +import java.lang.reflect.*; +import java.util.*; -import com.oracle.graal.api.meta.Constant; -import com.oracle.graal.api.meta.JavaType; -import com.oracle.graal.api.meta.ResolvedJavaField; -import com.oracle.graal.api.meta.ResolvedJavaMethod; -import com.oracle.graal.api.meta.ResolvedJavaType; -import com.oracle.graal.graph.GraalInternalError; -import com.oracle.graal.graph.NodeInputList; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.meta.HotSpotResolvedJavaMethod; -import com.oracle.graal.hotspot.meta.HotSpotResolvedObjectType; -import com.oracle.graal.hotspot.meta.HotSpotSignature; -import com.oracle.graal.nodes.CallTargetNode; -import com.oracle.graal.nodes.Invoke; -import com.oracle.graal.nodes.InvokeNode; -import com.oracle.graal.nodes.PiNode; -import com.oracle.graal.nodes.ValueNode; -import com.oracle.graal.nodes.java.MethodCallTargetNode; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; -import com.oracle.graal.nodes.java.SelfReplacingMethodCallTargetNode; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.type.GenericStamp.*; -import com.oracle.graal.replacements.nodes.MacroNode; +import com.oracle.graal.replacements.nodes.*; /** * Common base class for method handle invoke nodes. @@ -282,7 +269,7 @@ // invoker's stamp would be wrong because it's a less concrete type // (usually java.lang.Object). InvokeNode invoke; - if (stamp() instanceof GenericStamp && ((GenericStamp) stamp()).type() == GenericStampType.Void) { + if (stamp() == StampFactory.forVoid()) { invoke = new InvokeNode(callTarget, getBci(), stamp()); } else { invoke = new InvokeNode(callTarget, getBci());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Fri Feb 28 16:19:10 2014 +0100 @@ -35,6 +35,7 @@ import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/GraphKit.java Wed Feb 26 13:09:16 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.stubs; - -import java.lang.reflect.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.java.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.*; -import com.oracle.graal.phases.common.*; -import com.oracle.graal.phases.util.*; -import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.ReplacementsImpl.*; -import com.oracle.graal.word.phases.*; - -/** - * A utility for manually creating a graph. This will be expanded as necessary to support all - * subsystems that employ manual graph creation (as opposed to {@linkplain GraphBuilderPhase - * bytecode parsing} based graph creation). - */ -public class GraphKit { - - private final Providers providers; - private final StructuredGraph graph; - private FixedWithNextNode lastFixedNode; - - public GraphKit(StructuredGraph graph, Providers providers) { - this.providers = providers; - this.graph = graph; - this.lastFixedNode = graph.start(); - } - - public StructuredGraph getGraph() { - return graph; - } - - /** - * Ensures a floating node is added to or already present in the graph via {@link Graph#unique}. - * - * @return a node similar to {@code node} if one exists, otherwise {@code node} - */ - protected <T extends FloatingNode> T unique(T node) { - return graph.unique(node); - } - - /** - * Appends a fixed node to the graph. - */ - protected <T extends FixedNode> T append(T node) { - T result = graph.add(node); - assert lastFixedNode != null; - assert result.predecessor() == null; - graph.addAfterFixed(lastFixedNode, result); - if (result instanceof FixedWithNextNode) { - lastFixedNode = (FixedWithNextNode) result; - } else { - lastFixedNode = null; - } - return result; - } - - /** - * Creates and appends an {@link InvokeNode} for a call to a given method with a given set of - * arguments. - * - * @param declaringClass the class declaring the invoked method - * @param name the name of the invoked method - * @param args the arguments to the invocation - */ - public InvokeNode createInvoke(Class<?> declaringClass, String name, ValueNode... args) { - ResolvedJavaMethod method = null; - for (Method m : declaringClass.getDeclaredMethods()) { - if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(name)) { - assert method == null : "found more than one method in " + declaringClass + " named " + name; - method = providers.getMetaAccess().lookupJavaMethod(m); - } - } - assert method != null : "did not find method in " + declaringClass + " named " + name; - Signature signature = method.getSignature(); - JavaType returnType = signature.getReturnType(null); - assert checkArgs(method, args); - MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, method, args, returnType)); - InvokeNode invoke = append(new InvokeNode(callTarget, FrameState.UNKNOWN_BCI)); - return invoke; - } - - /** - * Determines if a given set of arguments is compatible with the signature of a given method. - * - * @return true if {@code args} are compatible with the signature if {@code method} - * @throws AssertionError if {@code args} are not compatible with the signature if - * {@code method} - */ - public boolean checkArgs(ResolvedJavaMethod method, ValueNode... args) { - Signature signature = method.getSignature(); - if (signature.getParameterCount(false) != args.length) { - throw new AssertionError(graph + ": wrong number of arguments to " + method); - } - for (int i = 0; i != args.length; i++) { - Kind expected = signature.getParameterKind(i).getStackKind(); - Kind actual = args[i].stamp().getStackKind(); - if (expected != actual) { - throw new AssertionError(graph + ": wrong kind of value for argument " + i + " of calls to " + method + " [" + actual + " != " + expected + "]"); - } - } - return true; - } - - /** - * Rewrite all word types in the graph. - */ - public void rewriteWordTypes() { - new WordTypeRewriterPhase(providers.getMetaAccess(), providers.getCodeCache().getTarget().wordKind).apply(graph); - } - - /** - * {@linkplain #inline(InvokeNode) Inlines} all invocations currently in the graph. - */ - public void inlineInvokes() { - for (InvokeNode invoke : graph.getNodes().filter(InvokeNode.class).snapshot()) { - inline(invoke); - } - - // Clean up all code that is now dead after inlining. - new DeadCodeEliminationPhase().apply(graph); - assert graph.getNodes().filter(InvokeNode.class).isEmpty(); - } - - /** - * Inlines a given invocation to a method. The graph of the inlined method is - * {@linkplain ReplacementsImpl#makeGraph processed} in the same manner as for snippets and - * method substitutions. - */ - public void inline(InvokeNode invoke) { - ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod(); - ReplacementsImpl repl = new ReplacementsImpl(providers, new Assumptions(false), providers.getCodeCache().getTarget()); - StructuredGraph calleeGraph = repl.makeGraph(method, null, method, null, FrameStateProcessing.CollapseFrameForSingleSideEffect); - InliningUtil.inline(invoke, calleeGraph, false); - } -}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Feb 28 16:19:10 2014 +0100 @@ -598,35 +598,35 @@ switch (opcode) { case IADD: case LADD: - v = new IntegerAddNode(result, x, y); + v = new IntegerAddNode(StampFactory.forKind(result), x, y); break; case FADD: case DADD: - v = new FloatAddNode(result, x, y, isStrictFP); + v = new FloatAddNode(StampFactory.forKind(result), x, y, isStrictFP); break; case ISUB: case LSUB: - v = new IntegerSubNode(result, x, y); + v = new IntegerSubNode(StampFactory.forKind(result), x, y); break; case FSUB: case DSUB: - v = new FloatSubNode(result, x, y, isStrictFP); + v = new FloatSubNode(StampFactory.forKind(result), x, y, isStrictFP); break; case IMUL: case LMUL: - v = new IntegerMulNode(result, x, y); + v = new IntegerMulNode(StampFactory.forKind(result), x, y); break; case FMUL: case DMUL: - v = new FloatMulNode(result, x, y, isStrictFP); + v = new FloatMulNode(StampFactory.forKind(result), x, y, isStrictFP); break; case FDIV: case DDIV: - v = new FloatDivNode(result, x, y, isStrictFP); + v = new FloatDivNode(StampFactory.forKind(result), x, y, isStrictFP); break; case FREM: case DREM: - v = new FloatRemNode(result, x, y, isStrictFP); + v = new FloatRemNode(StampFactory.forKind(result), x, y, isStrictFP); break; default: throw new GraalInternalError("should not reach"); @@ -641,11 +641,11 @@ switch (opcode) { case IDIV: case LDIV: - v = new IntegerDivNode(result, x, y); + v = new IntegerDivNode(StampFactory.forKind(result), x, y); break; case IREM: case LREM: - v = new IntegerRemNode(result, x, y); + v = new IntegerRemNode(StampFactory.forKind(result), x, y); break; default: throw new GraalInternalError("should not reach"); @@ -664,15 +664,15 @@ switch (opcode) { case ISHL: case LSHL: - v = new LeftShiftNode(kind, x, s); + v = new LeftShiftNode(StampFactory.forKind(kind), x, s); break; case ISHR: case LSHR: - v = new RightShiftNode(kind, x, s); + v = new RightShiftNode(StampFactory.forKind(kind), x, s); break; case IUSHR: case LUSHR: - v = new UnsignedRightShiftNode(kind, x, s); + v = new UnsignedRightShiftNode(StampFactory.forKind(kind), x, s); break; default: throw new GraalInternalError("should not reach"); @@ -683,19 +683,20 @@ private void genLogicOp(Kind kind, int opcode) { ValueNode y = frameState.pop(kind); ValueNode x = frameState.pop(kind); + Stamp stamp = StampFactory.forKind(kind); BitLogicNode v; switch (opcode) { case IAND: case LAND: - v = new AndNode(kind, x, y); + v = new AndNode(stamp, x, y); break; case IOR: case LOR: - v = new OrNode(kind, x, y); + v = new OrNode(stamp, x, y); break; case IXOR: case LXOR: - v = new XorNode(kind, x, y); + v = new XorNode(stamp, x, y); break; default: throw new GraalInternalError("should not reach"); @@ -740,7 +741,7 @@ int delta = stream().readIncrement(); ValueNode x = frameState.loadLocal(index); ValueNode y = appendConstant(Constant.forInt(delta)); - frameState.storeLocal(index, append(new IntegerAddNode(Kind.Int, x, y))); + frameState.storeLocal(index, append(new IntegerAddNode(StampFactory.forKind(Kind.Int), x, y))); } private void genGoto() {
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Fri Feb 28 16:19:10 2014 +0100 @@ -554,7 +554,7 @@ case IDIV: case IREM: masm.cdql(); - exceptionOffset = masm.codeBuffer.position(); + exceptionOffset = masm.position(); masm.idivl(asRegister(src)); break; @@ -562,7 +562,7 @@ case LDIV: case LREM: masm.cdqq(); - exceptionOffset = masm.codeBuffer.position(); + exceptionOffset = masm.position(); masm.idivq(asRegister(src)); break; @@ -570,7 +570,7 @@ case IUREM: // Must zero the high 64-bit word (in RDX) of the dividend masm.xorq(AMD64.rdx, AMD64.rdx); - exceptionOffset = masm.codeBuffer.position(); + exceptionOffset = masm.position(); masm.divl(asRegister(src)); break; @@ -578,7 +578,7 @@ case LUREM: // Must zero the high 64-bit word (in RDX) of the dividend masm.xorq(AMD64.rdx, AMD64.rdx); - exceptionOffset = masm.codeBuffer.position(); + exceptionOffset = masm.position(); masm.divq(asRegister(src)); break; default:
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Fri Feb 28 16:19:10 2014 +0100 @@ -155,7 +155,7 @@ if (align) { emitAlignmentForDirectCall(crb, masm); } - int before = masm.codeBuffer.position(); + int before = masm.position(); if (scratch != null) { // offset might not fit a 32-bit immediate, generate an // indirect call with a 64-bit immediate @@ -164,7 +164,7 @@ } else { masm.call(); } - int after = masm.codeBuffer.position(); + int after = masm.position(); crb.recordDirectCall(before, after, callTarget, info); crb.recordExceptionHandlers(after, info); masm.ensureUniquePC(); @@ -172,7 +172,7 @@ protected static void emitAlignmentForDirectCall(CompilationResultBuilder crb, AMD64MacroAssembler masm) { // make sure that the displacement word of the call ends up word aligned - int offset = masm.codeBuffer.position(); + int offset = masm.position(); offset += crb.target.arch.getMachineCodeCallDisplacementOffset(); int modulus = crb.target.wordSize; if (offset % modulus != 0) { @@ -181,25 +181,25 @@ } public static void directJmp(CompilationResultBuilder crb, AMD64MacroAssembler masm, InvokeTarget target) { - int before = masm.codeBuffer.position(); + int before = masm.position(); masm.jmp(0, true); - int after = masm.codeBuffer.position(); + int after = masm.position(); crb.recordDirectCall(before, after, target, null); masm.ensureUniquePC(); } public static void directConditionalJmp(CompilationResultBuilder crb, AMD64MacroAssembler masm, InvokeTarget target, ConditionFlag cond) { - int before = masm.codeBuffer.position(); + int before = masm.position(); masm.jcc(cond, 0, true); - int after = masm.codeBuffer.position(); + int after = masm.position(); crb.recordDirectCall(before, after, target, null); masm.ensureUniquePC(); } public static void indirectCall(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) { - int before = masm.codeBuffer.position(); + int before = masm.position(); masm.call(dst); - int after = masm.codeBuffer.position(); + int after = masm.position(); crb.recordIndirectCall(before, after, callTarget, info); crb.recordExceptionHandlers(after, info); masm.ensureUniquePC();
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Fri Feb 28 16:19:10 2014 +0100 @@ -198,7 +198,6 @@ masm.movl(idxScratchReg, indexReg); } - Buffer buf = masm.codeBuffer; // Compare index against jump table bounds int highKey = lowKey + targets.length - 1; if (lowKey != 0) { @@ -215,9 +214,8 @@ } // Set scratch to address of jump table - int leaPos = buf.position(); masm.leaq(scratchReg, new AMD64Address(AMD64.rip, 0)); - int afterLea = buf.position(); + final int afterLea = masm.position(); // Load jump table entry into scratch and jump to it masm.movslq(idxScratchReg, new AMD64Address(scratchReg, idxScratchReg, Scale.Times4, 0)); @@ -225,29 +223,29 @@ masm.jmp(scratchReg); // Inserting padding so that jump table address is 4-byte aligned - if ((buf.position() & 0x3) != 0) { - masm.nop(4 - (buf.position() & 0x3)); + if ((masm.position() & 0x3) != 0) { + masm.nop(4 - (masm.position() & 0x3)); } // Patch LEA instruction above now that we know the position of the jump table - int jumpTablePos = buf.position(); - buf.setPosition(leaPos); - masm.leaq(scratchReg, new AMD64Address(AMD64.rip, jumpTablePos - afterLea)); - buf.setPosition(jumpTablePos); + // TODO this is ugly and should be done differently + final int jumpTablePos = masm.position(); + final int leaDisplacementPosition = afterLea - 4; + masm.emitInt(jumpTablePos - afterLea, leaDisplacementPosition); // Emit jump table entries for (LabelRef target : targets) { Label label = target.label(); - int offsetToJumpTableBase = buf.position() - jumpTablePos; + int offsetToJumpTableBase = masm.position() - jumpTablePos; if (label.isBound()) { int imm32 = label.position() - jumpTablePos; - buf.emitInt(imm32); + masm.emitInt(imm32); } else { - label.addPatchAt(buf.position()); + label.addPatchAt(masm.position()); - buf.emitByte(0); // pseudo-opcode for jump table entry - buf.emitShort(offsetToJumpTableBase); - buf.emitByte(0); // padding to make jump table entry 4 bytes wide + masm.emitByte(0); // pseudo-opcode for jump table entry + masm.emitShort(offsetToJumpTableBase); + masm.emitByte(0); // padding to make jump table entry 4 bytes wide } }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Fri Feb 28 16:19:10 2014 +0100 @@ -122,7 +122,7 @@ @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { if (state != null) { - crb.recordImplicitException(masm.codeBuffer.position(), state); + crb.recordImplicitException(masm.position(), state); } emitMemAccess(crb, masm); } @@ -329,7 +329,7 @@ @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - crb.recordImplicitException(masm.codeBuffer.position(), state); + crb.recordImplicitException(masm.position(), state); masm.nullCheck(asRegister(input)); }
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java Fri Feb 28 16:19:10 2014 +0100 @@ -146,7 +146,7 @@ @Override public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { if (state != null) { - // crb.recordImplicitException(masm.codeBuffer.position(), state); + // crb.recordImplicitException(masm.position(), state); throw new InternalError("NYI"); } emitMemAccess(masm); @@ -305,7 +305,7 @@ encodePointer(masm, scratch, base, shift, alignment, testForNull); if (state != null) { throw new InternalError("NYI"); - // crb.recordImplicitException(masm.codeBuffer.position(), state); + // crb.recordImplicitException(masm.position(), state); } masm.emitStore(scratch, address.toAddress(), "u32"); }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java Fri Feb 28 16:19:10 2014 +0100 @@ -266,8 +266,6 @@ @Override public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) { - Buffer buf = masm.codeBuffer; - // Compare index against jump table bounds int highKey = lowKey + targets.length - 1; @@ -285,7 +283,7 @@ } // address of jump table - int tablePos = buf.position(); + int tablePos = masm.position(); JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4); String name = "jumptable" + jt.position;
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Fri Feb 28 16:19:10 2014 +0100 @@ -252,7 +252,7 @@ @Override public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) { - crb.recordImplicitException(masm.codeBuffer.position(), state); + crb.recordImplicitException(masm.position(), state); masm.nullCheck(asRegister(input)); }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java Fri Feb 28 16:19:10 2014 +0100 @@ -147,7 +147,7 @@ if (align) { // We don't need alignment on SPARC. } - int before = masm.codeBuffer.position(); + int before = masm.position(); if (scratch != null) { // offset might not fit a 30-bit displacement, generate an // indirect call with a 64-bit immediate @@ -156,7 +156,7 @@ } else { new Call(0).emit(masm); } - int after = masm.codeBuffer.position(); + int after = masm.position(); crb.recordDirectCall(before, after, callTarget, info); crb.recordExceptionHandlers(after, info); new Nop().emit(masm); // delay slot @@ -164,19 +164,19 @@ } public static void indirectJmp(CompilationResultBuilder crb, SPARCMacroAssembler masm, Register dst, InvokeTarget target) { - int before = masm.codeBuffer.position(); + int before = masm.position(); new Sethix(0L, dst, true).emit(masm); new Jmp(new SPARCAddress(dst, 0)).emit(masm); - int after = masm.codeBuffer.position(); + int after = masm.position(); crb.recordIndirectCall(before, after, target, null); new Nop().emit(masm); // delay slot masm.ensureUniquePC(); } public static void indirectCall(CompilationResultBuilder crb, SPARCMacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) { - int before = masm.codeBuffer.position(); + int before = masm.position(); new Jmpl(dst, 0, o7).emit(masm); - int after = masm.codeBuffer.position(); + int after = masm.position(); crb.recordIndirectCall(before, after, callTarget, info); crb.recordExceptionHandlers(after, info); new Nop().emit(masm); // delay slot
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Fri Feb 28 16:19:10 2014 +0100 @@ -234,7 +234,6 @@ Register value = asIntReg(index); Register scratchReg = asLongReg(scratch); - Buffer buf = masm.codeBuffer; // Compare index against jump table bounds int highKey = lowKey + targets.length - 1; if (lowKey != 0) { @@ -258,7 +257,7 @@ new Nop().emit(masm); // delay slot // address of jump table - int tablePos = buf.position(); + int tablePos = masm.position(); JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4); crb.compilationResult.addAnnotation(jt);
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java Fri Feb 28 16:19:10 2014 +0100 @@ -120,7 +120,7 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { if (state != null) { - crb.recordImplicitException(masm.codeBuffer.position(), state); + crb.recordImplicitException(masm.position(), state); } emitMemAccess(masm); } @@ -225,7 +225,7 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - crb.recordImplicitException(masm.codeBuffer.position(), state); + crb.recordImplicitException(masm.position(), state); new Ldx(new SPARCAddress(asRegister(input), 0), r0).emit(masm); }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java Fri Feb 28 16:19:10 2014 +0100 @@ -42,6 +42,6 @@ @Override public void emitCode(CompilationResultBuilder crb) { - crb.recordInfopoint(crb.asm.codeBuffer.position(), state, reason); + crb.recordInfopoint(crb.asm.position(), state, reason); } }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java Fri Feb 28 16:19:10 2014 +0100 @@ -89,11 +89,11 @@ public abstract static class BaseSwitchClosure implements SwitchClosure { private final CompilationResultBuilder crb; - private final AbstractAssembler masm; + private final Assembler masm; private final LabelRef[] keyTargets; private final LabelRef defaultTarget; - public BaseSwitchClosure(CompilationResultBuilder crb, AbstractAssembler masm, LabelRef[] keyTargets, LabelRef defaultTarget) { + public BaseSwitchClosure(CompilationResultBuilder crb, Assembler masm, LabelRef[] keyTargets, LabelRef defaultTarget) { this.crb = crb; this.masm = masm; this.keyTargets = keyTargets;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Fri Feb 28 16:19:10 2014 +0100 @@ -54,7 +54,7 @@ } } - public final AbstractAssembler asm; + public final Assembler asm; public final CompilationResult compilationResult; public final TargetDescription target; public final CodeCacheProvider codeCache; @@ -78,8 +78,7 @@ private List<ExceptionInfo> exceptionInfoList; - public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext, - CompilationResult compilationResult) { + public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, FrameContext frameContext, CompilationResult compilationResult) { this.target = codeCache.getTarget(); this.codeCache = codeCache; this.foreignCalls = foreignCalls; @@ -97,15 +96,15 @@ private static final CompilationResult.Mark[] NO_REFS = {}; public CompilationResult.Mark recordMark(Object id) { - return compilationResult.recordMark(asm.codeBuffer.position(), id, NO_REFS); + return compilationResult.recordMark(asm.position(), id, NO_REFS); } public CompilationResult.Mark recordMark(Object id, CompilationResult.Mark... references) { - return compilationResult.recordMark(asm.codeBuffer.position(), id, references); + return compilationResult.recordMark(asm.position(), id, references); } public void blockComment(String s) { - compilationResult.addAnnotation(new CompilationResult.CodeComment(asm.codeBuffer.position(), s)); + compilationResult.addAnnotation(new CompilationResult.CodeComment(asm.position(), s)); } /** @@ -114,7 +113,7 @@ * the compilation result. */ public void finish() { - compilationResult.setTargetCode(asm.codeBuffer.close(false), asm.codeBuffer.position()); + compilationResult.setTargetCode(asm.close(false), asm.position()); // Record exception handlers if they exist if (exceptionInfoList != null) { @@ -159,7 +158,7 @@ public void recordInlineDataInCode(Constant data) { assert data != null; - int pos = asm.codeBuffer.position(); + int pos = asm.position(); Debug.log("Inline data in code: pos = %d, data = %s", pos, data); compilationResult.recordInlineData(pos, data); } @@ -171,7 +170,7 @@ public AbstractAddress recordDataReferenceInCode(Data data) { assert data != null; - int pos = asm.codeBuffer.position(); + int pos = asm.position(); Debug.log("Data reference in code: pos = %d, data = %s", pos, data); compilationResult.recordDataReference(pos, data); return asm.getPlaceholder();
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilderFactory.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilderFactory.java Fri Feb 28 16:19:10 2014 +0100 @@ -34,7 +34,7 @@ /** * Creates a new {@link CompilationResultBuilder}. */ - CompilationResultBuilder createBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext, + CompilationResultBuilder createBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, FrameContext frameContext, CompilationResult compilationResult); /** @@ -42,7 +42,7 @@ */ CompilationResultBuilderFactory Default = new CompilationResultBuilderFactory() { - public CompilationResultBuilder createBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext, + public CompilationResultBuilder createBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, FrameContext frameContext, CompilationResult compilationResult) { return new CompilationResultBuilder(codeCache, foreignCalls, frameMap, asm, frameContext, compilationResult); }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Fri Feb 28 16:19:10 2014 +0100 @@ -29,6 +29,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.type.*; public class CountedLoopInfo { @@ -52,18 +53,18 @@ public ValueNode maxTripCountNode(boolean assumePositive) { StructuredGraph graph = iv.valueNode().graph(); - Kind kind = iv.valueNode().kind(); + Stamp stamp = iv.valueNode().stamp(); IntegerArithmeticNode range = IntegerArithmeticNode.sub(graph, end, iv.initNode()); if (oneOff) { if (iv.direction() == Direction.Up) { - range = IntegerArithmeticNode.add(graph, range, ConstantNode.forIntegerKind(kind, 1, graph)); + range = IntegerArithmeticNode.add(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph)); } else { - range = IntegerArithmeticNode.sub(graph, range, ConstantNode.forIntegerKind(kind, 1, graph)); + range = IntegerArithmeticNode.sub(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph)); } } - IntegerDivNode div = graph.add(new IntegerDivNode(kind, range, iv.strideNode())); + IntegerDivNode div = graph.add(new IntegerDivNode(iv.valueNode().stamp().unrestricted(), range, iv.strideNode())); graph.addBeforeFixed(loop.entryPoint(), div); - ConstantNode zero = ConstantNode.forIntegerKind(kind, 0, graph); + ConstantNode zero = ConstantNode.forIntegerStamp(stamp, 0, graph); if (assumePositive) { return div; } @@ -137,19 +138,19 @@ if (overflowGuard != null) { return overflowGuard; } - Kind kind = iv.valueNode().kind(); + IntegerStamp stamp = (IntegerStamp) iv.valueNode().stamp(); StructuredGraph graph = iv.valueNode().graph(); CompareNode cond; // we use a negated guard with a < condition to achieve a >= - ConstantNode one = ConstantNode.forIntegerKind(kind, 1, graph); + ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph); if (iv.direction() == Direction.Up) { - IntegerArithmeticNode v1 = sub(graph, ConstantNode.forIntegerKind(kind, kind.getMaxValue(), graph), sub(graph, iv.strideNode(), one)); + IntegerArithmeticNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMaxValue(stamp.getBits(), stamp.isUnsigned()), graph), sub(graph, iv.strideNode(), one)); if (oneOff) { v1 = sub(graph, v1, one); } cond = graph.unique(new IntegerLessThanNode(v1, end)); } else { assert iv.direction() == Direction.Down; - IntegerArithmeticNode v1 = add(graph, ConstantNode.forIntegerKind(kind, kind.getMinValue(), graph), sub(graph, one, iv.strideNode())); + IntegerArithmeticNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, IntegerStamp.defaultMinValue(stamp.getBits(), stamp.isUnsigned()), graph), sub(graph, one, iv.strideNode())); if (oneOff) { v1 = add(graph, v1, one); } @@ -161,7 +162,7 @@ return overflowGuard; } - public Kind getKind() { - return iv.valueNode().kind(); + public IntegerStamp getStamp() { + return (IntegerStamp) iv.valueNode().stamp(); } }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java Fri Feb 28 16:19:10 2014 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.loop.phases; -import com.oracle.graal.api.meta.*; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; @@ -38,7 +37,7 @@ if (context.getOptimisticOptimizations().useLoopLimitChecks()) { loops.detectedCountedLoops(); for (LoopEx loop : loops.countedLoops()) { - if (loop.lirLoop().children.isEmpty() && loop.counted().getKind() == Kind.Int) { + if (loop.lirLoop().children.isEmpty() && loop.counted().getStamp().getBits() <= 32) { boolean hasSafepoint = false; for (LoopEndNode loopEnd : loop.loopBegin().loopEnds()) { hasSafepoint |= loopEnd.canSafepoint();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -151,6 +151,16 @@ } } + public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess, StructuredGraph graph) { + if (stamp instanceof PrimitiveStamp) { + return forPrimitive(stamp, constant, graph); + } else { + ConstantNode ret = forConstant(constant, metaAccess, graph); + assert ret.stamp().isCompatible(stamp); + return ret; + } + } + /** * Returns a node for a Java primitive. */ @@ -319,6 +329,13 @@ } } + /** + * Returns a node for a constant double that's compatible to a given stamp. + */ + public static ConstantNode forFloatingStamp(Stamp stamp, double value, StructuredGraph graph) { + return forFloatingKind(stamp.getStackKind(), value, graph); + } + public static ConstantNode defaultForKind(Kind kind, StructuredGraph graph) { switch (kind) { case Boolean:
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -30,10 +30,10 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "&") -public final class AndNode extends BitLogicNode implements Canonicalizable { +public final class AndNode extends BitLogicNode implements Canonicalizable, NarrowableArithmeticNode { - public AndNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); + public AndNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); } @Override @@ -44,7 +44,7 @@ @Override public Constant evalConst(Constant... inputs) { assert inputs.length == 2; - return Constant.forIntegerKind(kind(), inputs[0].asLong() & inputs[1].asLong(), null); + return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() & inputs[1].asLong()); } @Override @@ -53,28 +53,18 @@ return x(); } if (x().isConstant() && !y().isConstant()) { - return graph().unique(new AndNode(kind(), y(), x())); + return graph().unique(new AndNode(stamp(), y(), x())); } if (x().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); + return ConstantNode.forPrimitive(stamp(), evalConst(x().asConstant(), y().asConstant()), graph()); } else if (y().isConstant()) { - if (kind() == Kind.Int) { - int c = y().asConstant().asInt(); - if (c == -1) { - return x(); - } - if (c == 0) { - return ConstantNode.forInt(0, graph()); - } - } else { - assert kind() == Kind.Long; - long c = y().asConstant().asLong(); - if (c == -1) { - return x(); - } - if (c == 0) { - return ConstantNode.forLong(0, graph()); - } + long rawY = y().asConstant().asLong(); + long mask = IntegerStamp.defaultMask(PrimitiveStamp.getBits(stamp())); + if ((rawY & mask) == mask) { + return x(); + } + if ((rawY & mask) == 0) { + return ConstantNode.forIntegerStamp(stamp(), 0, graph()); } return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; @@ -47,12 +46,12 @@ /** * Creates a new BinaryNode instance. * - * @param kind the result type of this instruction + * @param stamp the result type of this instruction * @param x the first input instruction * @param y the second input instruction */ - public BinaryNode(Kind kind, ValueNode x, ValueNode y) { - super(StampFactory.forKind(kind)); + public BinaryNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp); this.x = x; this.y = y; } @@ -84,53 +83,38 @@ } public static BinaryNode add(StructuredGraph graph, ValueNode x, ValueNode y) { - assert x.kind() == y.kind(); - switch (x.kind()) { - case Byte: - case Char: - case Short: - case Int: - case Long: - return IntegerArithmeticNode.add(graph, x, y); - case Float: - case Double: - return graph.unique(new FloatAddNode(x.kind(), x, y, false)); - default: - throw GraalInternalError.shouldNotReachHere(); + assert x.stamp().isCompatible(y.stamp()); + Stamp stamp = x.stamp(); + if (stamp instanceof IntegerStamp) { + return IntegerArithmeticNode.add(graph, x, y); + } else if (stamp instanceof FloatStamp) { + return graph.unique(new FloatAddNode(stamp, x, y, false)); + } else { + throw GraalInternalError.shouldNotReachHere(); } } public static BinaryNode sub(StructuredGraph graph, ValueNode x, ValueNode y) { - assert x.kind() == y.kind(); - switch (x.kind()) { - case Byte: - case Char: - case Short: - case Int: - case Long: - return IntegerArithmeticNode.sub(graph, x, y); - case Float: - case Double: - return graph.unique(new FloatSubNode(x.kind(), x, y, false)); - default: - throw GraalInternalError.shouldNotReachHere(); + assert x.stamp().isCompatible(y.stamp()); + Stamp stamp = x.stamp(); + if (stamp instanceof IntegerStamp) { + return IntegerArithmeticNode.sub(graph, x, y); + } else if (stamp instanceof FloatStamp) { + return graph.unique(new FloatSubNode(stamp, x, y, false)); + } else { + throw GraalInternalError.shouldNotReachHere(); } } public static BinaryNode mul(StructuredGraph graph, ValueNode x, ValueNode y) { - assert x.kind() == y.kind(); - switch (x.kind()) { - case Byte: - case Char: - case Short: - case Int: - case Long: - return IntegerArithmeticNode.mul(graph, x, y); - case Float: - case Double: - return graph.unique(new FloatMulNode(x.kind(), x, y, false)); - default: - throw GraalInternalError.shouldNotReachHere(); + assert x.stamp().isCompatible(y.stamp()); + Stamp stamp = x.stamp(); + if (stamp instanceof IntegerStamp) { + return IntegerArithmeticNode.mul(graph, x, y); + } else if (stamp instanceof FloatStamp) { + return graph.unique(new FloatMulNode(stamp, x, y, false)); + } else { + throw GraalInternalError.shouldNotReachHere(); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -22,14 +22,14 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; /** * The {@code LogicNode} class definition. */ -public abstract class BitLogicNode extends BinaryNode implements ArithmeticLIRLowerable { +public abstract class BitLogicNode extends BinaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { /** * Constructs a new logic operation node. @@ -37,44 +37,23 @@ * @param x the first input into this node * @param y the second input into this node */ - public BitLogicNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); - assert kind == Kind.Int || kind == Kind.Long; + public BitLogicNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); + assert stamp instanceof IntegerStamp; } public static BitLogicNode and(StructuredGraph graph, ValueNode v1, ValueNode v2) { - assert v1.kind() == v2.kind(); - switch (v1.kind()) { - case Int: - return graph.unique(new AndNode(Kind.Int, v1, v2)); - case Long: - return graph.unique(new AndNode(Kind.Long, v1, v2)); - default: - throw ValueNodeUtil.shouldNotReachHere(); - } + assert v1.stamp().isCompatible(v2.stamp()); + return graph.unique(new AndNode(StampTool.and(v1.stamp(), v2.stamp()), v1, v2)); } public static BitLogicNode or(StructuredGraph graph, ValueNode v1, ValueNode v2) { - assert v1.kind() == v2.kind(); - switch (v1.kind()) { - case Int: - return graph.unique(new OrNode(Kind.Int, v1, v2)); - case Long: - return graph.unique(new OrNode(Kind.Long, v1, v2)); - default: - throw ValueNodeUtil.shouldNotReachHere(); - } + assert v1.stamp().isCompatible(v2.stamp()); + return graph.unique(new OrNode(StampTool.or(v1.stamp(), v2.stamp()), v1, v2)); } public static BitLogicNode xor(StructuredGraph graph, ValueNode v1, ValueNode v2) { - assert v1.kind() == v2.kind(); - switch (v1.kind()) { - case Int: - return graph.unique(new XorNode(Kind.Int, v1, v2)); - case Long: - return graph.unique(new XorNode(Kind.Long, v1, v2)); - default: - throw ValueNodeUtil.shouldNotReachHere(); - } + assert v1.stamp().isCompatible(v2.stamp()); + return graph.unique(new XorNode(StampTool.xor(v1.stamp(), v2.stamp()), v1, v2)); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -49,8 +49,8 @@ } public ConditionalNode(LogicNode condition, ValueNode trueValue, ValueNode falseValue) { - super(trueValue.kind(), trueValue, falseValue); - assert trueValue.kind() == falseValue.kind(); + super(trueValue.stamp().meet(falseValue.stamp()), trueValue, falseValue); + assert trueValue.stamp().isCompatible(falseValue.stamp()); this.condition = condition; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; @@ -39,8 +38,8 @@ return y; } - public FixedBinaryNode(Kind kind, ValueNode x, ValueNode y) { - super(StampFactory.forKind(kind)); + public FixedBinaryNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp); this.x = x; this.y = y; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -27,20 +27,22 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "+") public final class FloatAddNode extends FloatArithmeticNode implements Canonicalizable { - public FloatAddNode(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - super(kind, x, y, isStrictFP); + public FloatAddNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) { + super(stamp, x, y, isStrictFP); } public Constant evalConst(Constant... inputs) { assert inputs.length == 2; - if (kind() == Kind.Float) { + assert inputs[0].getKind() == inputs[1].getKind(); + if (inputs[0].getKind() == Kind.Float) { return Constant.forFloat(inputs[0].asFloat() + inputs[1].asFloat()); } else { - assert kind() == Kind.Double; + assert inputs[0].getKind() == Kind.Double; return Constant.forDouble(inputs[0].asDouble() + inputs[1].asDouble()); } } @@ -48,22 +50,14 @@ @Override public Node canonical(CanonicalizerTool tool) { if (x().isConstant() && !y().isConstant()) { - return graph().unique(new FloatAddNode(kind(), y(), x(), isStrictFP())); + return graph().unique(new FloatAddNode(stamp(), y(), x(), isStrictFP())); } if (x().isConstant()) { return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); } else if (y().isConstant()) { - if (kind() == Kind.Float) { - float c = y().asConstant().asFloat(); - if (c == 0.0f) { - return x(); - } - } else { - assert kind() == Kind.Double; - double c = y().asConstant().asDouble(); - if (c == 0.0) { - return x(); - } + Constant c = y().asConstant(); + if ((c.getKind() == Kind.Float && c.asFloat() == 0.0f) || (c.getKind() == Kind.Double && c.asDouble() == 0.0)) { + return x(); } } return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatArithmeticNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -22,17 +22,17 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; public abstract class FloatArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable { private final boolean isStrictFP; - public FloatArithmeticNode(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - super(kind, x, y); - assert kind.isNumericFloat(); + public FloatArithmeticNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) { + super(stamp, x, y); + assert stamp instanceof FloatStamp; this.isStrictFP = isStrictFP; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -27,20 +27,22 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "/") public final class FloatDivNode extends FloatArithmeticNode implements Canonicalizable { - public FloatDivNode(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - super(kind, x, y, isStrictFP); + public FloatDivNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) { + super(stamp, x, y, isStrictFP); } public Constant evalConst(Constant... inputs) { assert inputs.length == 2; - if (kind() == Kind.Float) { + assert inputs[0].getKind() == inputs[1].getKind(); + if (inputs[0].getKind() == Kind.Float) { return Constant.forFloat(inputs[0].asFloat() / inputs[1].asFloat()); } else { - assert kind() == Kind.Double; + assert inputs[0].getKind() == Kind.Double; return Constant.forDouble(inputs[0].asDouble() / inputs[1].asDouble()); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -22,9 +22,9 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "==") public final class FloatEqualsNode extends CompareNode { @@ -37,8 +37,8 @@ */ public FloatEqualsNode(ValueNode x, ValueNode y) { super(x, y); - assert x.kind() == Kind.Double || x.kind() == Kind.Float; - assert y.kind() == Kind.Double || y.kind() == Kind.Float; + assert x.stamp() instanceof FloatStamp && y.stamp() instanceof FloatStamp; + assert x.stamp().isCompatible(y.stamp()); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -22,10 +22,10 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "<") public final class FloatLessThanNode extends CompareNode { @@ -42,8 +42,8 @@ */ public FloatLessThanNode(ValueNode x, ValueNode y, boolean unorderedIsTrue) { super(x, y); - assert x.kind() == Kind.Double || x.kind() == Kind.Float; - assert y.kind() == Kind.Double || y.kind() == Kind.Float; + assert x.stamp() instanceof FloatStamp && y.stamp() instanceof FloatStamp; + assert x.stamp().isCompatible(y.stamp()); this.unorderedIsTrue = unorderedIsTrue; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -27,20 +27,22 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "*") public final class FloatMulNode extends FloatArithmeticNode implements Canonicalizable { - public FloatMulNode(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - super(kind, x, y, isStrictFP); + public FloatMulNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) { + super(stamp, x, y, isStrictFP); } public Constant evalConst(Constant... inputs) { assert inputs.length == 2; - if (kind() == Kind.Float) { + assert inputs[0].getKind() == inputs[1].getKind(); + if (inputs[0].getKind() == Kind.Float) { return Constant.forFloat(inputs[0].asFloat() * inputs[1].asFloat()); } else { - assert kind() == Kind.Double; + assert inputs[0].getKind() == Kind.Double; return Constant.forDouble(inputs[0].asDouble() * inputs[1].asDouble()); } } @@ -48,7 +50,7 @@ @Override public Node canonical(CanonicalizerTool tool) { if (x().isConstant() && !y().isConstant()) { - return graph().unique(new FloatMulNode(kind(), y(), x(), isStrictFP())); + return graph().unique(new FloatMulNode(stamp(), y(), x(), isStrictFP())); } if (x().isConstant()) { return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -27,20 +27,22 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "%") public final class FloatRemNode extends FloatArithmeticNode implements Canonicalizable { - public FloatRemNode(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - super(kind, x, y, isStrictFP); + public FloatRemNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) { + super(stamp, x, y, isStrictFP); } public Constant evalConst(Constant... inputs) { assert inputs.length == 2; - if (kind() == Kind.Float) { + assert inputs[0].getKind() == inputs[1].getKind(); + if (inputs[0].getKind() == Kind.Float) { return Constant.forFloat(inputs[0].asFloat() % inputs[1].asFloat()); } else { - assert kind() == Kind.Double; + assert inputs[0].getKind() == Kind.Double; return Constant.forDouble(inputs[0].asDouble() % inputs[1].asDouble()); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -27,20 +27,22 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "-") public final class FloatSubNode extends FloatArithmeticNode implements Canonicalizable { - public FloatSubNode(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - super(kind, x, y, isStrictFP); + public FloatSubNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) { + super(stamp, x, y, isStrictFP); } public Constant evalConst(Constant... inputs) { assert inputs.length == 2; - if (kind() == Kind.Float) { + assert inputs[0].getKind() == inputs[1].getKind(); + if (inputs[0].getKind() == Kind.Float) { return Constant.forFloat(inputs[0].asFloat() - inputs[1].asFloat()); } else { - assert kind() == Kind.Double; + assert inputs[0].getKind() == Kind.Double; return Constant.forDouble(inputs[0].asDouble() - inputs[1].asDouble()); } } @@ -48,24 +50,25 @@ @Override public Node canonical(CanonicalizerTool tool) { if (x() == y()) { - return ConstantNode.forFloatingKind(kind(), 0.0f, graph()); + return ConstantNode.forFloatingStamp(stamp(), 0.0f, graph()); } if (x().isConstant() && y().isConstant()) { return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); } else if (y().isConstant()) { - if (kind() == Kind.Float) { - float c = y().asConstant().asFloat(); - if (c == 0.0f) { + Constant c = y().asConstant(); + if (c.getKind() == Kind.Float) { + float f = c.asFloat(); + if (f == 0.0f) { return x(); } - return graph().unique(new FloatAddNode(kind(), x(), ConstantNode.forFloat(-c, graph()), isStrictFP())); + return graph().unique(new FloatAddNode(stamp(), x(), ConstantNode.forFloat(-f, graph()), isStrictFP())); } else { - assert kind() == Kind.Double; - double c = y().asConstant().asDouble(); - if (c == 0.0) { + assert c.getKind() == Kind.Double; + double d = c.asDouble(); + if (d == 0.0) { return x(); } - return graph().unique(new FloatAddNode(kind(), x(), ConstantNode.forDouble(-c, graph()), isStrictFP())); + return graph().unique(new FloatAddNode(stamp(), x(), ConstantNode.forDouble(-d, graph()), isStrictFP())); } } return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -30,10 +30,10 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "+") -public class IntegerAddNode extends IntegerArithmeticNode implements Canonicalizable { +public class IntegerAddNode extends IntegerArithmeticNode implements Canonicalizable, NarrowableArithmeticNode { - public IntegerAddNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); + public IntegerAddNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); } @Override @@ -44,13 +44,13 @@ @Override public Constant evalConst(Constant... inputs) { assert inputs.length == 2; - return Constant.forIntegerKind(kind(), inputs[0].asLong() + inputs[1].asLong(), null); + return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() + inputs[1].asLong()); } @Override public Node canonical(CanonicalizerTool tool) { if (x().isConstant() && !y().isConstant()) { - return graph().unique(new IntegerAddNode(kind(), y(), x())); + return graph().unique(new IntegerAddNode(stamp(), y(), x())); } if (x() instanceof IntegerSubNode) { IntegerSubNode sub = (IntegerSubNode) x(); @@ -79,12 +79,7 @@ return reassociated; } if (c < 0) { - if (kind() == Kind.Int) { - return IntegerArithmeticNode.sub(graph(), x(), ConstantNode.forInt((int) -c, graph())); - } else { - assert kind() == Kind.Long; - return IntegerArithmeticNode.sub(graph(), x(), ConstantNode.forLong(-c, graph())); - } + return IntegerArithmeticNode.sub(graph(), x(), ConstantNode.forIntegerStamp(stamp(), -c, graph())); } } if (x() instanceof NegateNode) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -22,29 +22,27 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; public abstract class IntegerArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable { - public IntegerArithmeticNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); - assert kind.isNumericInteger(); + public IntegerArithmeticNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); + assert stamp instanceof IntegerStamp; } public static IntegerAddNode add(StructuredGraph graph, ValueNode v1, ValueNode v2) { - assert v1.kind() == v2.kind(); - return graph.unique(new IntegerAddNode(v1.kind(), v1, v2)); + return graph.unique(new IntegerAddNode(StampTool.add(v1.stamp(), v2.stamp()), v1, v2)); } public static IntegerMulNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2) { - assert v1.kind() == v2.kind(); - return graph.unique(new IntegerMulNode(v1.kind(), v1, v2)); + assert v1.stamp().isCompatible(v2.stamp()); + return graph.unique(new IntegerMulNode(v1.stamp().unrestricted(), v1, v2)); } public static IntegerSubNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2) { - assert v1.kind() == v2.kind(); - return graph.unique(new IntegerSubNode(v1.kind(), v1, v2)); + return graph.unique(new IntegerSubNode(StampTool.sub(v1.stamp(), v2.stamp()), v1, v2)); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -23,8 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -32,7 +30,7 @@ /** * An {@code IntegerConvert} converts an integer to an integer of different width. */ -public abstract class IntegerConvertNode extends ConvertNode implements Canonicalizable, ArithmeticLIRLowerable { +public abstract class IntegerConvertNode extends ConvertNode implements ArithmeticLIRLowerable { private final int resultBits; @@ -61,8 +59,7 @@ } } - @Override - public Node canonical(CanonicalizerTool tool) { + protected ValueNode canonicalConvert() { if (getInput().stamp() instanceof IntegerStamp) { int inputBits = ((IntegerStamp) getInput().stamp()).getBits(); if (inputBits == resultBits) { @@ -73,7 +70,7 @@ } } - return this; + return null; } public static ValueNode convert(ValueNode input, Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; @@ -33,8 +32,8 @@ @NodeInfo(shortName = "/") public class IntegerDivNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { - public IntegerDivNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); + public IntegerDivNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); } @Override @@ -45,16 +44,11 @@ @Override public Node canonical(CanonicalizerTool tool) { if (x().isConstant() && y().isConstant()) { - long yConst = y().asConstant().asLong(); - if (yConst == 0) { + long y = y().asConstant().asLong(); + if (y == 0) { return this; // this will trap, can not canonicalize } - if (kind() == Kind.Int) { - return ConstantNode.forInt(x().asConstant().asInt() / (int) yConst, graph()); - } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(x().asConstant().asLong() / yConst, graph()); - } + return ConstantNode.forIntegerStamp(stamp(), x().asConstant().asLong() / y, graph()); } else if (y().isConstant()) { long c = y().asConstant().asLong(); if (c == 1) { @@ -65,23 +59,18 @@ } long abs = Math.abs(c); if (CodeUtil.isPowerOf2(abs) && x().stamp() instanceof IntegerStamp) { + Stamp unrestricted = stamp().unrestricted(); ValueNode dividend = x(); IntegerStamp stampX = (IntegerStamp) x().stamp(); int log2 = CodeUtil.log2(abs); // no rounding if dividend is positive or if its low bits are always 0 if (stampX.canBeNegative() || (stampX.upMask() & (abs - 1)) != 0) { - int bits; - if (kind().getStackKind() == Kind.Int) { - bits = 32; - } else { - assert kind() == Kind.Long; - bits = 64; - } - RightShiftNode sign = graph().unique(new RightShiftNode(kind(), x(), ConstantNode.forInt(bits - 1, graph()))); - UnsignedRightShiftNode round = graph().unique(new UnsignedRightShiftNode(kind(), sign, ConstantNode.forInt(bits - log2, graph()))); + int bits = PrimitiveStamp.getBits(stamp()); + RightShiftNode sign = graph().unique(new RightShiftNode(unrestricted, x(), ConstantNode.forInt(bits - 1, graph()))); + UnsignedRightShiftNode round = graph().unique(new UnsignedRightShiftNode(unrestricted, sign, ConstantNode.forInt(bits - log2, graph()))); dividend = IntegerArithmeticNode.add(graph(), dividend, round); } - RightShiftNode shift = graph().unique(new RightShiftNode(kind(), dividend, ConstantNode.forInt(log2, graph()))); + RightShiftNode shift = graph().unique(new RightShiftNode(unrestricted, dividend, ConstantNode.forInt(log2, graph()))); if (c < 0) { return graph().unique(new NegateNode(shift)); } @@ -94,8 +83,9 @@ IntegerSubNode integerSubNode = (IntegerSubNode) x(); if (integerSubNode.y() instanceof IntegerRemNode) { IntegerRemNode integerRemNode = (IntegerRemNode) integerSubNode.y(); - if (integerSubNode.kind() == this.kind() && integerRemNode.kind() == this.kind() && integerSubNode.x() == integerRemNode.x() && this.y() == integerRemNode.y()) { - return graph().add(new IntegerDivNode(kind(), integerSubNode.x(), this.y())); + if (integerSubNode.stamp().isCompatible(this.stamp()) && integerRemNode.stamp().isCompatible(this.stamp()) && integerSubNode.x() == integerRemNode.x() && + this.y() == integerRemNode.y()) { + return graph().add(new IntegerDivNode(stamp(), integerSubNode.x(), this.y())); } } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -28,24 +28,25 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "*") -public class IntegerMulNode extends IntegerArithmeticNode implements Canonicalizable { +public class IntegerMulNode extends IntegerArithmeticNode implements Canonicalizable, NarrowableArithmeticNode { - public IntegerMulNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); + public IntegerMulNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); } @Override public Constant evalConst(Constant... inputs) { assert inputs.length == 2; - return Constant.forIntegerKind(kind(), inputs[0].asLong() * inputs[1].asLong(), null); + return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() * inputs[1].asLong()); } @Override public Node canonical(CanonicalizerTool tool) { if (x().isConstant() && !y().isConstant()) { - return graph().unique(new IntegerMulNode(kind(), y(), x())); + return graph().unique(new IntegerMulNode(stamp(), y(), x())); } if (x().isConstant()) { return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); @@ -55,11 +56,11 @@ return x(); } if (c == 0) { - return ConstantNode.defaultForKind(kind(), graph()); + return ConstantNode.forIntegerStamp(stamp(), 0, graph()); } long abs = Math.abs(c); if (abs > 0 && CodeUtil.isPowerOf2(abs)) { - LeftShiftNode shift = graph().unique(new LeftShiftNode(kind(), x(), ConstantNode.forInt(CodeUtil.log2(abs), graph()))); + LeftShiftNode shift = graph().unique(new LeftShiftNode(stamp().unrestricted(), x(), ConstantNode.forInt(CodeUtil.log2(abs), graph()))); if (c < 0) { return graph().unique(new NegateNode(shift)); } else {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; @@ -33,29 +32,24 @@ @NodeInfo(shortName = "%") public class IntegerRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { - public IntegerRemNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); + public IntegerRemNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); } @Override public Node canonical(CanonicalizerTool tool) { if (x().isConstant() && y().isConstant()) { - long yConst = y().asConstant().asLong(); - if (yConst == 0) { + long y = y().asConstant().asLong(); + if (y == 0) { return this; // this will trap, can not canonicalize } - if (kind() == Kind.Int) { - return ConstantNode.forInt(x().asConstant().asInt() % (int) yConst, graph()); - } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(x().asConstant().asLong() % yConst, graph()); - } + return ConstantNode.forIntegerStamp(stamp(), x().asConstant().asLong() % y, graph()); } else if (y().isConstant()) { long c = y().asConstant().asLong(); if (c == 1 || c == -1) { - return ConstantNode.forIntegerKind(kind(), 0, graph()); + return ConstantNode.forIntegerStamp(stamp(), 0, graph()); } else if (c > 0 && CodeUtil.isPowerOf2(c) && x().stamp() instanceof IntegerStamp && ((IntegerStamp) x().stamp()).isPositive()) { - return graph().unique(new AndNode(kind(), x(), ConstantNode.forIntegerKind(kind(), c - 1, graph()))); + return graph().unique(new AndNode(stamp(), x(), ConstantNode.forIntegerStamp(stamp(), c - 1, graph()))); } } return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -30,10 +30,10 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "-") -public class IntegerSubNode extends IntegerArithmeticNode implements Canonicalizable { +public class IntegerSubNode extends IntegerArithmeticNode implements Canonicalizable, NarrowableArithmeticNode { - public IntegerSubNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); + public IntegerSubNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); } @Override @@ -44,13 +44,13 @@ @Override public Constant evalConst(Constant... inputs) { assert inputs.length == 2; - return Constant.forIntegerKind(kind(), inputs[0].asLong() - inputs[1].asLong(), null); + return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() - inputs[1].asLong()); } @Override public Node canonical(CanonicalizerTool tool) { if (x() == y()) { - return ConstantNode.forIntegerKind(kind(), 0, graph()); + return ConstantNode.forIntegerStamp(stamp(), 0, graph()); } if (x() instanceof IntegerAddNode) { IntegerAddNode x = (IntegerAddNode) x(); @@ -98,12 +98,7 @@ return reassociated; } if (c < 0) { - if (kind() == Kind.Int) { - return IntegerArithmeticNode.add(graph(), x(), ConstantNode.forInt((int) -c, graph())); - } else { - assert kind() == Kind.Long; - return IntegerArithmeticNode.add(graph(), x(), ConstantNode.forLong(-c, graph())); - } + return IntegerArithmeticNode.add(graph(), x(), ConstantNode.forIntegerStamp(stamp(), -c, graph())); } } else if (x().isConstant()) { long c = x().asConstant().asLong();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -53,7 +53,7 @@ * @param y the instruction that produces the second input to this instruction */ public IntegerTestNode(ValueNode x, ValueNode y) { - assert (x == null && y == null) || x.kind() == y.kind(); + assert (x == null && y == null) || x.stamp().isCompatible(y.stamp()); this.x = x; this.y = y; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -32,8 +32,8 @@ @NodeInfo(shortName = "<<") public final class LeftShiftNode extends ShiftNode implements Canonicalizable { - public LeftShiftNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); + public LeftShiftNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); } @Override @@ -79,19 +79,19 @@ if (total != (total & mask)) { return ConstantNode.forIntegerKind(kind(), 0, graph()); } - return graph().unique(new LeftShiftNode(kind(), other.x(), ConstantNode.forInt(total, graph()))); + return graph().unique(new LeftShiftNode(stamp(), other.x(), ConstantNode.forInt(total, graph()))); } else if ((other instanceof RightShiftNode || other instanceof UnsignedRightShiftNode) && otherAmount == amount) { if (kind() == Kind.Long) { - return graph().unique(new AndNode(kind(), other.x(), ConstantNode.forLong(-1L << amount, graph()))); + return graph().unique(new AndNode(stamp(), other.x(), ConstantNode.forLong(-1L << amount, graph()))); } else { assert kind() == Kind.Int; - return graph().unique(new AndNode(kind(), other.x(), ConstantNode.forInt(-1 << amount, graph()))); + return graph().unique(new AndNode(stamp(), other.x(), ConstantNode.forInt(-1 << amount, graph()))); } } } } if (originalAmout != amount) { - return graph().unique(new LeftShiftNode(kind(), x(), ConstantNode.forInt(amount, graph()))); + return graph().unique(new LeftShiftNode(stamp(), x(), ConstantNode.forInt(amount, graph()))); } } return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -32,7 +32,7 @@ /** * The {@code NarrowNode} converts an integer to a narrower integer. */ -public class NarrowNode extends IntegerConvertNode { +public class NarrowNode extends IntegerConvertNode implements Simplifiable { public NarrowNode(ValueNode input, int resultBits) { super(StampTool.narrowingConversion(input.stamp(), resultBits), input, resultBits); @@ -64,28 +64,70 @@ return false; } - @Override - public Node canonical(CanonicalizerTool tool) { + private ValueNode tryCanonicalize() { + ValueNode ret = canonicalConvert(); + if (ret != null) { + return ret; + } + if (getInput() instanceof NarrowNode) { + // zzzzzzzz yyyyxxxx -(narrow)-> yyyyxxxx -(narrow)-> xxxx + // ==> zzzzzzzz yyyyxxxx -(narrow)-> xxxx NarrowNode other = (NarrowNode) getInput(); return graph().unique(new NarrowNode(other.getInput(), getResultBits())); } else if (getInput() instanceof IntegerConvertNode) { // SignExtendNode or ZeroExtendNode IntegerConvertNode other = (IntegerConvertNode) getInput(); if (getResultBits() == other.getInputBits()) { + // xxxx -(extend)-> yyyy xxxx -(narrow)-> xxxx + // ==> no-op return other.getInput(); } else if (getResultBits() < other.getInputBits()) { + // yyyyxxxx -(extend)-> zzzzzzzz yyyyxxxx -(narrow)-> xxxx + // ==> yyyyxxxx -(narrow)-> xxxx return graph().unique(new NarrowNode(other.getInput(), getResultBits())); } else { if (other instanceof SignExtendNode) { + // sxxx -(sign-extend)-> ssssssss sssssxxx -(narrow)-> sssssxxx + // ==> sxxx -(sign-extend)-> sssssxxx return graph().unique(new SignExtendNode(other.getInput(), getResultBits())); } else if (other instanceof ZeroExtendNode) { + // xxxx -(zero-extend)-> 00000000 00000xxx -(narrow)-> 0000xxxx + // ==> xxxx -(zero-extend)-> 0000xxxx return graph().unique(new ZeroExtendNode(other.getInput(), getResultBits())); } } } - return super.canonical(tool); + return null; + } + + private boolean tryNarrow(SimplifierTool tool, Stamp stamp, ValueNode node) { + boolean canNarrow = node instanceof NarrowableArithmeticNode && node.usages().count() == 1; + + if (canNarrow) { + for (Node inputNode : node.inputs().snapshot()) { + ValueNode input = (ValueNode) inputNode; + if (!tryNarrow(tool, stamp, input)) { + ValueNode narrow = graph().unique(new NarrowNode(input, getResultBits())); + node.replaceFirstInput(input, narrow); + tool.addToWorkList(narrow); + } + } + node.setStamp(stamp); + } + + return canNarrow; + } + + @Override + public void simplify(SimplifierTool tool) { + ValueNode ret = tryCanonicalize(); + if (ret != null) { + graph().replaceFloating(this, ret); + } else if (tryNarrow(tool, stamp().unrestricted(), getInput())) { + graph().replaceFloating(this, getInput()); + } } @Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowableArithmeticNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.calc; + +/** + * Marker interface for nodes where it is valid to apply a {@link NarrowNode} to its inputs and do a + * narrow operation instead of doing the wide operation and applying the {@link NarrowNode} to the + * result. + */ +public interface NarrowableArithmeticNode { +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -32,7 +32,7 @@ /** * The {@code NegateNode} node negates its operand. */ -public final class NegateNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable { +public final class NegateNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable, NarrowableArithmeticNode { @Input private ValueNode x;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; /** * Returns -1, 0, or 1 if either x < y, x == y, or x > y. If the comparison is undecided (one of the @@ -43,7 +44,7 @@ * less, false when greater. */ public NormalizeCompareNode(ValueNode x, ValueNode y, boolean isUnorderedLess) { - super(Kind.Int, x, y); + super(StampFactory.forKind(Kind.Int), x, y); this.isUnorderedLess = isUnorderedLess; } @@ -51,7 +52,7 @@ public void lower(LoweringTool tool) { LogicNode equalComp; LogicNode lessComp; - if (x().kind() == Kind.Double || x().kind() == Kind.Float) { + if (x().stamp() instanceof FloatStamp) { equalComp = graph().unique(new FloatEqualsNode(x(), y())); lessComp = graph().unique(new FloatLessThanNode(x(), y(), isUnorderedLess)); } else {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -32,7 +32,7 @@ /** * Binary negation of long or integer values. */ -public final class NotNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable { +public final class NotNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable, NarrowableArithmeticNode { @Input private ValueNode x; @@ -48,7 +48,7 @@ @Override public Constant evalConst(Constant... inputs) { assert inputs.length == 1; - return Constant.forIntegerKind(kind(), ~inputs[0].asLong(), null); + return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), ~inputs[0].asLong()); } /** @@ -58,7 +58,6 @@ */ public NotNode(ValueNode x) { super(StampTool.not(x.stamp())); - assert x.kind() == Kind.Int || x.kind() == Kind.Long; this.x = x; }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -32,8 +32,8 @@ @NodeInfo(shortName = "|") public final class OrNode extends BitLogicNode implements Canonicalizable { - public OrNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); + public OrNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); } @Override @@ -44,7 +44,7 @@ @Override public Constant evalConst(Constant... inputs) { assert inputs.length == 2; - return Constant.forIntegerKind(kind(), inputs[0].asLong() | inputs[1].asLong(), null); + return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() | inputs[1].asLong()); } @Override @@ -53,28 +53,18 @@ return x(); } if (x().isConstant() && !y().isConstant()) { - return graph().unique(new OrNode(kind(), y(), x())); + return graph().unique(new OrNode(stamp(), y(), x())); } if (x().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); + return ConstantNode.forPrimitive(stamp(), evalConst(x().asConstant(), y().asConstant()), graph()); } else if (y().isConstant()) { - if (kind() == Kind.Int) { - int c = y().asConstant().asInt(); - if (c == -1) { - return ConstantNode.forInt(-1, graph()); - } - if (c == 0) { - return x(); - } - } else { - assert kind() == Kind.Long; - long c = y().asConstant().asLong(); - if (c == -1) { - return ConstantNode.forLong(-1, graph()); - } - if (c == 0) { - return x(); - } + long rawY = y().asConstant().asLong(); + long mask = IntegerStamp.defaultMask(PrimitiveStamp.getBits(stamp())); + if ((rawY & mask) == mask) { + return ConstantNode.forIntegerStamp(stamp(), mask, graph()); + } + if ((rawY & mask) == 0) { + return x(); } return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -32,8 +32,8 @@ @NodeInfo(shortName = ">>") public final class RightShiftNode extends ShiftNode implements Canonicalizable { - public RightShiftNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); + public RightShiftNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); } @Override @@ -50,7 +50,7 @@ @Override public Node canonical(CanonicalizerTool tool) { if (x().stamp() instanceof IntegerStamp && ((IntegerStamp) x().stamp()).isPositive()) { - return graph().unique(new UnsignedRightShiftNode(kind(), x(), y())); + return graph().unique(new UnsignedRightShiftNode(stamp(), x(), y())); } if (x().isConstant() && y().isConstant()) { return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); @@ -90,14 +90,14 @@ * full shift for this kind */ assert total >= mask; - return graph().unique(new RightShiftNode(kind(), other.x(), ConstantNode.forInt(mask, graph()))); + return graph().unique(new RightShiftNode(stamp(), other.x(), ConstantNode.forInt(mask, graph()))); } - return graph().unique(new RightShiftNode(kind(), other.x(), ConstantNode.forInt(total, graph()))); + return graph().unique(new RightShiftNode(stamp(), other.x(), ConstantNode.forInt(total, graph()))); } } } if (originalAmout != amount) { - return graph().unique(new RightShiftNode(kind(), x(), ConstantNode.forInt(amount, graph()))); + return graph().unique(new RightShiftNode(stamp(), x(), ConstantNode.forInt(amount, graph()))); } } return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -22,9 +22,9 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; /** * The {@code ShiftOp} class represents shift operations. @@ -37,7 +37,7 @@ * @param x the first input value * @param s the second input value */ - public ShiftNode(Kind kind, ValueNode x, ValueNode s) { - super(kind, x, s); + public ShiftNode(Stamp stamp, ValueNode x, ValueNode s) { + super(stamp, x, s); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -32,7 +32,7 @@ /** * The {@code SignExtendNode} converts an integer to a wider integer using sign extension. */ -public class SignExtendNode extends IntegerConvertNode { +public class SignExtendNode extends IntegerConvertNode implements Canonicalizable { public SignExtendNode(ValueNode input, int resultBits) { super(StampTool.signExtend(input.stamp(), resultBits), input, resultBits); @@ -67,12 +67,21 @@ @Override public Node canonical(CanonicalizerTool tool) { + ValueNode ret = canonicalConvert(); + if (ret != null) { + return ret; + } + if (getInput() instanceof SignExtendNode) { + // sxxx -(sign-extend)-> ssss sxxx -(sign-extend)-> ssssssss sssssxxx + // ==> sxxx -(sign-extend)-> ssssssss sssssxxx SignExtendNode other = (SignExtendNode) getInput(); return graph().unique(new SignExtendNode(other.getInput(), getResultBits())); } else if (getInput() instanceof ZeroExtendNode) { ZeroExtendNode other = (ZeroExtendNode) getInput(); if (other.getResultBits() > other.getInputBits()) { + // sxxx -(zero-extend)-> 0000 sxxx -(sign-extend)-> 00000000 0000sxxx + // ==> sxxx -(zero-extend)-> 00000000 0000sxxx return graph().unique(new ZeroExtendNode(other.getInput(), getResultBits())); } } @@ -80,11 +89,13 @@ if (getInput().stamp() instanceof IntegerStamp) { IntegerStamp inputStamp = (IntegerStamp) getInput().stamp(); if ((inputStamp.upMask() & (1L << (getInputBits() - 1))) == 0L) { + // 0xxx -(sign-extend)-> 0000 0xxx + // ==> 0xxx -(zero-extend)-> 0000 0xxx return graph().unique(new ZeroExtendNode(getInput(), getResultBits())); } } - return super.canonical(tool); + return this; } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -33,8 +33,16 @@ @NodeInfo(shortName = "|/|") public class UnsignedDivNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { - public UnsignedDivNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); + /** + * Used by {@code NodeIntrinsic} in {@code UnsignedMathSubstitutions}. + */ + @SuppressWarnings("unused") + private UnsignedDivNode(Kind kind, ValueNode x, ValueNode y) { + this(StampFactory.forKind(kind), x, y); + } + + public UnsignedDivNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); } @Override @@ -44,19 +52,14 @@ if (yConst == 0) { return this; // this will trap, cannot canonicalize } - if (kind() == Kind.Int) { - return ConstantNode.forInt(UnsignedMath.divide(x().asConstant().asInt(), (int) yConst), graph()); - } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(UnsignedMath.divide(x().asConstant().asLong(), yConst), graph()); - } + return ConstantNode.forIntegerStamp(stamp(), UnsignedMath.divide(x().asConstant().asLong(), yConst), graph()); } else if (y().isConstant()) { long c = y().asConstant().asLong(); if (c == 1) { return x(); } if (CodeUtil.isPowerOf2(c)) { - return graph().unique(new UnsignedRightShiftNode(kind(), x(), ConstantNode.forInt(CodeUtil.log2(c), graph()))); + return graph().unique(new UnsignedRightShiftNode(stamp(), x(), ConstantNode.forInt(CodeUtil.log2(c), graph()))); } } return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -33,8 +33,16 @@ @NodeInfo(shortName = "|%|") public class UnsignedRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable { - public UnsignedRemNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); + /** + * Used by {@code NodeIntrinsic} in {@code UnsignedMathSubstitutions}. + */ + @SuppressWarnings("unused") + private UnsignedRemNode(Kind kind, ValueNode x, ValueNode y) { + this(StampFactory.forKind(kind), x, y); + } + + public UnsignedRemNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); } @Override @@ -44,18 +52,13 @@ if (yConst == 0) { return this; // this will trap, cannot canonicalize } - if (kind() == Kind.Int) { - return ConstantNode.forInt(UnsignedMath.remainder(x().asConstant().asInt(), (int) yConst), graph()); - } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(UnsignedMath.remainder(x().asConstant().asLong(), yConst), graph()); - } + return ConstantNode.forIntegerStamp(stamp(), UnsignedMath.remainder(x().asConstant().asLong(), yConst), graph()); } else if (y().isConstant()) { long c = y().asConstant().asLong(); if (c == 1) { - return ConstantNode.forIntegerKind(kind(), 0, graph()); + return ConstantNode.forIntegerStamp(stamp(), 0, graph()); } else if (CodeUtil.isPowerOf2(c)) { - return graph().unique(new AndNode(kind(), x(), ConstantNode.forIntegerKind(kind(), c - 1, graph()))); + return graph().unique(new AndNode(stamp(), x(), ConstantNode.forIntegerStamp(stamp(), c - 1, graph()))); } } return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -32,8 +32,8 @@ @NodeInfo(shortName = ">>>") public final class UnsignedRightShiftNode extends ShiftNode implements Canonicalizable { - public UnsignedRightShiftNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); + public UnsignedRightShiftNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); } @Override @@ -79,19 +79,19 @@ if (total != (total & mask)) { return ConstantNode.forIntegerKind(kind(), 0, graph()); } - return graph().unique(new UnsignedRightShiftNode(kind(), other.x(), ConstantNode.forInt(total, graph()))); + return graph().unique(new UnsignedRightShiftNode(stamp(), other.x(), ConstantNode.forInt(total, graph()))); } else if (other instanceof LeftShiftNode && otherAmount == amount) { if (kind() == Kind.Long) { - return graph().unique(new AndNode(kind(), other.x(), ConstantNode.forLong(-1L >>> amount, graph()))); + return graph().unique(new AndNode(stamp(), other.x(), ConstantNode.forLong(-1L >>> amount, graph()))); } else { assert kind() == Kind.Int; - return graph().unique(new AndNode(kind(), other.x(), ConstantNode.forInt(-1 >>> amount, graph()))); + return graph().unique(new AndNode(stamp(), other.x(), ConstantNode.forInt(-1 >>> amount, graph()))); } } } } if (originalAmout != amount) { - return graph().unique(new UnsignedRightShiftNode(kind(), x(), ConstantNode.forInt(amount, graph()))); + return graph().unique(new UnsignedRightShiftNode(stamp(), x(), ConstantNode.forInt(amount, graph()))); } } return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -32,8 +32,8 @@ @NodeInfo(shortName = "^") public final class XorNode extends BitLogicNode implements Canonicalizable { - public XorNode(Kind kind, ValueNode x, ValueNode y) { - super(kind, x, y); + public XorNode(Stamp stamp, ValueNode x, ValueNode y) { + super(stamp, x, y); } @Override @@ -44,35 +44,26 @@ @Override public Constant evalConst(Constant... inputs) { assert inputs.length == 2; - return Constant.forIntegerKind(kind(), inputs[0].asLong() ^ inputs[1].asLong(), null); + return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() ^ inputs[1].asLong()); } @Override public Node canonical(CanonicalizerTool tool) { if (x() == y()) { - return ConstantNode.forIntegerKind(kind(), 0, graph()); + return ConstantNode.forIntegerStamp(stamp(), 0, graph()); } if (x().isConstant() && !y().isConstant()) { - return graph().unique(new XorNode(kind(), y(), x())); + return graph().unique(new XorNode(stamp(), y(), x())); } if (x().isConstant()) { - return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); + return ConstantNode.forPrimitive(stamp(), evalConst(x().asConstant(), y().asConstant()), graph()); } else if (y().isConstant()) { - if (kind() == Kind.Int) { - int c = y().asConstant().asInt(); - if (c == 0) { - return x(); - } else if (c == -1) { - return graph().unique(new NotNode(x())); - } - } else { - assert kind() == Kind.Long; - long c = y().asConstant().asLong(); - if (c == 0) { - return x(); - } else if (c == -1) { - return graph().unique(new NotNode(x())); - } + long rawY = y().asConstant().asLong(); + long mask = IntegerStamp.defaultMask(PrimitiveStamp.getBits(stamp())); + if ((rawY & mask) == 0) { + return x(); + } else if ((rawY & mask) == mask) { + return graph().unique(new NotNode(x())); } return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -32,7 +32,7 @@ /** * The {@code ZeroExtendNode} converts an integer to a wider integer using zero extension. */ -public class ZeroExtendNode extends IntegerConvertNode { +public class ZeroExtendNode extends IntegerConvertNode implements Canonicalizable { public ZeroExtendNode(ValueNode input, int resultBits) { super(StampTool.zeroExtend(input.stamp(), resultBits), input, resultBits); @@ -63,12 +63,19 @@ @Override public Node canonical(CanonicalizerTool tool) { + ValueNode ret = canonicalConvert(); + if (ret != null) { + return ret; + } + if (getInput() instanceof ZeroExtendNode) { + // xxxx -(zero-extend)-> 0000 xxxx -(zero-extend)-> 00000000 0000xxxx + // ==> xxxx -(zero-extend)-> 00000000 0000xxxx ZeroExtendNode other = (ZeroExtendNode) getInput(); return graph().unique(new ZeroExtendNode(other.getInput(), getResultBits())); } - return super.canonical(tool); + return this; } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -76,7 +76,7 @@ if (ObjectStamp.isObjectAlwaysNull(object())) { return object(); } - if (hub.isConstant() && hub.kind() == Kind.Object && hub.asConstant().asObject() instanceof Class) { + if (hub.isConstant() && hub.asConstant().getKind() == Kind.Object && hub.asConstant().asObject() instanceof Class) { Class clazz = (Class) hub.asConstant().asObject(); ResolvedJavaType t = tool.getMetaAccess().lookupJavaType(clazz); return graph().add(new CheckCastNode(t, object(), null, forStoreCheck));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -64,7 +64,7 @@ public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue) { super(StampFactory.forKind(Kind.Boolean.getStackKind())); - assert expected.kind() == newValue.kind(); + assert expected.stamp().isCompatible(newValue.stamp()); this.object = object; this.offset = offset; this.expected = expected;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java Fri Feb 28 16:19:10 2014 +0100 @@ -29,7 +29,7 @@ public final class GenericStamp extends Stamp { public enum GenericStampType { - Dependency, Extension, Condition, Void + Dependency, Extension, Condition } private final GenericStampType type; @@ -49,11 +49,7 @@ @Override public Kind getStackKind() { - if (type == GenericStampType.Void) { - return Kind.Void; - } else { - return Kind.Illegal; - } + return Kind.Illegal; } @Override @@ -63,8 +59,7 @@ @Override public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { - assert type == GenericStampType.Void; - return metaAccess.lookupJavaType(Void.TYPE); + throw GraalInternalError.shouldNotReachHere(type + " stamp has not Java type"); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Fri Feb 28 16:19:10 2014 +0100 @@ -38,7 +38,6 @@ private static final Stamp dependencyStamp = new GenericStamp(GenericStampType.Dependency); private static final Stamp extensionStamp = new GenericStamp(GenericStampType.Extension); private static final Stamp conditionStamp = new GenericStamp(GenericStampType.Condition); - private static final Stamp voidStamp = new GenericStamp(GenericStampType.Void); private static final Stamp nodeIntrinsicStamp = new ObjectStamp(null, false, false, false); private static final Stamp positiveInt = forInteger(Kind.Int, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); @@ -73,7 +72,7 @@ setFloatCache(Kind.Double); setCache(Kind.Object, objectStamp); - setCache(Kind.Void, voidStamp); + setCache(Kind.Void, VoidStamp.getInstance()); for (Kind k : Kind.values()) { illegalStampCache[k.ordinal()] = new IllegalStamp(k); } @@ -87,8 +86,12 @@ return stampCache[kind.ordinal()]; } + /** + * Return the stamp for the {@code void} type. This will return a singleton instance than can be + * compared using {@code ==}. + */ public static Stamp forVoid() { - return voidStamp; + return VoidStamp.getInstance(); } /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Fri Feb 28 16:19:10 2014 +0100 @@ -369,16 +369,6 @@ } } - public static Stamp intToLong(IntegerStamp intStamp) { - long downMask = intStamp.downMask(); - long upMask = intStamp.upMask(); - if (!intStamp.isUnsigned()) { - downMask = SignExtendNode.signExtend(downMask, intStamp.getBits()); - upMask = SignExtendNode.signExtend(upMask, intStamp.getBits()); - } - return new IntegerStamp(64, intStamp.isUnsigned(), intStamp.lowerBound(), intStamp.upperBound(), downMask, upMask); - } - public static Stamp narrowingConversion(Stamp input, int resultBits) { if (input instanceof IntegerStamp) { IntegerStamp inputStamp = (IntegerStamp) input;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/VoidStamp.java Fri Feb 28 16:19:10 2014 +0100 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.type; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Singleton stamp representing the value of type {@code void}. + */ +public final class VoidStamp extends Stamp { + + private VoidStamp() { + } + + @Override + public Stamp unrestricted() { + return this; + } + + @Override + public Kind getStackKind() { + return Kind.Void; + } + + @Override + public PlatformKind getPlatformKind(LIRTypeTool tool) { + throw GraalInternalError.shouldNotReachHere("void stamp has no value"); + } + + @Override + public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { + return metaAccess.lookupJavaType(Void.TYPE); + } + + @Override + public String toString() { + return "void"; + } + + @Override + public boolean alwaysDistinct(Stamp other) { + return this != other; + } + + @Override + public Stamp meet(Stamp other) { + if (other instanceof IllegalStamp) { + return other.join(this); + } + if (this == other) { + return this; + } + return StampFactory.illegal(Kind.Illegal); + } + + @Override + public Stamp join(Stamp other) { + if (other instanceof IllegalStamp) { + return other.join(this); + } + if (this == other) { + return this; + } + return StampFactory.illegal(Kind.Illegal); + } + + @Override + public boolean isCompatible(Stamp stamp) { + return this == stamp; + } + + private static VoidStamp instance = new VoidStamp(); + + static VoidStamp getInstance() { + return instance; + } +}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Fri Feb 28 16:19:10 2014 +0100 @@ -185,7 +185,7 @@ boolean improvedStamp = tryInferStamp(valueNode); Constant constant = valueNode.stamp().asConstant(); if (constant != null && !(node instanceof ConstantNode)) { - performReplacement(valueNode, ConstantNode.forConstant(constant, context.getMetaAccess(), valueNode.graph())); + performReplacement(valueNode, ConstantNode.forConstant(valueNode.stamp(), constant, context.getMetaAccess(), valueNode.graph())); } else if (improvedStamp) { // the improved stamp may enable additional canonicalization tryCanonicalize(valueNode, nodeClass);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/UnsignedMathTest.java Fri Feb 28 16:19:10 2014 +0100 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.test.*; + +/** + * Tests the substitutions for the {@link UnsignedMath} class. + */ +public class UnsignedMathTest extends GraalCompilerTest { + + public static boolean aboveThanInt(int a, int b) { + return UnsignedMath.aboveThan(a, b); + } + + public static boolean aboveOrEqualInt(int a, int b) { + return UnsignedMath.aboveOrEqual(a, b); + } + + public static boolean belowThanInt(int a, int b) { + return UnsignedMath.belowThan(a, b); + } + + public static boolean belowOrEqualInt(int a, int b) { + return UnsignedMath.belowOrEqual(a, b); + } + + public static int divideInt(int a, int b) { + return UnsignedMath.divide(a, b); + } + + public static int remainderInt(int a, int b) { + return UnsignedMath.remainder(a, b); + } + + public static boolean aboveThanLong(long a, long b) { + return UnsignedMath.aboveThan(a, b); + } + + public static boolean aboveOrEqualLong(long a, long b) { + return UnsignedMath.aboveOrEqual(a, b); + } + + public static boolean belowThanLong(long a, long b) { + return UnsignedMath.belowThan(a, b); + } + + public static boolean belowOrEqualLong(long a, long b) { + return UnsignedMath.belowOrEqual(a, b); + } + + public static long divideLong(long a, long b) { + return UnsignedMath.divide(a, b); + } + + public static long remainderLong(long a, long b) { + return UnsignedMath.remainder(a, b); + } + + private void testInt(int a, int b) { + test("aboveThanInt", a, b); + test("aboveOrEqualInt", a, b); + test("belowThanInt", a, b); + test("belowOrEqualInt", a, b); + test("divideInt", a, b); + test("remainderInt", a, b); + } + + private void testLong(long a, long b) { + test("aboveThanLong", a, b); + test("aboveOrEqualLong", a, b); + test("belowThanLong", a, b); + test("belowOrEqualLong", a, b); + test("divideLong", a, b); + test("remainderLong", a, b); + } + + @Test + public void testInt() { + testInt(5, 7); + testInt(-3, -7); + testInt(-3, 7); + testInt(42, -5); + } + + @Test + public void testLong() { + testLong(5, 7); + testLong(-3, -7); + testLong(-3, 7); + testLong(42, -5); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Fri Feb 28 16:19:10 2014 +0100 @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.util.*; +import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing; +import com.oracle.graal.word.phases.*; + +/** + * A utility for manually creating a graph. This will be expanded as necessary to support all + * subsystems that employ manual graph creation (as opposed to {@linkplain GraphBuilderPhase + * bytecode parsing} based graph creation). + */ +public class GraphKit { + + protected final Providers providers; + protected final StructuredGraph graph; + protected FixedWithNextNode lastFixedNode; + + private final List<Structure> structures; + + abstract static class Structure { + } + + public GraphKit(StructuredGraph graph, Providers providers) { + this.providers = providers; + this.graph = graph; + this.lastFixedNode = graph.start(); + + structures = new ArrayList<>(); + /* Add a dummy element, so that the access of the last element never leads to an exception. */ + structures.add(new Structure() { + }); + } + + public StructuredGraph getGraph() { + return graph; + } + + /** + * Ensures a floating node is added to or already present in the graph via {@link Graph#unique}. + * + * @return a node similar to {@code node} if one exists, otherwise {@code node} + */ + public <T extends FloatingNode> T unique(T node) { + return graph.unique(node); + } + + /** + * Appends a fixed node to the graph. + */ + public <T extends FixedNode> T append(T node) { + T result = graph.add(node); + assert lastFixedNode != null; + assert result.predecessor() == null; + graph.addAfterFixed(lastFixedNode, result); + if (result instanceof FixedWithNextNode) { + lastFixedNode = (FixedWithNextNode) result; + } else { + lastFixedNode = null; + } + return result; + } + + public InvokeNode createInvoke(Class<?> declaringClass, String name, ValueNode... args) { + return createInvoke(declaringClass, name, InvokeKind.Static, null, FrameState.UNKNOWN_BCI, args); + } + + /** + * Creates and appends an {@link InvokeNode} for a call to a given method with a given set of + * arguments. The method is looked up via reflection based on the declaring class and name. + * + * @param declaringClass the class declaring the invoked method + * @param name the name of the invoked method + * @param args the arguments to the invocation + */ + public InvokeNode createInvoke(Class<?> declaringClass, String name, InvokeKind invokeKind, FrameStateBuilder frameStateBuilder, int bci, ValueNode... args) { + boolean isStatic = invokeKind == InvokeKind.Static; + ResolvedJavaMethod method = null; + for (Method m : declaringClass.getDeclaredMethods()) { + if (Modifier.isStatic(m.getModifiers()) == isStatic && m.getName().equals(name)) { + assert method == null : "found more than one method in " + declaringClass + " named " + name; + method = providers.getMetaAccess().lookupJavaMethod(m); + } + } + assert method != null : "did not find method in " + declaringClass + " named " + name; + return createInvoke(method, invokeKind, frameStateBuilder, bci, args); + } + + /** + * Creates and appends an {@link InvokeNode} for a call to a given method with a given set of + * arguments. + */ + public InvokeNode createInvoke(ResolvedJavaMethod method, InvokeKind invokeKind, FrameStateBuilder frameStateBuilder, int bci, ValueNode... args) { + assert Modifier.isStatic(method.getModifiers()) == (invokeKind == InvokeKind.Static); + Signature signature = method.getSignature(); + JavaType returnType = signature.getReturnType(null); + assert checkArgs(method, args); + MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, method, args, returnType, bci)); + InvokeNode invoke = append(new InvokeNode(callTarget, bci)); + + if (frameStateBuilder != null) { + if (invoke.kind() != Kind.Void) { + frameStateBuilder.push(invoke.kind(), invoke); + } + invoke.setStateAfter(frameStateBuilder.create(0)); + if (invoke.kind() != Kind.Void) { + frameStateBuilder.pop(invoke.kind()); + } + } + return invoke; + } + + protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, JavaType returnType, @SuppressWarnings("unused") int bci) { + return new MethodCallTargetNode(invokeKind, targetMethod, args, returnType); + } + + /** + * Determines if a given set of arguments is compatible with the signature of a given method. + * + * @return true if {@code args} are compatible with the signature if {@code method} + * @throws AssertionError if {@code args} are not compatible with the signature if + * {@code method} + */ + public boolean checkArgs(ResolvedJavaMethod method, ValueNode... args) { + Signature signature = method.getSignature(); + boolean isStatic = Modifier.isStatic(method.getModifiers()); + if (signature.getParameterCount(!isStatic) != args.length) { + throw new AssertionError(graph + ": wrong number of arguments to " + method); + } + int paramNum = 0; + for (int i = 0; i != args.length; i++) { + Kind expected; + if (i == 0 && !isStatic) { + expected = Kind.Object; + } else { + expected = signature.getParameterKind(paramNum++).getStackKind(); + } + Kind actual = args[i].stamp().getStackKind(); + if (expected != actual) { + throw new AssertionError(graph + ": wrong kind of value for argument " + i + " of call to " + method + " [" + actual + " != " + expected + "]"); + } + } + return true; + } + + /** + * Rewrite all word types in the graph. + */ + public void rewriteWordTypes() { + new WordTypeRewriterPhase(providers.getMetaAccess(), providers.getCodeCache().getTarget().wordKind).apply(graph); + } + + /** + * {@linkplain #inline(InvokeNode) Inlines} all invocations currently in the graph. + */ + public void inlineInvokes() { + for (InvokeNode invoke : graph.getNodes().filter(InvokeNode.class).snapshot()) { + inline(invoke); + } + + // Clean up all code that is now dead after inlining. + new DeadCodeEliminationPhase().apply(graph); + assert graph.getNodes().filter(InvokeNode.class).isEmpty(); + } + + /** + * Inlines a given invocation to a method. The graph of the inlined method is + * {@linkplain ReplacementsImpl#makeGraph processed} in the same manner as for snippets and + * method substitutions. + */ + public void inline(InvokeNode invoke) { + ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod(); + ReplacementsImpl repl = new ReplacementsImpl(providers, new Assumptions(false), providers.getCodeCache().getTarget()); + StructuredGraph calleeGraph = repl.makeGraph(method, null, method, null, FrameStateProcessing.CollapseFrameForSingleSideEffect); + InliningUtil.inline(invoke, calleeGraph, false); + } + + protected void pushStructure(Structure structure) { + structures.add(structure); + } + + protected <T extends Structure> T getTopStructure(Class<T> expectedClass) { + return expectedClass.cast(structures.get(structures.size() - 1)); + } + + protected void popStructure() { + structures.remove(structures.size() - 1); + } + + protected enum IfState { + CONDITION, THEN_PART, ELSE_PART, FINISHED + } + + static class IfStructure extends Structure { + protected IfState state; + protected FixedNode thenPart; + protected FixedNode elsePart; + } + + /** + * Starts an if-block. This call can be followed by a call to {@link #thenPart} to start + * emitting the code executed when the condition hold; and a call to {@link #elsePart} to start + * emititng the code when the condition does not hold. It must be followed by a call to + * {@link #endIf} to close the if-block. + * + * @param condition The condition for the if-block + * @param trueProbability The estimated probability the the condition is true + */ + public void startIf(LogicNode condition, double trueProbability) { + BeginNode thenSuccessor = graph.add(new BeginNode()); + BeginNode elseSuccessor = graph.add(new BeginNode()); + append(new IfNode(condition, thenSuccessor, elseSuccessor, trueProbability)); + lastFixedNode = null; + + IfStructure s = new IfStructure(); + s.state = IfState.CONDITION; + s.thenPart = thenSuccessor; + s.elsePart = elseSuccessor; + pushStructure(s); + } + + private IfStructure saveLastNode() { + IfStructure s = getTopStructure(IfStructure.class); + switch (s.state) { + case CONDITION: + assert lastFixedNode == null; + break; + case THEN_PART: + s.thenPart = lastFixedNode; + break; + case ELSE_PART: + s.elsePart = lastFixedNode; + break; + case FINISHED: + assert false; + break; + } + lastFixedNode = null; + return s; + } + + public void thenPart() { + IfStructure s = saveLastNode(); + lastFixedNode = (FixedWithNextNode) s.thenPart; + s.state = IfState.THEN_PART; + } + + public void elsePart() { + IfStructure s = saveLastNode(); + lastFixedNode = (FixedWithNextNode) s.elsePart; + s.state = IfState.ELSE_PART; + } + + public void endIf() { + IfStructure s = saveLastNode(); + + FixedWithNextNode thenPart = s.thenPart instanceof FixedWithNextNode ? (FixedWithNextNode) s.thenPart : null; + FixedWithNextNode elsePart = s.elsePart instanceof FixedWithNextNode ? (FixedWithNextNode) s.elsePart : null; + + if (thenPart != null && elsePart != null) { + /* Both parts are alive, we need a real merge. */ + EndNode thenEnd = graph.add(new EndNode()); + graph.addAfterFixed(thenPart, thenEnd); + EndNode elseEnd = graph.add(new EndNode()); + graph.addAfterFixed(elsePart, elseEnd); + + MergeNode merge = graph.add(new MergeNode()); + merge.addForwardEnd(thenEnd); + merge.addForwardEnd(elseEnd); + + lastFixedNode = merge; + + } else if (thenPart != null) { + /* elsePart ended with a control sink, so we can continue with thenPart. */ + lastFixedNode = thenPart; + + } else if (elsePart != null) { + /* thenPart ended with a control sink, so we can continue with elsePart. */ + lastFixedNode = elsePart; + + } else { + /* Both parts ended with a control sink, so no nodes can be added after the if. */ + assert lastFixedNode == null; + } + s.state = IfState.FINISHED; + popStructure(); + } +}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -37,18 +37,18 @@ @Input private ValueNode value; public BitCountNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, value.kind().getBitCount())); + super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits())); this.value = value; } @Override public Node canonical(CanonicalizerTool tool) { if (value.isConstant()) { - long v = value.asConstant().asLong(); - if (value.kind().getStackKind() == Kind.Int) { - return ConstantNode.forInt(Integer.bitCount((int) v), graph()); - } else if (value.kind() == Kind.Long) { - return ConstantNode.forInt(Long.bitCount(v), graph()); + Constant c = value.asConstant(); + if (c.getKind() == Kind.Int) { + return ConstantNode.forInt(Integer.bitCount(c.asInt()), graph()); + } else if (c.getKind() == Kind.Long) { + return ConstantNode.forInt(Long.bitCount(c.asLong()), graph()); } } return this;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,18 +37,18 @@ @Input private ValueNode value; public BitScanForwardNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, value.kind().getBitCount())); + super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits())); this.value = value; } @Override public Node canonical(CanonicalizerTool tool) { if (value.isConstant()) { - long v = value.asConstant().asLong(); - if (value.kind().getStackKind() == Kind.Int) { - return ConstantNode.forInt(Integer.numberOfTrailingZeros((int) v), graph()); - } else if (value.kind() == Kind.Long) { - return ConstantNode.forInt(Long.numberOfTrailingZeros(v), graph()); + Constant c = value.asConstant(); + if (c.getKind() == Kind.Int) { + return ConstantNode.forInt(Integer.numberOfTrailingZeros(c.asInt()), graph()); + } else if (c.getKind() == Kind.Long) { + return ConstantNode.forInt(Long.numberOfTrailingZeros(c.asLong()), graph()); } } return this;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,18 +37,18 @@ @Input private ValueNode value; public BitScanReverseNode(ValueNode value) { - super(StampFactory.forInteger(Kind.Int, 0, value.kind().getBitCount())); + super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits())); this.value = value; } @Override public Node canonical(CanonicalizerTool tool) { if (value.isConstant()) { - long v = value.asConstant().asLong(); - if (value.kind().getStackKind() == Kind.Int) { - return ConstantNode.forInt(31 - Integer.numberOfLeadingZeros((int) v), graph()); - } else if (value.kind() == Kind.Long) { - return ConstantNode.forInt(63 - Long.numberOfLeadingZeros(v), graph()); + Constant c = value.asConstant(); + if (c.getKind() == Kind.Int) { + return ConstantNode.forInt(31 - Integer.numberOfLeadingZeros(c.asInt()), graph()); + } else if (c.getKind() == Kind.Long) { + return ConstantNode.forInt(63 - Long.numberOfLeadingZeros(c.asLong()), graph()); } } return this;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -48,8 +48,8 @@ } public MathIntrinsicNode(ValueNode x, Operation op) { - super(StampFactory.forKind(x.kind())); - assert x.kind() == Kind.Double; + super(StampFactory.forKind(Kind.Double)); + assert x.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(x.stamp()) == 64; this.x = x; this.operation = op; }
--- a/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java Fri Feb 28 16:19:10 2014 +0100 @@ -41,7 +41,7 @@ @ServiceProvider(OptimizedCallTargetInstrumentationFactory.class) public class AMD64OptimizedCallTargetInstrumentationFactory implements OptimizedCallTargetInstrumentationFactory { - public CompilationResultBuilder createBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext, + public CompilationResultBuilder createBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, FrameContext frameContext, CompilationResult compilationResult) { return new OptimizedCallTargetInstrumentation(codeCache, foreignCalls, frameMap, asm, frameContext, compilationResult) { @Override @@ -51,14 +51,14 @@ Register thisRegister = codeCache.getRegisterConfig().getCallingConventionRegisters(Type.JavaCall, Kind.Object)[0]; Register spillRegister = AMD64.r10; // TODO(mg): fix me AMD64Address nMethodAddress = new AMD64Address(thisRegister, getFieldOffset("installedCode", OptimizedCallTarget.class)); - int verifiedEntryPoint = asm.codeBuffer.position(); + int verifiedEntryPoint = asm.position(); if (config.useCompressedOops) { asm.movl(spillRegister, nMethodAddress); - asm.nop(AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE - (asm.codeBuffer.position() - verifiedEntryPoint)); + asm.nop(AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE - (asm.position() - verifiedEntryPoint)); AMD64HotSpotMove.decodePointer(asm, spillRegister, registers.getHeapBaseRegister(), config.getOopEncoding()); } else { asm.movq(spillRegister, nMethodAddress); - asm.nop(AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE - (asm.codeBuffer.position() - verifiedEntryPoint)); + asm.nop(AMD64HotSpotBackend.PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE - (asm.position() - verifiedEntryPoint)); } Label doProlog = new Label();
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java Fri Feb 28 16:19:10 2014 +0100 @@ -43,7 +43,7 @@ */ public abstract class OptimizedCallTargetInstrumentation extends CompilationResultBuilder { - public OptimizedCallTargetInstrumentation(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext, + public OptimizedCallTargetInstrumentation(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, FrameContext frameContext, CompilationResult compilationResult) { super(codeCache, foreignCalls, frameMap, asm, frameContext, compilationResult); }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -38,8 +38,8 @@ public class IntegerAddExactNode extends IntegerAddNode implements Canonicalizable, IntegerExactArithmeticNode { public IntegerAddExactNode(ValueNode x, ValueNode y) { - super(x.kind(), x, y); - assert x.kind() == y.kind() && (x.kind() == Kind.Int || x.kind() == Kind.Long); + super(x.stamp().unrestricted(), x, y); + assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; } @Override @@ -54,12 +54,15 @@ return graph().unique(new IntegerAddExactNode(y(), x())); } if (x().isConstant()) { + Constant xConst = x().asConstant(); + Constant yConst = y().asConstant(); + assert xConst.getKind() == yConst.getKind(); try { - if (kind() == Kind.Int) { - return ConstantNode.forInt(ExactMath.addExact(x().asConstant().asInt(), y().asConstant().asInt()), graph()); + if (xConst.getKind() == Kind.Int) { + return ConstantNode.forInt(ExactMath.addExact(xConst.asInt(), yConst.asInt()), graph()); } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(ExactMath.addExact(x().asConstant().asLong(), y().asConstant().asLong()), graph()); + assert xConst.getKind() == Kind.Long; + return ConstantNode.forLong(ExactMath.addExact(xConst.asLong(), yConst.asLong()), graph()); } } catch (ArithmeticException ex) { // The operation will result in an overflow exception, so do not canonicalize.
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; import com.oracle.truffle.api.*; /** @@ -37,8 +38,8 @@ public class IntegerMulExactNode extends IntegerMulNode implements Canonicalizable, IntegerExactArithmeticNode { public IntegerMulExactNode(ValueNode x, ValueNode y) { - super(x.kind(), x, y); - assert x.kind() == y.kind() && (x.kind() == Kind.Int || x.kind() == Kind.Long); + super(x.stamp().unrestricted(), x, y); + assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; } @Override @@ -47,12 +48,15 @@ return graph().unique(new IntegerMulExactNode(y(), x())); } if (x().isConstant()) { + Constant xConst = x().asConstant(); + Constant yConst = y().asConstant(); + assert xConst.getKind() == yConst.getKind(); try { - if (kind() == Kind.Int) { - return ConstantNode.forInt(ExactMath.multiplyExact(x().asConstant().asInt(), y().asConstant().asInt()), graph()); + if (xConst.getKind() == Kind.Int) { + return ConstantNode.forInt(ExactMath.multiplyExact(xConst.asInt(), yConst.asInt()), graph()); } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(ExactMath.multiplyExact(x().asConstant().asLong(), y().asConstant().asLong()), graph()); + assert xConst.getKind() == Kind.Long; + return ConstantNode.forLong(ExactMath.multiplyExact(xConst.asLong(), yConst.asLong()), graph()); } } catch (ArithmeticException ex) { // The operation will result in an overflow exception, so do not canonicalize. @@ -63,7 +67,7 @@ return x(); } if (c == 0) { - return ConstantNode.defaultForKind(kind(), graph()); + return ConstantNode.forIntegerStamp(stamp(), 0, graph()); } } return this;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Fri Feb 28 16:19:10 2014 +0100 @@ -38,8 +38,8 @@ public class IntegerSubExactNode extends IntegerSubNode implements Canonicalizable, IntegerExactArithmeticNode { public IntegerSubExactNode(ValueNode x, ValueNode y) { - super(x.kind(), x, y); - assert x.kind() == y.kind() && (x.kind() == Kind.Int || x.kind() == Kind.Long); + super(StampTool.sub(x.stamp(), y.stamp()), x, y); + assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp; } @Override @@ -51,15 +51,18 @@ @Override public Node canonical(CanonicalizerTool tool) { if (x() == y()) { - return ConstantNode.forIntegerKind(kind(), 0, graph()); + return ConstantNode.forIntegerStamp(stamp(), 0, graph()); } if (x().isConstant() && y().isConstant()) { + Constant xConst = x().asConstant(); + Constant yConst = y().asConstant(); + assert xConst.getKind() == yConst.getKind(); try { - if (kind() == Kind.Int) { - return ConstantNode.forInt(ExactMath.subtractExact(x().asConstant().asInt(), y().asConstant().asInt()), graph()); + if (xConst.getKind() == Kind.Int) { + return ConstantNode.forInt(ExactMath.subtractExact(xConst.asInt(), yConst.asInt()), graph()); } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(ExactMath.subtractExact(x().asConstant().asLong(), y().asConstant().asLong()), graph()); + assert xConst.getKind() == Kind.Long; + return ConstantNode.forLong(ExactMath.subtractExact(xConst.asLong(), yConst.asLong()), graph()); } } catch (ArithmeticException ex) { // The operation will result in an overflow exception, so do not canonicalize.
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Wed Feb 26 13:09:16 2014 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Fri Feb 28 16:19:10 2014 +0100 @@ -202,7 +202,7 @@ case NOT: assert arguments.size() == 1; - replace(invoke, graph.unique(new XorNode(wordKind, arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph)))); + replace(invoke, graph.unique(new XorNode(StampFactory.forKind(wordKind), arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph)))); break; case READ: { @@ -320,8 +320,8 @@ */ private static ValueNode createBinaryNodeInstance(Class<? extends ValueNode> nodeClass, Kind kind, ValueNode left, ValueNode right) { try { - Constructor<? extends ValueNode> constructor = nodeClass.getConstructor(Kind.class, ValueNode.class, ValueNode.class); - return constructor.newInstance(kind, left, right); + Constructor<? extends ValueNode> constructor = nodeClass.getConstructor(Stamp.class, ValueNode.class, ValueNode.class); + return constructor.newInstance(StampFactory.forKind(kind), left, right); } catch (Throwable ex) { throw new GraalInternalError(ex).addContext(nodeClass.getName()); }
--- a/mx/mx_graal.py Wed Feb 26 13:09:16 2014 +0100 +++ b/mx/mx_graal.py Fri Feb 28 16:19:10 2014 +0100 @@ -1325,6 +1325,7 @@ mx.run_java( ['-jar', os.path.join(absoluteMicro, "target", "microbenchmarks.jar"), "-f", "1", + "-v", "EXTRA" if mx._opts.verbose else "NORMAL", "-i", "10", "-wi", "10", "--jvm", exe, "--jvmArgs", " ".join(["-" + vm] + forkedVmArgs)] + regex,
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Feb 26 13:09:16 2014 +0100 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Fri Feb 28 16:19:10 2014 +0100 @@ -1006,6 +1006,15 @@ __ delayed()->nop(); } +void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm, + int total_args_passed, + int comp_args_on_stack, + const BasicType *sig_bt, + const VMRegPair *regs) { + AdapterGenerator agen(masm); + agen.gen_i2c_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs); +} + // --------------------------------------------------------------- AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm, int total_args_passed, @@ -1016,9 +1025,7 @@ AdapterFingerPrint* fingerprint) { address i2c_entry = __ pc(); - AdapterGenerator agen(masm); - - agen.gen_i2c_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs); + gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs); // ------------------------------------------------------------------------- @@ -1063,7 +1070,7 @@ } address c2i_entry = __ pc(); - + AdapterGenerator agen(masm); agen.gen_c2i_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs, L_skip_fixup); __ flush();
--- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed Feb 26 13:09:16 2014 +0100 +++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Fri Feb 28 16:19:10 2014 +0100 @@ -711,7 +711,7 @@ __ bind(L_fail); } -static void gen_i2c_adapter(MacroAssembler *masm, +void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm, int total_args_passed, int comp_args_on_stack, const BasicType *sig_bt,
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Feb 26 13:09:16 2014 +0100 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Feb 28 16:19:10 2014 +0100 @@ -642,7 +642,7 @@ __ bind(L_fail); } -static void gen_i2c_adapter(MacroAssembler *masm, +void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm, int total_args_passed, int comp_args_on_stack, const BasicType *sig_bt,
--- a/src/share/vm/graal/graalCodeInstaller.cpp Wed Feb 26 13:09:16 2014 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Fri Feb 28 16:19:10 2014 +0100 @@ -808,7 +808,6 @@ void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) { oop id_obj = CompilationResult_Mark::id(site); - arrayOop references = (arrayOop) CompilationResult_Mark::references(site); if (id_obj != NULL) { assert(java_lang_boxing_object::is_instance(id_obj, T_INT), "Integer id expected");
--- a/src/share/vm/graal/graalJavaAccess.hpp Wed Feb 26 13:09:16 2014 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Fri Feb 28 16:19:10 2014 +0100 @@ -169,7 +169,6 @@ end_class \ start_class(CompilationResult_Mark) \ oop_field(CompilationResult_Mark, id, "Ljava/lang/Object;") \ - oop_field(CompilationResult_Mark, references, "[Lcom/oracle/graal/api/code/CompilationResult$Mark;") \ end_class \ start_class(DebugInfo) \ oop_field(DebugInfo, bytecodePosition, "Lcom/oracle/graal/api/code/BytecodePosition;") \
--- a/src/share/vm/runtime/sharedRuntime.hpp Wed Feb 26 13:09:16 2014 +0100 +++ b/src/share/vm/runtime/sharedRuntime.hpp Fri Feb 28 16:19:10 2014 +0100 @@ -402,6 +402,12 @@ const VMRegPair *regs, AdapterFingerPrint* fingerprint); + static void gen_i2c_adapter(MacroAssembler *_masm, + int total_args_passed, + int comp_args_on_stack, + const BasicType *sig_bt, + const VMRegPair *regs); + // OSR support // OSR_migration_begin will extract the jvm state from an interpreter