# HG changeset patch # User Roland Schatz # Date 1438163958 -7200 # Node ID aeb7a47e272d18dca378a3a6c25d37520ed203a4 # Parent 992575891f42d645fe6f2b61e6a8961f9c20cf11# Parent bdfd42480dc9c9e610bd751186cbbe04ac3874ff Merge. diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Wed Jul 29 11:59:18 2015 +0200 @@ -29,6 +29,9 @@ import static com.oracle.graal.asm.sparc.SPARCAssembler.Ops.*; import static java.lang.String.*; import static jdk.internal.jvmci.sparc.SPARC.*; + +import java.util.*; + import jdk.internal.jvmci.code.*; import jdk.internal.jvmci.meta.*; import jdk.internal.jvmci.sparc.*; @@ -78,6 +81,10 @@ private static final Ops[] OPS; private static final Op2s[] OP2S; + private static final Op3s[][] OP3S; + + private ArrayList delaySlotOptimizationPoints = new ArrayList<>(5); + static { Ops[] ops = Ops.values(); OPS = new Ops[ops.length]; @@ -89,6 +96,13 @@ for (Op2s op2 : op2s) { OP2S[op2.value] = op2; } + OP3S = new Op3s[2][64]; + for (Op3s op3 : Op3s.values()) { + if (op3.value >= 1 << 6) { + throw new RuntimeException("Error " + op3 + " " + op3.value); + } + OP3S[op3.op.value & 1][op3.value] = op3; + } } public enum Ops { @@ -238,7 +252,7 @@ Lddf (0b10_0011, "lddf", LdstOp), Stf (0b10_0100, "stf", LdstOp), Stfsr (0b10_0101, "stfsr", LdstOp), - Staf (0x10_0110, "staf", LdstOp), + Staf (0b10_0110, "staf", LdstOp), Stdf (0b10_0111, "stdf", LdstOp), Rd (0b10_1000, "rd", ArithOp), @@ -257,6 +271,7 @@ private final Ops op; private Op3s(int value, String name, Ops op) { + assert isImm(value, 6); this.value = value; this.operator = name; this.op = op; @@ -270,8 +285,21 @@ return operator; } - public boolean appliesTo(int instructionWord) { - return ((instructionWord >>> 19) & 0b1_1111) == value; + public boolean throwsException() { + if (op == LdstOp) { + return true; + } + switch (this) { + case Udiv: + case Udivx: + case Sdiv: + case Sdivx: + case Udivcc: + case Sdivcc: + return true; + default: + return false; + } } } @@ -796,6 +824,574 @@ } } + /** + * Specifies various bit fields used in SPARC instructions. + */ + @SuppressWarnings("unused") + public abstract static class BitSpec { + private static final BitSpec op = new ContinousBitSpec(31, 30, "op"); + private static final BitSpec op2 = new ContinousBitSpec(24, 22, "op2"); + private static final BitSpec op3 = new ContinousBitSpec(24, 19, "op3"); + private static final BitSpec rd = new ContinousBitSpec(29, 25, "rd"); + private static final BitSpec rs1 = new ContinousBitSpec(18, 14, "rs1"); + private static final BitSpec rs2 = new ContinousBitSpec(4, 0, "rs2"); + private static final BitSpec simm13 = new ContinousBitSpec(12, 0, "simm13"); + private static final BitSpec imm22 = new ContinousBitSpec(21, 0, "imm22"); + private static final BitSpec immAsi = new ContinousBitSpec(12, 5, "immASI"); + private static final BitSpec i = new ContinousBitSpec(13, 13, "i"); + private static final BitSpec disp19 = new ContinousBitSpec(18, 0, true, "disp19"); + private static final BitSpec disp22 = new ContinousBitSpec(21, 0, true, "disp22"); + private static final BitSpec disp30 = new ContinousBitSpec(29, 0, true, "disp30"); + private static final BitSpec a = new ContinousBitSpec(29, 29, "a"); + private static final BitSpec p = new ContinousBitSpec(19, 19, "p"); + private static final BitSpec cond = new ContinousBitSpec(28, 25, "cond"); + private static final BitSpec rcond = new ContinousBitSpec(27, 25, "rcond"); + private static final BitSpec cc = new ContinousBitSpec(21, 20, "cc"); + private static final BitSpec d16hi = new ContinousBitSpec(21, 20, "d16hi"); + private static final BitSpec d16lo = new ContinousBitSpec(13, 0, "d16lo"); + private static final BitSpec d16 = new CompositeBitSpec(d16hi, d16lo); + // CBCond + private static final BitSpec cLo = new ContinousBitSpec(27, 25, "cLo"); + private static final BitSpec cHi = new ContinousBitSpec(29, 29, "cHi"); + private static final BitSpec c = new CompositeBitSpec(cHi, cLo); + private static final BitSpec cbcond = new ContinousBitSpec(28, 28, "cbcond"); + private static final BitSpec cc2 = new ContinousBitSpec(21, 21, "cc2"); + private static final BitSpec d10Lo = new ContinousBitSpec(12, 5, "d10Lo"); + private static final BitSpec d10Hi = new ContinousBitSpec(20, 19, "d10Hi"); + private static final BitSpec d10 = new CompositeBitSpec(d10Hi, d10Lo); + private static final BitSpec simm5 = new ContinousBitSpec(4, 0, true, "simm5"); + + public abstract int setBits(int word, int value); + + public abstract int getBits(int word); + + public abstract int getWidth(); + + public abstract boolean valueFits(int value); + } + + public static class ContinousBitSpec extends BitSpec { + private final int hiBit; + private final int lowBit; + private final int width; + private final boolean signExt; + private final int mask; + private final String name; + + public ContinousBitSpec(int hiBit, int lowBit, String name) { + this(hiBit, lowBit, false, name); + } + + public ContinousBitSpec(int hiBit, int lowBit, boolean signExt, String name) { + super(); + this.hiBit = hiBit; + this.lowBit = lowBit; + this.signExt = signExt; + this.width = hiBit - lowBit + 1; + mask = ((1 << width) - 1) << lowBit; + this.name = name; + } + + @Override + public int setBits(int word, int value) { + assert valueFits(value) : "Value: " + value + " does not fit in " + this; + return (word & ~mask) | ((value << lowBit) & mask); + } + + @Override + public int getBits(int word) { + if (signExt) { + return ((word & mask) << (31 - hiBit)) >> (32 - width); + } else { + return (word & mask) >>> lowBit; + } + } + + @Override + public int getWidth() { + return width; + } + + @Override + public String toString() { + return String.format("%s [%d:%d]", name, hiBit, lowBit); + } + + @Override + public boolean valueFits(int value) { + if (signExt) { + return isSimm(value, getWidth()); + } else { + return isImm(value, getWidth()); + } + } + } + + public static class CompositeBitSpec extends BitSpec { + private final BitSpec left; + private final int leftWidth; + private final BitSpec right; + private final int rightWidth; + + public CompositeBitSpec(BitSpec left, BitSpec right) { + super(); + this.left = left; + this.leftWidth = left.getWidth(); + this.right = right; + this.rightWidth = right.getWidth(); + } + + @Override + public int getBits(int word) { + int l = left.getBits(word); + int r = right.getBits(word); + return l << rightWidth | r; + } + + @Override + public int setBits(int word, int value) { + int l = leftBits(value); + int r = rightBits(value); + return left.setBits(right.setBits(word, r), l); + } + + private int leftBits(int value) { + return SPARCAssembler.getBits(value, rightWidth + leftWidth, rightWidth); + } + + private int rightBits(int value) { + return SPARCAssembler.getBits(value, rightWidth - 1, 0); + } + + @Override + public int getWidth() { + return left.getWidth() + right.getWidth(); + } + + @Override + public String toString() { + return String.format("CompositeBitSpec[%s, %s]", left, right); + } + + @Override + public boolean valueFits(int value) { + return left.valueFits(leftBits(value)) && right.valueFits(rightBits(value)); + } + } + + public static class BitKey { + private final BitSpec spec; + private final int value; + + public BitKey(BitSpec spec, int value) { + super(); + this.spec = spec; + this.value = value; + } + + @Override + public String toString() { + return String.format("BitKey %s=%s", spec, value); + } + } + + /** + * Represents a prefix tree of {@link BitSpec} objects to find the most accurate SPARCOp. + */ + public static class BitKeyIndex { + private final BitSpec spec; + private final Map nodes; + private SPARCOp op; + + public BitKeyIndex(SPARCOp op) { + assert op != null; + this.op = op; + this.nodes = null; + this.spec = null; + } + + public BitKeyIndex(BitSpec spec) { + assert spec != null; + this.op = null; + this.nodes = new HashMap<>(4); + this.spec = spec; + } + + /** + * Adds operation to the index. + * + * @param keys Ordered by the importance + * @param operation Operation represented by this list of keys + */ + private void addOp(List keys, SPARCOp operation) { + assert keys.size() > 0; + BitKey first = keys.get(0); + assert first.spec.equals(spec) : first.spec + " " + spec; + BitKeyIndex node; + if (keys.size() == 1) { + if (nodes.containsKey(first.value)) { + node = nodes.get(first.value); + assert node.op == null : node + " " + keys; + node.op = operation; + } else { + assert !nodes.containsKey(first.value) : "Index must be unique. Existing key: " + nodes.get(first.value); + node = new BitKeyIndex(operation); + } + } else { + node = nodes.get(first.value); + if (node == null) { + node = new BitKeyIndex(keys.get(1).spec); + } + node.addOp(keys.subList(1, keys.size()), operation); + } + nodes.put(first.value, node); + } + + /** + * Finds the best matching {@link SPARCOp} for this instruction. + */ + public SPARCOp find(int inst) { + if (nodes != null) { + int key = spec.getBits(inst); + BitKeyIndex sub = nodes.get(key); + if (sub == null) { + if (op != null) { + return op; + } else { + throw new RuntimeException(String.format("%s 0x%x, 0x%x %s", spec, inst, key, nodes)); + } + } + return sub.find(inst); + } else { + return this.op; + } + } + + @Override + public String toString() { + return this.op == null ? this.spec + ": " + this.nodes : this.op.toString(); + } + } + + public static final Bpcc BPCC = new Bpcc(Op2s.Bp); + public static final Bpcc FBPCC = new Bpcc(Op2s.Fbp); + public static final CBCond CBCOND = new CBCond(); + public static final Bpr BPR = new Bpr(); + public static final Br BR = new Br(); + public static final Sethi SETHI = new Sethi(); + public static final Op3Op OP3 = new Op3Op(); + public static final SPARCOp LDST = new SPARCOp(Ops.LdstOp); + public static final SPARCOp BRANCH = new SPARCOp(Ops.BranchOp); + public static final SPARCOp CALL = new SPARCOp(Ops.CallOp); + private static final BitKeyIndex INDEX = new BitKeyIndex(BitSpec.op); + + static { + for (SPARCOp op : SPARCOp.OPS) { + INDEX.addOp(op.getKeys(), op); + } + } + + public static SPARCOp getSPARCOp(int inst) { + return INDEX.find(inst); + } + + /** + * Represents a class of SPARC instruction and gives methods to modify its fields. + */ + public static class SPARCOp { + private final Ops op; + private final BitKey opKey; + private List keyFields; + private static final List OPS = new ArrayList<>(); + + public SPARCOp(Ops op) { + super(); + this.op = op; + this.opKey = new BitKey(BitSpec.op, op.value); + OPS.add(this); + } + + protected int setBits(int word) { + return BitSpec.op.setBits(word, op.value); + } + + public boolean match(int inst) { + for (BitKey k : keyFields) { + if (k.spec.getBits(inst) != k.value) { + return false; + } + } + return true; + } + + protected List getKeys() { + if (keyFields == null) { + keyFields = new ArrayList<>(4); + keyFields.add(opKey); + } + return keyFields; + } + + public Ops getOp(int inst) { + return SPARCAssembler.OPS[BitSpec.op.getBits(inst)]; + } + + @Override + public String toString() { + String name = getClass().getName(); + name = name.substring(name.lastIndexOf(".") + 1); + return name + "[op: " + op + "]"; + } + } + + /** + * Base class for control transfer operations; provides access to the disp field. + */ + public abstract static class ControlTransferOp extends SPARCOp { + private final Op2s op2; + private final boolean delaySlot; + private final BitSpec disp; + private final BitKey op2Key; + + private ControlTransferOp(Ops op, Op2s op2, boolean delaySlot, BitSpec disp) { + super(op); + this.op2 = op2; + this.delaySlot = delaySlot; + this.disp = disp; + this.op2Key = new BitKey(BitSpec.op2, op2.value); + } + + public boolean hasDelaySlot() { + return delaySlot; + } + + @Override + protected int setBits(int word) { + return BitSpec.op2.setBits(super.setBits(word), op2.value); + } + + protected int setDisp(int inst, SPARCMacroAssembler masm, Label lab) { + if (lab.isBound()) { + int d = (lab.position() - masm.position()) / 4; + return setDisp(inst, d); + } else { + masm.patchUnbound(lab); + return inst; + } + } + + public int setDisp(int inst, int d) { + assert this.match(inst); + return this.disp.setBits(inst, d); + } + + public boolean isValidDisp(int d) { + return this.disp.valueFits(d); + } + + public int setAnnul(int inst, boolean a) { + return BitSpec.a.setBits(inst, a ? 1 : 0); + } + + @Override + protected List getKeys() { + List keys = super.getKeys(); + keys.add(op2Key); + return keys; + } + + public int getDisp(int inst) { + return this.disp.getBits(inst); + } + + public abstract boolean isAnnulable(int inst); + + public abstract boolean isConditional(int inst); + } + + public static class Bpcc extends ControlTransferOp { + public Bpcc(Op2s op2) { + super(Ops.BranchOp, op2, true, BitSpec.disp19); + } + + public void emit(SPARCMacroAssembler masm, CC cc, ConditionFlag cf, Annul annul, BranchPredict p, Label lab) { + int inst = setBits(0); + inst = BitSpec.a.setBits(inst, annul.flag); + inst = BitSpec.cond.setBits(inst, cf.value); + inst = BitSpec.cc.setBits(inst, cc.value); + inst = BitSpec.p.setBits(inst, p.flag); + masm.emitInt(setDisp(inst, masm, lab)); + } + + @Override + public boolean isAnnulable(int inst) { + return isConditional(inst); + } + + @Override + public boolean isConditional(int inst) { + int cond = BitSpec.cond.getBits(inst); + return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value; + } + } + + public static class Br extends ControlTransferOp { + public Br() { + super(Ops.BranchOp, Op2s.Br, true, BitSpec.disp22); + } + + @Override + public boolean isAnnulable(int inst) { + return isConditional(inst); + } + + @Override + public boolean isConditional(int inst) { + int cond = BitSpec.cond.getBits(inst); + return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value; + } + } + + public static class Bpr extends ControlTransferOp { + private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 0); + + public Bpr() { + super(Ops.BranchOp, Op2s.Bpr, true, BitSpec.d16); + } + + public void emit(SPARCMacroAssembler masm, RCondition rcond, Annul a, BranchPredict p, Register rs1, Label lab) { + int inst = setBits(0); + inst = BitSpec.rcond.setBits(inst, rcond.value); + inst = BitSpec.a.setBits(inst, a.flag); + inst = BitSpec.p.setBits(inst, p.flag); + inst = BitSpec.rs1.setBits(inst, rs1.encoding); + masm.emitInt(setDisp(inst, masm, lab)); + } + + @Override + protected List getKeys() { + List keys = super.getKeys(); + keys.add(CBCOND_KEY); + return keys; + } + + @Override + public boolean isAnnulable(int inst) { + return isConditional(inst); + } + + @Override + public boolean isConditional(int inst) { + int cond = BitSpec.cond.getBits(inst); + return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value; + } + } + + public static final class CBCond extends ControlTransferOp { + private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 1); + + private CBCond() { + super(Ops.BranchOp, Op2s.Bpr, false, BitSpec.d10); + } + + @Override + protected List getKeys() { + List keys = super.getKeys(); + keys.add(CBCOND_KEY); + return keys; + } + + public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, Register rs2, Label lab) { + int inst = setBits(0, cf, cc2, rs1); + inst = BitSpec.rs2.setBits(inst, rs2.encoding); + emit(masm, lab, inst); + } + + public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, int simm5, Label lab) { + int inst = setBits(0, cf, cc2, rs1); + inst = BitSpec.simm5.setBits(inst, simm5); + emit(masm, lab, inst); + } + + private void emit(SPARCMacroAssembler masm, Label lab, int baseInst) { + int inst = baseInst; + masm.insertNopAfterCBCond(); + masm.emitInt(setDisp(inst, masm, lab)); + } + + private int setBits(int base, ConditionFlag cf, boolean cc2, Register rs1) { + int inst = super.setBits(base); + inst = BitSpec.rs1.setBits(inst, rs1.encoding); + inst = BitSpec.cc2.setBits(inst, cc2 ? 1 : 0); + inst = BitSpec.c.setBits(inst, cf.value); + return BitSpec.cbcond.setBits(inst, 1); + } + + @Override + public boolean isAnnulable(int inst) { + return false; + } + + @Override + public boolean isConditional(int inst) { + return true; + } + } + + public static class Op2Op extends SPARCOp { + private final Op2s op2; + private final BitKey op2Key; + + public Op2Op(Ops op, Op2s op2) { + super(op); + this.op2 = op2; + op2Key = new BitKey(BitSpec.op2, op2.value); + } + + @Override + protected int setBits(int word) { + int result = super.setBits(word); + return BitSpec.op2.setBits(result, op2.value); + } + + @Override + protected List getKeys() { + List keys = super.getKeys(); + keys.add(op2Key); + return keys; + } + } + + public static class Sethi extends Op2Op { + public Sethi() { + super(Ops.BranchOp, Op2s.Sethi); + } + + public Register getRS1(int word) { + int regNum = BitSpec.rs1.getBits(word); + return SPARC.cpuRegisters[regNum]; + } + + public int getImm22(int word) { + return BitSpec.imm22.getBits(word); + } + + public boolean isNop(int inst) { + return getRS1(inst).equals(g0) && getImm22(inst) == 0; + } + } + + public static class Op3Op extends SPARCOp { + public Op3Op() { + super(ArithOp); + } + + public Op3s getOp3(int inst) { + assert match(inst); + return OP3S[ArithOp.value & 1][BitSpec.op3.getBits(inst)]; + } + } + public boolean hasFeature(CPUFeature feature) { return ((SPARC) this.target.arch).features.contains(feature); } @@ -897,7 +1493,12 @@ // @formatter:on protected void fmt00(int a, int op2, int b) { assert isImm(a, 5) && isImm(op2, 3) && isImm(b, 22) : String.format("a: 0x%x op2: 0x%x b: 0x%x", a, op2, b); - this.emitInt(a << 25 | op2 << 22 | b); + int word = 0; + BitSpec.op.setBits(word, 0); + BitSpec.rd.setBits(word, a); + BitSpec.op2.setBits(word, op2); + BitSpec.imm22.setBits(word, b); + emitInt(a << 25 | op2 << 22 | b); } private void op3(Op3s op3, Opfs opf, Register rs1, Register rs2, Register rd) { @@ -975,7 +1576,11 @@ } protected static boolean isCBCond(int inst) { - return getOp(inst).equals(Ops.BranchOp) && getOp2(inst).equals(Op2s.Bpr) && getBits(inst, 28, 28) == 1; + return isOp2(Ops.BranchOp, Op2s.Bpr, inst) && getBits(inst, 28, 28) == 1; + } + + private static boolean isOp2(Ops ops, Op2s op2s, int inst) { + return getOp(inst).equals(ops) && getOp2(inst).equals(op2s); } private static Ops getOp(int inst) { @@ -986,7 +1591,7 @@ return OP2S[getBits(inst, 24, 22)]; } - private static int getBits(int inst, int hiBit, int lowBit) { + public static int getBits(int inst, int hiBit, int lowBit) { return (inst >> lowBit) & ((1 << (hiBit - lowBit + 1)) - 1); } @@ -1033,6 +1638,7 @@ pos &= (1 << disp) - 1; int a = (annul.flag << 4) | cond.getValue(); int b = (cc.getValue() << 20) | ((predictTaken.flag) << 19) | pos; + delaySlotOptimizationPoints.add(position()); fmt00(a, op2.getValue(), b); } @@ -1055,10 +1661,11 @@ int d16hi = (pos >> 13) << 13; int d16lo = d16hi ^ pos; int b = (d16hi << 20) | (predictTaken.flag << 19) | (rs1.encoding() << 14) | d16lo; + delaySlotOptimizationPoints.add(position()); fmt00(a, Op2s.Bpr.getValue(), b); } - private int patchUnbound(Label label) { + protected int patchUnbound(Label label) { label.addPatchAt(position()); return 0; } @@ -1377,6 +1984,7 @@ public void fcmp(CC cc, Opfs opf, Register rs1, Register rs2) { int a = cc.value; int b = opf.value << 5 | rs2.encoding; + delaySlotOptimizationPoints.add(position()); fmt10(a, Fcmp.value, rs1.encoding, b); } @@ -1830,4 +2438,69 @@ public void fpadd32(Register rs1, Register rs2, Register rd) { op3(Impdep1, Fpadd32, rs1, rs2, rd); } + + /** + * Does peephole optimization on code generated by this assembler. This method should be called + * at the end of code generation. + *

+ * It searches for conditional branch instructions which has nop in the delay slot then looks at + * the instruction at branch target; if it is an arithmetic instruction, which does not throw an + * exception (e.g. division), it pulls this instruction into the delay slot and increments the + * displacement by 1. + */ + public void peephole() { + for (int i : delaySlotOptimizationPoints) { + optimizeDelaySlot(i); + } + } + + /** + * Optimizes branch instruction b which has a nop in the delay slot. It tries to stuff + * the instruction at bs branch target into the delay slot of b, set the annul + * flag and increments bs disp field by 1; + *

+ * If bs branch target instruction is an unconditional branch t, then it tries to + * put ts delayed instruction into the delay slot of b and add the ts disp + * field to bs disp field. + */ + private void optimizeDelaySlot(int i) { + int delaySlotAbsolute = i + INSTRUCTION_SIZE; + int nextInst = getInt(delaySlotAbsolute); + SPARCOp nextOp = getSPARCOp(nextInst); + if (nextOp instanceof Sethi && ((Sethi) nextOp).isNop(nextInst)) { + int inst = getInt(i); + SPARCOp op = getSPARCOp(inst); + if (op instanceof ControlTransferOp && ((ControlTransferOp) op).hasDelaySlot() && ((ControlTransferOp) op).isAnnulable(inst)) { + ControlTransferOp ctOp = (ControlTransferOp) op; + int disp = ctOp.getDisp(inst); + int branchTargetAbsolute = i + disp * INSTRUCTION_SIZE; + int branchTargetInst = getInt(branchTargetAbsolute); + SPARCOp branchTargetOp = getSPARCOp(branchTargetInst); + if (branchTargetOp instanceof Op3Op) { + Op3s op3 = ((Op3Op) branchTargetOp).getOp3(branchTargetInst); + if (!op3.throwsException()) { + inst = ctOp.setDisp(inst, disp + 1); // Increment the offset + inst = ctOp.setAnnul(inst, true); + emitInt(inst, i); + emitInt(branchTargetInst, delaySlotAbsolute); + } + } else if (branchTargetOp instanceof ControlTransferOp && !((ControlTransferOp) branchTargetOp).isConditional(branchTargetInst)) { + // If branchtarget is a unconditional branch + ControlTransferOp branchTargetOpBranch = (ControlTransferOp) branchTargetOp; + int btDisp = branchTargetOpBranch.getDisp(branchTargetInst); + int newDisp = disp + btDisp; + if (ctOp.isValidDisp(newDisp)) { // Test if we don't exceed field size + int instAfter = ctOp.setDisp(inst, newDisp); + instAfter = ctOp.setAnnul(instAfter, true); + branchTargetInst = getInt(branchTargetAbsolute + INSTRUCTION_SIZE); + branchTargetOp = getSPARCOp(branchTargetInst); + if (branchTargetOp instanceof Op3Op && !((Op3Op) branchTargetOp).getOp3(branchTargetInst).throwsException()) { + emitInt(instAfter, i); + emitInt(branchTargetInst, delaySlotAbsolute); + } + } + } + } + } + } } diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java Wed Jul 29 11:59:18 2015 +0200 @@ -76,48 +76,8 @@ protected final void patchJumpTarget(int branch, int branchTarget) { final int disp = (branchTarget - branch) / 4; final int inst = getInt(branch); - Op2s op2 = Op2s.byValue((inst & OP2_MASK) >> OP2_SHIFT); - int maskBits; - int setBits; - switch (op2) { - case Br: - case Fb: - case Sethi: - case Illtrap: - // Disp 22 in the lower 22 bits - assert isSimm(disp, 22); - setBits = disp << DISP22_SHIFT; - maskBits = DISP22_MASK; - break; - case Fbp: - case Bp: - // Disp 19 in the lower 19 bits - assert isSimm(disp, 19); - setBits = disp << DISP19_SHIFT; - maskBits = DISP19_MASK; - break; - case Bpr: - if (isCBCond(inst)) { - assert isSimm10(disp) : String.format("%d: instruction: 0x%x", disp, inst); - int d10Split = 0; - d10Split |= (disp & 0b11_0000_0000) << D10HI_SHIFT - 8; - d10Split |= (disp & 0b00_1111_1111) << D10LO_SHIFT; - setBits = d10Split; - maskBits = D10LO_MASK | D10HI_MASK; - } else { - assert isSimm(disp, 16); - int d16Split = 0; - d16Split |= (disp & 0b1100_0000_0000_0000) << D16HI_SHIFT - 14; - d16Split |= (disp & 0b0011_1111_1111_1111) << D16LO_SHIFT; - setBits = d16Split; - maskBits = D16HI_MASK | D16LO_MASK; - } - break; - default: - throw new InternalError("Unknown op2 " + op2); - } - int newInst = ~maskBits & inst; - newInst |= setBits; + ControlTransferOp op = (ControlTransferOp) getSPARCOp(inst); + int newInst = op.setDisp(inst, disp); emitInt(newInst, branch); } diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/BackendOptions.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/BackendOptions.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/BackendOptions.java Wed Jul 29 11:59:18 2015 +0200 @@ -25,7 +25,7 @@ import static com.oracle.graal.compiler.common.BackendOptions.UserOptions.*; import static com.oracle.graal.compiler.common.GraalOptions.*; import jdk.internal.jvmci.options.*; -import jdk.internal.jvmci.options.DerivedOptionValue.*; +import jdk.internal.jvmci.options.DerivedOptionValue.OptionSupplier; /** * Options to control the backend configuration. @@ -36,27 +36,44 @@ // @formatter:off @Option(help = "Destruct SSA LIR eagerly (before other LIR phases).", type = OptionType.Debug) public static final OptionValue LIREagerSSADestruction = new OptionValue<>(false); + @Option(help = "Enable Linear Scan on SSI form.", type = OptionType.Debug) + public static final OptionValue LIROptSSILinearScan = new OptionValue<>(false); + @Option(help = "Enable experimental Trace Register Allocation.", type = OptionType.Debug) + public static final OptionValue TraceRA = new OptionValue<>(false); // @formatter:on } + /* Enable SSI Construction. */ + public static final DerivedOptionValue EnableSSIConstruction = new DerivedOptionValue<>(new OptionSupplier() { + private static final long serialVersionUID = -7375589337502162545L; + + public Boolean get() { + return LIROptSSILinearScan.getValue() || TraceRA.getValue(); + } + }); + /* Create SSA LIR during LIR generation. */ public static final DerivedOptionValue ConstructionSSAlirDuringLirBuilding = new DerivedOptionValue<>(new OptionSupplier() { private static final long serialVersionUID = 7657622005438210681L; public Boolean get() { - return SSA_LIR.getValue(); + return SSA_LIR.getValue() || EnableSSIConstruction.getValue(); } }); public enum LSRAVariant { NONSSA_LSAR, - SSA_LSRA + SSA_LSRA, + SSI_LSRA } public static final DerivedOptionValue LinearScanVariant = new DerivedOptionValue<>(new OptionSupplier() { private static final long serialVersionUID = 364925071685235153L; public LSRAVariant get() { + if (LIROptSSILinearScan.getValue()) { + return LSRAVariant.SSI_LSRA; + } if (SSA_LIR.getValue() && !LIREagerSSADestruction.getValue()) { return LSRAVariant.SSA_LSRA; } @@ -71,9 +88,14 @@ public Boolean get() { switch (LinearScanVariant.getValue()) { case SSA_LSRA: + case SSI_LSRA: return true; } + if (TraceRA.getValue()) { + return true; + } return false; } }); + } diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/alloc/TraceBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/alloc/TraceBuilder.java Wed Jul 29 11:59:18 2015 +0200 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.alloc; + +import java.util.*; + +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; + +public final class TraceBuilder> { + + public static final class TraceBuilderResult> { + private final List> traces; + private final int[] blockToTrace; + + private TraceBuilderResult(List> traces, int[] blockToTrace) { + this.traces = traces; + this.blockToTrace = blockToTrace; + } + + public int getTraceForBlock(AbstractBlockBase block) { + return blockToTrace[block.getId()]; + } + + public List> getTraces() { + return traces; + } + } + + /** + * Build traces of sequentially executed blocks. + */ + public static > TraceBuilderResult computeTraces(T startBlock, List blocks) { + return new TraceBuilder<>(blocks).build(startBlock); + } + + private final PriorityQueue worklist; + private final BitSet processed; + /** + * Contains the number of unprocessed predecessors for every {@link AbstractBlockBase#getId() + * block}. + */ + private final int[] blocked; + private final int[] blockToTrace; + + private TraceBuilder(List blocks) { + processed = new BitSet(blocks.size()); + worklist = new PriorityQueue(TraceBuilder::compare); + blocked = new int[blocks.size()]; + blockToTrace = new int[blocks.size()]; + for (T block : blocks) { + blocked[block.getId()] = block.getPredecessorCount(); + } + } + + private static > int compare(T a, T b) { + return Double.compare(b.probability(), a.probability()); + } + + private boolean processed(T b) { + return processed.get(b.getId()); + } + + private TraceBuilderResult build(T startBlock) { + try (Scope s = Debug.scope("TraceBuilder"); Indent i = Debug.logAndIndent("start trace building: " + startBlock)) { + ArrayList> traces = buildTraces(startBlock); + + assert verify(traces); + return new TraceBuilderResult<>(traces, blockToTrace); + } + } + + private boolean verify(ArrayList> traces) { + assert traces.stream().flatMap(l -> l.stream()).distinct().count() == blocked.length : "Not all blocks assigned to traces!"; + for (List trace : traces) { + T last = null; + for (T current : trace) { + assert last == null || current.getPredecessors().contains(last); + last = current; + } + } + return true; + } + + protected ArrayList> buildTraces(T startBlock) { + ArrayList> traces = new ArrayList<>(); + // add start block + worklist.add(startBlock); + // process worklist + while (!worklist.isEmpty()) { + T block = worklist.poll(); + assert block != null; + traces.add(startTrace(block, traces.size())); + } + return traces; + } + + /** + * Build a new trace starting at {@code block}. + */ + private List startTrace(T block, int traceNumber) { + assert block.getPredecessors().stream().allMatch(this::processed) : "Predecessor unscheduled: " + block.getPredecessors().stream().filter(this::processed).findFirst().get(); + ArrayList trace = new ArrayList<>(); + int blockNumber = 0; + try (Indent i = Debug.logAndIndent("StartTrace: " + block)) { + for (T currentBlock = block; currentBlock != null; currentBlock = selectNext(currentBlock)) { + Debug.log("add %s (prob: %f)", currentBlock, currentBlock.probability()); + processed.set(currentBlock.getId()); + worklist.remove(currentBlock); + trace.add(currentBlock); + unblock(currentBlock); + currentBlock.setLinearScanNumber(blockNumber++); + blockToTrace[currentBlock.getId()] = traceNumber; + } + } + return trace; + } + + /** + * Decrease the {@link #blocked} count for all predecessors and add them to the worklist once + * the count reaches 0. + */ + private void unblock(T currentBlock) { + for (T successor : currentBlock.getSuccessors()) { + if (!processed(successor)) { + int blockCount = --blocked[successor.getId()]; + assert blockCount >= 0; + if (blockCount == 0) { + worklist.add(successor); + } + } + } + } + + /** + * @return The unprocessed predecessor with the highest probability, or {@code null}. + */ + private T selectNext(T currentBlock) { + T next = null; + for (T succ : currentBlock.getSuccessors()) { + if (!processed(succ) && (next == null || succ.probability() > next.probability())) { + next = succ; + } + } + return next; + } +} diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/Util.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/Util.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/Util.java Wed Jul 29 11:59:18 2015 +0200 @@ -24,8 +24,9 @@ import java.util.*; +import com.oracle.graal.debug.*; + import jdk.internal.jvmci.code.*; -import jdk.internal.jvmci.debug.*; /** * The {@code Util} class contains a motley collection of utility methods used throughout the diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Jul 29 11:59:18 2015 +0200 @@ -64,8 +64,6 @@ import jdk.internal.jvmci.code.*; import jdk.internal.jvmci.code.CallingConvention.Type; import jdk.internal.jvmci.common.*; -import jdk.internal.jvmci.debug.*; - import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.*; diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Wed Jul 29 11:59:18 2015 +0200 @@ -24,8 +24,6 @@ import java.io.*; -import jdk.internal.jvmci.debug.*; - import com.oracle.graal.debug.*; import org.junit.*; diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/LIRGenerationPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/LIRGenerationPhase.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/LIRGenerationPhase.java Wed Jul 29 11:59:18 2015 +0200 @@ -64,7 +64,7 @@ emitBlock(nodeLirBuilder, lirGenRes, (Block) b, graph, schedule.getBlockToNodesMap()); } context.lirGen.beforeRegisterAllocation(); - assert !ConstructionSSAlirDuringLirBuilding.getValue() || SSAUtils.verifySSAForm(lirGenRes.getLIR()); + assert !ConstructionSSAlirDuringLirBuilding.getValue() || SSAUtil.verifySSAForm(lirGenRes.getLIR()); } private static void emitBlock(NodeLIRBuilderTool nodeLirGen, LIRGenerationResult lirGenRes, Block b, StructuredGraph graph, BlockMap> blockMap) { diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/InstructionPrinter.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/InstructionPrinter.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/InstructionPrinter.java Wed Jul 29 11:59:18 2015 +0200 @@ -23,8 +23,8 @@ package com.oracle.graal.compiler.gen; import static com.oracle.graal.compiler.gen.InstructionPrinter.InstructionLineColumn.*; -import jdk.internal.jvmci.debug.*; +import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; /** diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Wed Jul 29 11:59:18 2015 +0200 @@ -33,8 +33,6 @@ import jdk.internal.jvmci.code.*; import jdk.internal.jvmci.common.*; -import jdk.internal.jvmci.debug.*; - import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.*; diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugTimerTest.java --- a/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugTimerTest.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugTimerTest.java Wed Jul 29 11:59:18 2015 +0200 @@ -26,8 +26,6 @@ import java.lang.management.*; -import jdk.internal.jvmci.debug.*; - import com.oracle.graal.debug.*; import org.junit.*; diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.debug/src/com/oracle/graal/debug/GraalDebugConfig.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/GraalDebugConfig.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/GraalDebugConfig.java Wed Jul 29 11:59:18 2015 +0200 @@ -199,8 +199,8 @@ * @return the {@link JavaMethod} represented by {@code context} or null */ public static JavaMethod asJavaMethod(Object context) { - if (context instanceof JavaMethodContex) { - return ((JavaMethodContex) context).asJavaMethod(); + if (context instanceof JavaMethodContext) { + return ((JavaMethodContext) context).asJavaMethod(); } return null; } diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.debug/src/com/oracle/graal/debug/JavaMethodContex.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/JavaMethodContex.java Tue Jul 28 17:35:49 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.debug; - -import jdk.internal.jvmci.meta.*; - -/** - * Interface for objects used in Debug {@linkplain Debug#context() context} that can provide a - * {@link JavaMethod}. - */ -public interface JavaMethodContex { - JavaMethod asJavaMethod(); -} diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.debug/src/com/oracle/graal/debug/JavaMethodContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/JavaMethodContext.java Wed Jul 29 11:59:18 2015 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.debug; + +import jdk.internal.jvmci.meta.*; + +/** + * Interface for objects used in Debug {@linkplain Debug#context() context} that can provide a + * {@link JavaMethod}. + */ +public interface JavaMethodContext { + JavaMethod asJavaMethod(); +} diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.debug/src/com/oracle/graal/debug/LogStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/LogStream.java Wed Jul 29 11:59:18 2015 +0200 @@ -0,0 +1,477 @@ +/* + * 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.debug; + +import java.io.*; + +/** + * A utility for printing compiler debug and informational output to an output stream. + * + * A {@link LogStream} instance maintains an internal buffer that is flushed to the underlying + * output stream every time one of the {@code println} methods is invoked, or a newline character ( + * {@code '\n'}) is written. + * + * All of the {@code print} and {@code println} methods return the {code LogStream} instance on + * which they were invoked. This allows chaining of these calls to mitigate use of String + * concatenation by the caller. + * + * A {@code LogStream} maintains a current {@linkplain #indentationLevel() indentation} level. Each + * line of output written to this stream has {@code n} spaces prefixed to it where {@code n} is the + * value that would be returned by {@link #indentationLevel()} when the first character of a new + * line is written. + * + * A {@code LogStream} maintains a current {@linkplain #position() position} for the current line + * being written. This position can be advanced to a specified position by + * {@linkplain #fillTo(int, char) filling} this stream with a given character. + */ +public class LogStream { + + /** + * Null output stream that simply swallows any output sent to it. + */ + public static final LogStream SINK = new LogStream(); + + private static final PrintStream SINK_PS = new PrintStream(new OutputStream() { + + @Override + public void write(int b) throws IOException { + } + }); + + private LogStream() { + this.ps = null; + this.lineBuffer = null; + } + + /** + * The output stream to which this log stream writes. + */ + private final PrintStream ps; + + private final StringBuilder lineBuffer; + private int indentationLevel; + private char indentation = ' '; + private boolean indentationDisabled; + + public final PrintStream out() { + if (ps == null) { + return SINK_PS; + } + return ps; + } + + /** + * The system dependent line separator. + */ + public static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + /** + * Creates a new log stream. + * + * @param os the underlying output stream to which prints are sent + */ + public LogStream(OutputStream os) { + ps = os instanceof PrintStream ? (PrintStream) os : new PrintStream(os); + lineBuffer = new StringBuilder(100); + } + + /** + * Creates a new log stream that shares the same {@linkplain #ps output stream} as a given + * {@link LogStream}. + * + * @param log a LogStream whose output stream is shared with this one + */ + public LogStream(LogStream log) { + ps = log.ps; + lineBuffer = new StringBuilder(100); + } + + /** + * Prepends {@link #indentation} to the current output line until its write position is equal to + * the current {@linkplain #indentationLevel()} level. + */ + private void indent() { + if (ps != null) { + if (!indentationDisabled && indentationLevel != 0) { + while (lineBuffer.length() < indentationLevel) { + lineBuffer.append(indentation); + } + } + } + } + + private LogStream flushLine(boolean withNewline) { + if (ps != null) { + if (withNewline) { + lineBuffer.append(LINE_SEPARATOR); + } + ps.print(lineBuffer.toString()); + ps.flush(); + lineBuffer.setLength(0); + } + return this; + } + + /** + * Flushes the stream. This is done by terminating the current line if it is not at position 0 + * and then flushing the underlying output stream. + */ + public void flush() { + if (ps != null) { + if (lineBuffer.length() != 0) { + flushLine(false); + } + ps.flush(); + } + } + + /** + * Gets the current column position of this log stream. + * + * @return the current column position of this log stream + */ + public int position() { + return lineBuffer == null ? 0 : lineBuffer.length(); + + } + + /** + * Gets the current indentation level for this log stream. + * + * @return the current indentation level for this log stream. + */ + public int indentationLevel() { + return indentationLevel; + } + + /** + * Adjusts the current indentation level of this log stream. + * + * @param delta + */ + public void adjustIndentation(int delta) { + if (delta < 0) { + indentationLevel = Math.max(0, indentationLevel + delta); + } else { + indentationLevel += delta; + } + } + + /** + * Gets the current indentation character of this log stream. + */ + public char indentation() { + return indentation; + } + + public void disableIndentation() { + indentationDisabled = true; + } + + public void enableIndentation() { + indentationDisabled = false; + } + + /** + * Sets the character used for indentation. + */ + public void setIndentation(char c) { + indentation = c; + } + + /** + * Advances this stream's {@linkplain #position() position} to a given position by repeatedly + * appending a given character as necessary. + * + * @param position the position to which this stream's position will be advanced + * @param filler the character used to pad the stream + */ + public LogStream fillTo(int position, char filler) { + if (ps != null) { + indent(); + while (lineBuffer.length() < position) { + lineBuffer.append(filler); + } + } + return this; + } + + /** + * Writes a boolean value to this stream as {@code "true"} or {@code "false"}. + * + * @param b the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream print(boolean b) { + if (ps != null) { + indent(); + lineBuffer.append(b); + } + return this; + } + + /** + * Writes a boolean value to this stream followed by a {@linkplain #LINE_SEPARATOR line + * separator}. + * + * @param b the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream println(boolean b) { + if (ps != null) { + indent(); + lineBuffer.append(b); + return flushLine(true); + } + return this; + } + + /** + * Writes a character value to this stream. + * + * @param c the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream print(char c) { + if (ps != null) { + indent(); + lineBuffer.append(c); + if (c == '\n') { + if (lineBuffer.indexOf(LINE_SEPARATOR, lineBuffer.length() - LINE_SEPARATOR.length()) != -1) { + flushLine(false); + } + } + } + return this; + } + + /** + * Writes a character value to this stream followed by a {@linkplain #LINE_SEPARATOR line + * separator}. + * + * @param c the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream println(char c) { + if (ps != null) { + indent(); + lineBuffer.append(c); + flushLine(true); + } + return this; + } + + /** + * Prints an int value. + * + * @param i the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream print(int i) { + if (ps != null) { + indent(); + lineBuffer.append(i); + } + return this; + } + + /** + * Writes an int value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}. + * + * @param i the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream println(int i) { + if (ps != null) { + indent(); + lineBuffer.append(i); + return flushLine(true); + } + return this; + } + + /** + * Writes a float value to this stream. + * + * @param f the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream print(float f) { + if (ps != null) { + indent(); + lineBuffer.append(f); + } + return this; + } + + /** + * Writes a float value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator} + * . + * + * @param f the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream println(float f) { + if (ps != null) { + indent(); + lineBuffer.append(f); + return flushLine(true); + } + return this; + } + + /** + * Writes a long value to this stream. + * + * @param l the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream print(long l) { + if (ps != null) { + indent(); + lineBuffer.append(l); + } + return this; + } + + /** + * Writes a long value to this stream followed by a {@linkplain #LINE_SEPARATOR line separator}. + * + * @param l the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream println(long l) { + if (ps != null) { + indent(); + lineBuffer.append(l); + return flushLine(true); + } + return this; + } + + /** + * Writes a double value to this stream. + * + * @param d the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream print(double d) { + if (ps != null) { + indent(); + lineBuffer.append(d); + } + return this; + } + + /** + * Writes a double value to this stream followed by a {@linkplain #LINE_SEPARATOR line + * separator}. + * + * @param d the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream println(double d) { + if (ps != null) { + indent(); + lineBuffer.append(d); + return flushLine(true); + } + return this; + } + + /** + * Writes a {@code String} value to this stream. This method ensures that the + * {@linkplain #position() position} of this stream is updated correctly with respect to any + * {@linkplain #LINE_SEPARATOR line separators} present in {@code s}. + * + * @param s the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream print(String s) { + if (ps != null) { + if (s == null) { + indent(); + lineBuffer.append(s); + return this; + } + + int index = 0; + int next = s.indexOf(LINE_SEPARATOR, index); + while (index < s.length()) { + indent(); + if (next > index) { + lineBuffer.append(s.substring(index, next)); + flushLine(true); + index = next + LINE_SEPARATOR.length(); + next = s.indexOf(LINE_SEPARATOR, index); + } else { + lineBuffer.append(s.substring(index)); + break; + } + } + } + return this; + } + + /** + * Writes a {@code String} value to this stream followed by a {@linkplain #LINE_SEPARATOR line + * separator}. + * + * @param s the value to be printed + * @return this {@link LogStream} instance + */ + public LogStream println(String s) { + if (ps != null) { + print(s); + flushLine(true); + } + return this; + } + + /** + * Writes a formatted string to this stream. + * + * @param format a format string as described in {@link String#format(String, Object...)} + * @param args the arguments to be formatted + * @return this {@link LogStream} instance + */ + public LogStream printf(String format, Object... args) { + if (ps != null) { + print(String.format(format, args)); + } + return this; + } + + /** + * Writes a {@linkplain #LINE_SEPARATOR line separator} to this stream. + * + * @return this {@code LogStream} instance + */ + public LogStream println() { + if (ps != null) { + indent(); + flushLine(true); + } + return this; + } +} diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Management.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Management.java Wed Jul 29 11:59:18 2015 +0200 @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.debug; + +import static java.lang.Thread.*; + +import java.lang.management.*; + +import javax.management.*; + +public class Management { + + private static final com.sun.management.ThreadMXBean threadMXBean = Management.initThreadMXBean(); + + /** + * The amount of memory allocated by + * {@link com.sun.management.ThreadMXBean#getThreadAllocatedBytes(long)} itself. + */ + private static final long threadMXBeanOverhead = -getCurrentThreadAllocatedBytes() + getCurrentThreadAllocatedBytes(); + + public static long getCurrentThreadAllocatedBytes() { + return threadMXBean.getThreadAllocatedBytes(currentThread().getId()) - threadMXBeanOverhead; + } + + private static com.sun.management.ThreadMXBean initThreadMXBean() { + try { + return (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean(); + } catch (Error err) { + return new UnimplementedBean(); + } + } + + public static ThreadMXBean getThreadMXBean() { + return threadMXBean; + } + + private static class UnimplementedBean implements ThreadMXBean, com.sun.management.ThreadMXBean { + + public ObjectName getObjectName() { + return null; + } + + public long getThreadAllocatedBytes(long arg0) { + return 0; + } + + public long[] getThreadAllocatedBytes(long[] arg0) { + return null; + } + + public long[] getThreadCpuTime(long[] arg0) { + return null; + } + + public long[] getThreadUserTime(long[] arg0) { + return null; + } + + public boolean isThreadAllocatedMemoryEnabled() { + return false; + } + + public boolean isThreadAllocatedMemorySupported() { + return false; + } + + public void setThreadAllocatedMemoryEnabled(boolean arg0) { + } + + public int getThreadCount() { + return 0; + } + + public int getPeakThreadCount() { + return 0; + } + + public long getTotalStartedThreadCount() { + return 0; + } + + public int getDaemonThreadCount() { + return 0; + } + + public long[] getAllThreadIds() { + return null; + } + + public ThreadInfo getThreadInfo(long id) { + return null; + } + + public ThreadInfo[] getThreadInfo(long[] ids) { + return null; + } + + public ThreadInfo getThreadInfo(long id, int maxDepth) { + return null; + } + + public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) { + return null; + } + + public boolean isThreadContentionMonitoringSupported() { + return false; + } + + public boolean isThreadContentionMonitoringEnabled() { + return false; + } + + public void setThreadContentionMonitoringEnabled(boolean enable) { + } + + public long getCurrentThreadCpuTime() { + return 0; + } + + public long getCurrentThreadUserTime() { + return 0; + } + + public long getThreadCpuTime(long id) { + return 0; + } + + public long getThreadUserTime(long id) { + return 0; + } + + public boolean isThreadCpuTimeSupported() { + return false; + } + + public boolean isCurrentThreadCpuTimeSupported() { + return false; + } + + public boolean isThreadCpuTimeEnabled() { + return false; + } + + public void setThreadCpuTimeEnabled(boolean enable) { + } + + public long[] findMonitorDeadlockedThreads() { + return null; + } + + public void resetPeakThreadCount() { + } + + public long[] findDeadlockedThreads() { + return null; + } + + public boolean isObjectMonitorUsageSupported() { + return false; + } + + public boolean isSynchronizerUsageSupported() { + return false; + } + + public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) { + return null; + } + + public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) { + return null; + } + } +} diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.debug/src/com/oracle/graal/debug/TTY.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/TTY.java Wed Jul 29 11:59:18 2015 +0200 @@ -0,0 +1,302 @@ +/* + * 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.debug; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; +import java.util.regex.*; + +import jdk.internal.jvmci.service.*; + +/** + * A collection of static methods for printing debug and informational output to a global + * {@link LogStream}. The output can be (temporarily) suppressed per thread through use of a + * {@linkplain Filter filter}. + */ +public class TTY { + + /** + * Support for thread-local suppression of {@link TTY}. + */ + public static class Filter { + + private LogStream previous; + private final Thread thread = Thread.currentThread(); + + /** + * Creates an object that will suppress {@link TTY} for the current thread if the given + * filter does not match the given object. To revert the suppression state to how it was + * before this call, the {@link #remove()} method must be called on the suppression object. + * + * @param filter the pattern for matching. If {@code null}, then the match is successful. If + * it starts with "~", then a regular expression + * {@linkplain Pattern#matches(String, CharSequence) match} is performed where + * the regular expression is specified by {@code filter} without the "~" prefix. + * Otherwise, a simple {@linkplain String#contains(CharSequence) substring} match + * is performed where {@code filter} is the substring used. + * @param object an object whose {@linkplain Object#toString() string} value is matched + * against {@code filter} + */ + public Filter(String filter, Object object) { + boolean suppressed = false; + if (filter != null) { + String input = object.toString(); + if (filter.startsWith("~")) { + suppressed = !Pattern.matches(filter.substring(1), input); + } else { + suppressed = !input.contains(filter); + } + if (suppressed) { + previous = out(); + log.set(LogStream.SINK); + } + } + } + + /** + * Creates an object that will suppress {@link TTY} for the current thread. To revert the + * suppression state to how it was before this call, the {@link #remove()} method must be + * called on this filter object. + */ + public Filter() { + previous = out(); + log.set(LogStream.SINK); + } + + /** + * Reverts the suppression state of {@link TTY} to how it was before this object was + * constructed. + */ + public void remove() { + assert thread == Thread.currentThread(); + if (previous != null) { + log.set(previous); + } + } + } + + /** + * The {@link PrintStream} to which all non-suppressed output from {@link TTY} is written. + */ + public static final PrintStream out; + static { + TTYStreamProvider p = Services.loadSingle(TTYStreamProvider.class, false); + out = p == null ? System.out : p.getStream(); + } + + private static final ThreadLocal log = new ThreadLocal() { + + @Override + protected LogStream initialValue() { + return new LogStream(out); + } + }; + + public static boolean isSuppressed() { + return log.get() == LogStream.SINK; + } + + /** + * Gets the thread-local log stream to which the static methods of this class send their output. + * This will either be a global log stream or the global {@linkplain LogStream#SINK sink} + * depending on whether any suppression {@linkplain Filter filters} are in effect for the + * current thread. + */ + public static LogStream out() { + return log.get(); + } + + /** + * @see LogStream#print(String) + */ + public static void print(String s) { + out().print(s); + } + + /** + * @see LogStream#print(int) + */ + public static void print(int i) { + out().print(i); + } + + /** + * @see LogStream#print(long) + */ + public static void print(long i) { + out().print(i); + } + + /** + * @see LogStream#print(char) + */ + public static void print(char c) { + out().print(c); + } + + /** + * @see LogStream#print(boolean) + */ + public static void print(boolean b) { + out().print(b); + } + + /** + * @see LogStream#print(double) + */ + public static void print(double d) { + out().print(d); + } + + /** + * @see LogStream#print(float) + */ + public static void print(float f) { + out().print(f); + } + + /** + * @see LogStream#println(String) + */ + public static void println(String s) { + out().println(s); + } + + /** + * @see LogStream#println() + */ + public static void println() { + out().println(); + } + + /** + * @see LogStream#println(int) + */ + public static void println(int i) { + out().println(i); + } + + /** + * @see LogStream#println(long) + */ + public static void println(long l) { + out().println(l); + } + + /** + * @see LogStream#println(char) + */ + public static void println(char c) { + out().println(c); + } + + /** + * @see LogStream#println(boolean) + */ + public static void println(boolean b) { + out().println(b); + } + + /** + * @see LogStream#println(double) + */ + public static void println(double d) { + out().println(d); + } + + /** + * @see LogStream#println(float) + */ + public static void println(float f) { + out().println(f); + } + + public static void print(String format, Object... args) { + out().printf(format, args); + } + + public static void println(String format, Object... args) { + out().printf(format + "%n", args); + } + + public static void fillTo(int i) { + out().fillTo(i, ' '); + } + + public static void printFields(Class javaClass) { + final String className = javaClass.getSimpleName(); + TTY.println(className + " {"); + for (final Field field : javaClass.getFields()) { + printField(field, false); + } + TTY.println("}"); + } + + public static void printField(final Field field, boolean tabbed) { + final String fieldName = String.format("%35s", field.getName()); + try { + String prefix = tabbed ? "" : " " + fieldName + " = "; + String postfix = tabbed ? "\t" : "\n"; + if (field.getType() == int.class) { + TTY.print(prefix + field.getInt(null) + postfix); + } else if (field.getType() == boolean.class) { + TTY.print(prefix + field.getBoolean(null) + postfix); + } else if (field.getType() == float.class) { + TTY.print(prefix + field.getFloat(null) + postfix); + } else if (field.getType() == String.class) { + TTY.print(prefix + field.get(null) + postfix); + } else if (field.getType() == Map.class) { + Map m = (Map) field.get(null); + TTY.print(prefix + printMap(m) + postfix); + } else { + TTY.print(prefix + field.get(null) + postfix); + } + } catch (IllegalAccessException e) { + // do nothing. + } + } + + private static String printMap(Map m) { + StringBuilder sb = new StringBuilder(); + + List keys = new ArrayList<>(); + for (Object key : m.keySet()) { + keys.add((String) key); + } + Collections.sort(keys); + + for (String key : keys) { + sb.append(key); + sb.append("\t"); + sb.append(m.get(key)); + sb.append("\n"); + } + + return sb.toString(); + } + + public static void flush() { + out().flush(); + } +} diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.debug/src/com/oracle/graal/debug/TTYStreamProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/TTYStreamProvider.java Wed Jul 29 11:59:18 2015 +0200 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.debug; + +import java.io.*; + +/** + * Provides a {@link PrintStream} that writes to the underlying log stream of the VM. + */ +public interface TTYStreamProvider { + PrintStream getStream(); +} diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Wed Jul 29 11:59:18 2015 +0200 @@ -26,8 +26,6 @@ import java.util.*; import java.util.concurrent.*; -import jdk.internal.jvmci.debug.*; - import com.oracle.graal.debug.*; public final class DebugScope implements Debug.Scope { diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java Wed Jul 29 11:59:18 2015 +0200 @@ -23,8 +23,6 @@ package com.oracle.graal.debug.internal; import static com.oracle.graal.debug.DebugCloseable.*; -import jdk.internal.jvmci.debug.*; - import com.oracle.graal.debug.*; public final class MemUseTrackerImpl extends AccumulatedDebugValue implements DebugMemUseTracker { diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java Wed Jul 29 11:59:18 2015 +0200 @@ -27,8 +27,6 @@ import java.lang.management.*; import java.util.concurrent.*; -import jdk.internal.jvmci.debug.*; - import com.oracle.graal.debug.*; public final class TimerImpl extends AccumulatedDebugValue implements DebugTimer { diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Wed Jul 29 11:59:18 2015 +0200 @@ -349,6 +349,7 @@ SPARCCall.indirectJmp(crb, masm, scratch, foreignCalls.lookupForeignCall(IC_MISS_HANDLER)); } } + masm.peephole(); } private static int calculateConstantSize(LIR lir) { diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationStatistics.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationStatistics.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationStatistics.java Wed Jul 29 11:59:18 2015 +0200 @@ -30,9 +30,9 @@ import java.util.*; import java.util.concurrent.*; -import jdk.internal.jvmci.debug.*; import jdk.internal.jvmci.hotspot.*; +import com.oracle.graal.debug.*; import com.sun.management.*; @SuppressWarnings("unused") diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Wed Jul 29 11:59:18 2015 +0200 @@ -33,7 +33,6 @@ import jdk.internal.jvmci.code.*; import jdk.internal.jvmci.compiler.Compiler; -import jdk.internal.jvmci.debug.*; import jdk.internal.jvmci.hotspot.*; import jdk.internal.jvmci.hotspot.events.*; import jdk.internal.jvmci.hotspot.events.EventProvider.CompilationEvent; diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Wed Jul 29 11:59:18 2015 +0200 @@ -35,7 +35,6 @@ import java.util.stream.*; import jdk.internal.jvmci.compiler.Compiler; -import jdk.internal.jvmci.debug.*; import jdk.internal.jvmci.hotspot.*; import jdk.internal.jvmci.meta.*; import jdk.internal.jvmci.options.*; diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugValuesPrinter.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugValuesPrinter.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugValuesPrinter.java Wed Jul 29 11:59:18 2015 +0200 @@ -30,8 +30,8 @@ import java.util.stream.*; import jdk.internal.jvmci.common.*; -import jdk.internal.jvmci.debug.*; +import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; /** diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Wed Jul 29 11:59:18 2015 +0200 @@ -23,9 +23,9 @@ package com.oracle.graal.hotspot; import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.debug.GraalDebugConfig.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.Options.*; import static jdk.internal.jvmci.common.UnsafeAccess.*; -import static com.oracle.graal.debug.GraalDebugConfig.*; import static jdk.internal.jvmci.hotspot.InitTimer.*; import java.lang.reflect.*; @@ -34,12 +34,7 @@ import jdk.internal.jvmci.code.*; import jdk.internal.jvmci.code.stack.*; import jdk.internal.jvmci.common.*; -import jdk.internal.jvmci.debug.*; - -import com.oracle.graal.debug.*; - import jdk.internal.jvmci.hotspot.*; -import jdk.internal.jvmci.hotspot.logging.*; import jdk.internal.jvmci.meta.*; import jdk.internal.jvmci.options.*; import jdk.internal.jvmci.runtime.*; @@ -49,8 +44,10 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.target.*; +import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.debug.*; +import com.oracle.graal.hotspot.logging.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.replacements.*; import com.oracle.graal.runtime.*; diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalVMEventListener.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalVMEventListener.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalVMEventListener.java Wed Jul 29 11:59:18 2015 +0200 @@ -22,12 +22,15 @@ */ package com.oracle.graal.hotspot; +import java.lang.reflect.*; +import java.util.*; + import jdk.internal.jvmci.code.*; -import jdk.internal.jvmci.debug.*; import jdk.internal.jvmci.hotspot.*; import jdk.internal.jvmci.service.*; import com.oracle.graal.debug.*; +import com.oracle.graal.hotspot.logging.*; @ServiceProvider(HotSpotVMEventListener.class) public class HotSpotGraalVMEventListener implements HotSpotVMEventListener { @@ -65,4 +68,36 @@ Debug.log("%s", codeCache.disassemble(installedCode)); } } + + @Override + public CompilerToVM completeInitialization(HotSpotJVMCIRuntime runtime, CompilerToVM compilerToVM) { + CompilerToVM toVM = compilerToVM; + if (CountingProxy.ENABLED) { + toVM = CountingProxy.getProxy(CompilerToVM.class, toVM); + } + if (Logger.ENABLED) { + toVM = LoggingProxy.getProxy(CompilerToVM.class, toVM); + } + + if (Boolean.valueOf(System.getProperty("jvmci.printconfig"))) { + printConfig(runtime.getConfig()); + } + + return toVM; + } + + private static void printConfig(HotSpotVMConfig config) { + Field[] fields = config.getClass().getDeclaredFields(); + Map sortedFields = new TreeMap<>(); + for (Field f : fields) { + f.setAccessible(true); + sortedFields.put(f.getName(), f); + } + for (Field f : sortedFields.values()) { + try { + Logger.info(String.format("%9s %-40s = %s", f.getType().getSimpleName(), f.getName(), Logger.pretty(f.get(config)))); + } catch (Exception e) { + } + } + } } diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Wed Jul 29 11:59:18 2015 +0200 @@ -29,11 +29,10 @@ import java.util.concurrent.atomic.*; import jdk.internal.jvmci.common.*; -import jdk.internal.jvmci.debug.*; - import jdk.internal.jvmci.hotspot.*; import jdk.internal.jvmci.options.*; +import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.debug.*; diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java Wed Jul 29 11:59:18 2015 +0200 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.logging; + +import java.lang.reflect.*; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; + +import com.oracle.graal.debug.*; + +/** + * A java.lang.reflect proxy that hierarchically logs all method invocations along with their + * parameters and return values. + */ +public class CountingProxy implements InvocationHandler { + + public static final boolean ENABLED = Boolean.valueOf(System.getProperty("jvmci.countcalls")); + + private T delegate; + + private ConcurrentHashMap calls = new ConcurrentHashMap<>(); + + public CountingProxy(T delegate) { + assert ENABLED; + TTY.println("Counting proxy for " + delegate.getClass().getSimpleName() + " created"); + this.delegate = delegate; + proxies.add(this); + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + int argCount = args == null ? 0 : args.length; + if (method.getParameterTypes().length != argCount) { + throw new RuntimeException("wrong parameter count"); + } + final Object result; + if (!calls.containsKey(method)) { + calls.putIfAbsent(method, new AtomicLong(0)); + } + AtomicLong count = calls.get(method); + count.incrementAndGet(); + try { + if (args == null) { + result = method.invoke(delegate); + } else { + result = method.invoke(delegate, args); + } + } catch (InvocationTargetException e) { + throw e.getCause(); + } + return result; + } + + public static T getProxy(Class interf, T delegate) { + Class[] interfaces = ProxyUtil.getAllInterfaces(delegate.getClass()); + Object obj = Proxy.newProxyInstance(interf.getClassLoader(), interfaces, new CountingProxy<>(delegate)); + return interf.cast(obj); + } + + private static ArrayList> proxies = new ArrayList<>(); + + static { + if (ENABLED) { + Runtime.getRuntime().addShutdownHook(new Thread() { + + @Override + public void run() { + for (CountingProxy proxy : proxies) { + proxy.print(); + } + } + }); + } + } + + protected void print() { + long sum = 0; + for (Map.Entry entry : calls.entrySet()) { + Method method = entry.getKey(); + long count = entry.getValue().get(); + sum += count; + TTY.println(delegate.getClass().getSimpleName() + "." + method.getName() + ": " + count); + } + TTY.println(delegate.getClass().getSimpleName() + " calls: " + sum); + } +} diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/HotSpotTTYStreamProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/HotSpotTTYStreamProvider.java Wed Jul 29 11:59:18 2015 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.logging; + +import java.io.*; + +import com.oracle.graal.debug.*; + +import jdk.internal.jvmci.hotspot.HotSpotJVMCIRuntime.*; +import jdk.internal.jvmci.service.*; + +@ServiceProvider(TTYStreamProvider.class) +class HotSpotTTYStreamProvider implements TTYStreamProvider { + + public PrintStream getStream() { + return Options.LogFile.getStream(); + } +} diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/Logger.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/Logger.java Wed Jul 29 11:59:18 2015 +0200 @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.logging; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.debug.*; + +import jdk.internal.jvmci.hotspot.*; + +/** + * Scoped logging class used to display the call hierarchy of {@link CompilerToVM} calls. + */ +public class Logger { + + public static final boolean ENABLED = Boolean.valueOf(System.getProperty("jvmci.debug")); + private static final int SPACING = 4; + private static final ThreadLocal loggerTL; + + private Deque openStack = new LinkedList<>(); + private boolean open = false; + private int level = 0; + + private static final PrintStream out; + + static { + if (ENABLED) { + loggerTL = new ThreadLocal() { + + @Override + protected Logger initialValue() { + return new Logger(); + } + }; + } else { + loggerTL = null; + } + + PrintStream ps = null; + String filename = System.getProperty("jvmci.info_file"); + if (filename != null && !"".equals(filename)) { + try { + ps = new PrintStream(new FileOutputStream(filename)); + } catch (FileNotFoundException e) { + e.printStackTrace(); + ps = null; + } + } + out = ps; + if (out != null) { + out.println("start: " + new Date()); + } + } + + public static void info(String message) { + if (ENABLED) { + log(message); + } else { + TTY.println(message); + } + if (out != null) { + out.println(message); + out.flush(); + } + } + + public static void log(String message) { + if (ENABLED) { + Logger logger = loggerTL.get(); + for (String line : message.split("\n")) { + if (logger.open) { + TTY.println("..."); + logger.open = false; + } + TTY.print(space(logger.level)); + TTY.println(line); + } + } + } + + public static void startScope(String message) { + if (ENABLED) { + Logger logger = loggerTL.get(); + if (logger.open) { + TTY.println("..."); + logger.open = false; + } + TTY.print(space(logger.level)); + TTY.print(message); + logger.openStack.push(logger.open); + logger.open = true; + logger.level++; + } + } + + public static void endScope(String message) { + if (ENABLED) { + Logger logger = loggerTL.get(); + logger.level--; + if (logger.open) { + TTY.println(message); + } else { + TTY.println(space(logger.level) + "..." + message); + } + logger.open = logger.openStack.pop(); + } + } + + private static String[] spaces = new String[50]; + + private static String space(int count) { + assert count >= 0; + String result; + if (count >= spaces.length || spaces[count] == null) { + StringBuilder str = new StringBuilder(); + for (int i = 0; i < count * SPACING; i++) { + str.append(' '); + } + result = str.toString(); + if (count < spaces.length) { + spaces[count] = result; + } + } else { + result = spaces[count]; + } + return result; + } + + public static String pretty(Object value) { + if (value == null) { + return "null"; + } + + Class klass = value.getClass(); + if (value instanceof Void) { + return "void"; + } else if (value instanceof String) { + return "\"" + value + "\""; + } else if (value instanceof Method) { + return "method \"" + ((Method) value).getName() + "\""; + } else if (value instanceof Class) { + return "class \"" + ((Class) value).getSimpleName() + "\""; + } else if (value instanceof Integer) { + if ((Integer) value < 10) { + return value.toString(); + } + return value + " (0x" + Integer.toHexString((Integer) value) + ")"; + } else if (value instanceof Long) { + if ((Long) value < 10 && (Long) value > -10) { + return value + "l"; + } + return value + "l (0x" + Long.toHexString((Long) value) + "l)"; + } else if (klass.isArray()) { + StringBuilder str = new StringBuilder(); + int dimensions = 0; + while (klass.isArray()) { + dimensions++; + klass = klass.getComponentType(); + } + int length = Array.getLength(value); + str.append(klass.getSimpleName()).append('[').append(length).append(']'); + for (int i = 1; i < dimensions; i++) { + str.append("[]"); + } + str.append(" {"); + for (int i = 0; i < length; i++) { + str.append(pretty(Array.get(value, i))); + if (i < length - 1) { + str.append(", "); + } + } + str.append('}'); + return str.toString(); + } + + return value.toString(); + } +} diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/LoggingProxy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/LoggingProxy.java Wed Jul 29 11:59:18 2015 +0200 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.logging; + +import java.lang.reflect.*; + +/** + * A java.lang.reflect proxy that hierarchically logs all method invocations along with their + * parameters and return values. + */ +public class LoggingProxy implements InvocationHandler { + + private T delegate; + + public LoggingProxy(T delegate) { + this.delegate = delegate; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + int argCount = args == null ? 0 : args.length; + if (method.getParameterTypes().length != argCount) { + throw new RuntimeException("wrong parameter count"); + } + StringBuilder str = new StringBuilder(); + str.append(method.getReturnType().getSimpleName() + " " + method.getDeclaringClass().getSimpleName() + "." + method.getName() + "("); + for (int i = 0; i < argCount; i++) { + str.append(i == 0 ? "" : ", "); + str.append(Logger.pretty(args[i])); + } + str.append(")"); + Logger.startScope(str.toString()); + final Object result; + try { + if (args == null) { + result = method.invoke(delegate); + } else { + result = method.invoke(delegate, args); + } + } catch (InvocationTargetException e) { + Logger.endScope(" = Exception " + e.getMessage()); + throw e.getCause(); + } + Logger.endScope(" = " + Logger.pretty(result)); + return result; + } + + /** + * The object returned by this method will implement all interfaces that are implemented by + * delegate. + */ + public static T getProxy(Class interf, T delegate) { + Class[] interfaces = ProxyUtil.getAllInterfaces(delegate.getClass()); + Object obj = Proxy.newProxyInstance(interf.getClassLoader(), interfaces, new LoggingProxy<>(delegate)); + return interf.cast(obj); + } +} diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/ProxyUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/ProxyUtil.java Wed Jul 29 11:59:18 2015 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.logging; + +import java.util.*; + +public final class ProxyUtil { + + public static Class[] getAllInterfaces(Class clazz) { + HashSet> interfaces = new HashSet<>(); + getAllInterfaces(clazz, interfaces); + return interfaces.toArray(new Class[interfaces.size()]); + } + + private static void getAllInterfaces(Class clazz, HashSet> interfaces) { + for (Class iface : clazz.getInterfaces()) { + if (!interfaces.contains(iface)) { + interfaces.add(iface); + getAllInterfaces(iface, interfaces); + } + } + if (clazz.getSuperclass() != null) { + getAllInterfaces(clazz.getSuperclass(), interfaces); + } + } +} diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Wed Jul 29 11:59:18 2015 +0200 @@ -57,63 +57,63 @@ } } - @Snippet(removeAllFrameStates = true) + @Snippet public static boolean[] booleanArrayClone(boolean[] src) { boolean[] result = (boolean[]) NewArrayNode.newUninitializedArray(Boolean.TYPE, src.length); ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Boolean); return result; } - @Snippet(removeAllFrameStates = true) + @Snippet public static byte[] byteArrayClone(byte[] src) { byte[] result = (byte[]) NewArrayNode.newUninitializedArray(Byte.TYPE, src.length); ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Byte); return result; } - @Snippet(removeAllFrameStates = true) + @Snippet public static short[] shortArrayClone(short[] src) { short[] result = (short[]) NewArrayNode.newUninitializedArray(Short.TYPE, src.length); ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Short); return result; } - @Snippet(removeAllFrameStates = true) + @Snippet public static char[] charArrayClone(char[] src) { char[] result = (char[]) NewArrayNode.newUninitializedArray(Character.TYPE, src.length); ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Char); return result; } - @Snippet(removeAllFrameStates = true) + @Snippet public static int[] intArrayClone(int[] src) { int[] result = (int[]) NewArrayNode.newUninitializedArray(Integer.TYPE, src.length); ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Int); return result; } - @Snippet(removeAllFrameStates = true) + @Snippet public static float[] floatArrayClone(float[] src) { float[] result = (float[]) NewArrayNode.newUninitializedArray(Float.TYPE, src.length); ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Float); return result; } - @Snippet(removeAllFrameStates = true) + @Snippet public static long[] longArrayClone(long[] src) { long[] result = (long[]) NewArrayNode.newUninitializedArray(Long.TYPE, src.length); ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Long); return result; } - @Snippet(removeAllFrameStates = true) + @Snippet public static double[] doubleArrayClone(double[] src) { double[] result = (double[]) NewArrayNode.newUninitializedArray(Double.TYPE, src.length); ArrayCopyCallNode.disjointArraycopy(src, 0, result, 0, src.length, Kind.Double); return result; } - @Snippet(removeAllFrameStates = true) + @Snippet public static Object[] objectArrayClone(Object[] src) { /* Since this snippet is lowered early the array must be initialized */ Object[] result = (Object[]) DynamicNewArrayNode.newArray(GraalDirectives.guardingNonNull(src.getClass().getComponentType()), src.length, Kind.Object); diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java Wed Jul 29 11:59:18 2015 +0200 @@ -464,7 +464,7 @@ /* * At least one array is of a known type requiring no store checks, so * assume the other is of the same type. Generally this is working around - * deficiencies in our propation of type information. + * deficiencies in our propagation of type information. */ componentKind = predictedKind; if (predictedKind == Kind.Object) { diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Wed Jul 29 11:59:18 2015 +0200 @@ -113,7 +113,7 @@ return null; } - private class DebugScopeContext implements JavaMethod, JavaMethodContex { + private class DebugScopeContext implements JavaMethod, JavaMethodContext { public JavaMethod asJavaMethod() { return this; } diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java Wed Jul 29 11:59:18 2015 +0200 @@ -38,8 +38,6 @@ import jdk.internal.jvmci.code.*; import jdk.internal.jvmci.common.*; import jdk.internal.jvmci.compiler.Compiler; -import jdk.internal.jvmci.debug.*; - import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Wed Jul 29 11:59:18 2015 +0200 @@ -22,10 +22,6 @@ */ package com.oracle.graal.lir.sparc; -import jdk.internal.jvmci.code.*; -import jdk.internal.jvmci.common.*; -import jdk.internal.jvmci.meta.*; -import jdk.internal.jvmci.sparc.*; import static com.oracle.graal.asm.sparc.SPARCAssembler.*; import static com.oracle.graal.asm.sparc.SPARCAssembler.Annul.*; import static com.oracle.graal.asm.sparc.SPARCAssembler.BranchPredict.*; @@ -35,11 +31,15 @@ import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import static jdk.internal.jvmci.code.ValueUtil.*; import static jdk.internal.jvmci.sparc.SPARC.*; -import static jdk.internal.jvmci.sparc.SPARC.CPUFeature.*; +import jdk.internal.jvmci.code.*; +import jdk.internal.jvmci.common.*; +import jdk.internal.jvmci.meta.*; +import jdk.internal.jvmci.sparc.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.gen.*; @@ -414,7 +414,7 @@ Label noOverflow = new Label(); masm.sra(asIntReg(dst), 0, tmp); masm.xorcc(SPARC.g0, SPARC.g0, SPARC.g0); - if (masm.hasFeature(CBCOND)) { + if (masm.hasFeature(SPARC.CPUFeature.CBCOND)) { masm.cbcondx(Equal, tmp, asIntReg(dst), noOverflow); // Is necessary, otherwise we will have a penalty of 5 cycles in S3 masm.nop(); diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java Wed Jul 29 11:59:18 2015 +0200 @@ -41,7 +41,7 @@ @Def({REG, HINT}) protected Value result; @Use({REG}) protected Value input; @Temp({REG}) protected Value tempIndex; - @Use({STACK}) protected StackSlotValue tmpSlot; + @Use({STACK, UNINITIALIZED}) protected StackSlotValue tmpSlot; public SPARCByteSwapOp(LIRGeneratorTool tool, Value result, Value input) { super(TYPE, SIZE); diff -r 992575891f42 -r aeb7a47e272d graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Tue Jul 28 17:35:49 2015 -0700 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Wed Jul 29 11:59:18 2015 +0200 @@ -31,13 +31,13 @@ import static com.oracle.graal.lir.sparc.SPARCMove.*; import static jdk.internal.jvmci.code.ValueUtil.*; import static jdk.internal.jvmci.sparc.SPARC.*; -import static jdk.internal.jvmci.sparc.SPARC.CPUFeature.*; import java.util.*; import jdk.internal.jvmci.code.*; import jdk.internal.jvmci.common.*; import jdk.internal.jvmci.meta.*; +import jdk.internal.jvmci.sparc.*; import jdk.internal.jvmci.sparc.SPARC.CPUFeature; import com.oracle.graal.asm.*; @@ -310,12 +310,15 @@ private static boolean isShortBranch(SPARCAssembler asm, int position, LabelHint hint, Label label) { int disp = 0; + boolean dispValid = true; if (label.isBound()) { disp = label.position() - position; } else if (hint != null && hint.isValid()) { disp = hint.getTarget() - hint.getPosition(); + } else { + dispValid = false; } - if (disp != 0) { + if (dispValid) { if (disp < 0) { disp -= maximumSelfOffsetInstructions * asm.target.wordSize; } else { @@ -402,7 +405,8 @@ @Alive({REG, ILLEGAL}) protected Value constantTableBase; @Temp({REG}) protected Value scratch; private final SwitchStrategy strategy; - private final LabelHint[] labelHints; + private final Map labelHints; + private final List