# HG changeset patch # User Gilles Duboscq # Date 1327576980 -3600 # Node ID d13bfce7b3dd786a1981015162e4adc90fb2e824 # Parent 4aacce9c9cb99f2fa2ce8f21ed64149d27550604# Parent b0aa4a52b89c68fa8a949341e17bf1cf8623d1d2 Merge diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiValueUtil.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiValueUtil.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiValueUtil.java Thu Jan 26 12:23:00 2012 +0100 @@ -110,25 +110,19 @@ } - public static boolean sameRegister(CiValue...values) { - for (int i = 0; i < values.length; i++) { - for (int j = i + 1; j < values.length; j++) { - if (isRegister(values[i]) && isRegister(values[j]) && asRegister(values[i]) != asRegister(values[j])) { - return false; - } - } - } - return true; + public static boolean sameRegister(CiValue v1, CiValue v2) { + return isRegister(v1) && isRegister(v2) && asRegister(v1) == asRegister(v2); + } + + public static boolean sameRegister(CiValue v1, CiValue v2, CiValue v3) { + return sameRegister(v1, v2) && sameRegister(v1, v3); } - public static boolean differentRegisters(CiValue...values) { - for (int i = 0; i < values.length; i++) { - for (int j = i + 1; j < values.length; j++) { - if (isRegister(values[i]) && isRegister(values[j]) && asRegister(values[i]) == asRegister(values[j])) { - return false; - } - } - } - return true; + public static boolean differentRegisters(CiValue v1, CiValue v2) { + return !isRegister(v1) || !isRegister(v2) || asRegister(v1) != asRegister(v2); + } + + public static boolean differentRegisters(CiValue v1, CiValue v2, CiValue v3) { + return differentRegisters(v1, v2) && differentRegisters(v1, v3) && differentRegisters(v2, v3); } } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiRuntime.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiRuntime.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiRuntime.java Thu Jan 26 12:23:00 2012 +0100 @@ -186,7 +186,7 @@ * @param method a method whose executable code is being modified * @param code the code to be executed when {@code method} is called */ - void installMethod(RiMethod method, CiTargetMethod code); + void installMethod(RiResolvedMethod method, CiTargetMethod code); /** * Adds the given machine code as an implementation of the given method without making it the default implementation. diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java Thu Jan 26 12:23:00 2012 +0100 @@ -76,7 +76,7 @@ if (op instanceof LIRXirInstruction) { LIRXirInstruction xir = (LIRXirInstruction) op; if (xir.infoAfter != null) { - xir.infoAfter.finish(op.hasCall() ? null : new CiBitMap(curRegisterRefMap), new CiBitMap(curFrameRefMap), frameMap); + xir.infoAfter.finish(new CiBitMap(curRegisterRefMap), new CiBitMap(curFrameRefMap), frameMap); } } } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java Thu Jan 26 12:23:00 2012 +0100 @@ -55,14 +55,14 @@ this.dataFlow = new DataFlowAnalysis(lir, frameMap.registerConfig); this.blockBeginLocations = new LocationMap[lir.linearScanOrder().size()]; this.blockEndLocations = new LocationMap[lir.linearScanOrder().size()]; - this.moveResolver = new MoveResolverImpl(frameMap); + this.moveResolver = new MoveResolverImpl(lir, frameMap); this.variableLastUse = new int[lir.numVariables()]; } private class MoveResolverImpl extends MoveResolver { - public MoveResolverImpl(FrameMap frameMap) { - super(frameMap); + public MoveResolverImpl(LIR lir, FrameMap frameMap) { + super(lir, frameMap); } @Override diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java Thu Jan 26 12:23:00 2012 +0100 @@ -104,7 +104,7 @@ if (fromBlock.numberOfSux() == 1) { List instructions = fromBlock.lir(); LIRInstruction instr = instructions.get(instructions.size() - 1); - assert instr instanceof LIRBranch && instr.code == StandardOpcode.JUMP : "block does not end with an unconditional jump"; + assert instr instanceof StandardOp.JumpOp : "block does not end with an unconditional jump"; moveResolver.init(instructions, instructions.size() - 1); assert trace(" insert at end of %s before %d", fromBlock, instructions.size() - 1); diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java Thu Jan 26 12:23:00 2012 +0100 @@ -54,12 +54,12 @@ this.dataFlow = new DataFlowAnalysis(lir, frameMap.registerConfig); this.blockLocations = new LocationMap[lir.linearScanOrder().size()]; - this.moveResolver = new MoveResolverImpl(frameMap); + this.moveResolver = new MoveResolverImpl(lir, frameMap); } private class MoveResolverImpl extends MoveResolver { - public MoveResolverImpl(FrameMap frameMap) { - super(frameMap); + public MoveResolverImpl(LIR lir, FrameMap frameMap) { + super(lir, frameMap); } @Override diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/LIRVerifier.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/LIRVerifier.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.alloc.util; - -import static com.oracle.max.cri.ci.CiValueUtil.*; -import static com.oracle.max.graal.alloc.util.ValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; -import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; -import com.oracle.max.graal.compiler.schedule.*; -import com.oracle.max.graal.compiler.util.*; - -public final class LIRVerifier { - private final LIR lir; - private final FrameMap frameMap; - - private final boolean beforeRegisterAllocation; - - private final BitSet[] blockLiveOut; - private final Object[] variableDefinitions; - - private BitSet liveOutFor(Block block) { - return blockLiveOut[block.blockID()]; - } - private void setLiveOutFor(Block block, BitSet liveOut) { - blockLiveOut[block.blockID()] = liveOut; - } - - private int maxRegisterNum() { - return frameMap.target.arch.registers.length; - } - - private boolean isAllocatableRegister(CiValue value) { - return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; - } - - public static boolean verify(final LIRInstruction op) { - ValueProcedure allowedProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { return allowed(op, value, mode, flags); } }; - - op.forEachInput(allowedProc); - op.forEachAlive(allowedProc); - op.forEachState(allowedProc); - op.forEachTemp(allowedProc); - op.forEachOutput(allowedProc); - return true; - } - - public static boolean verify(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap) { - LIRVerifier verifier = new LIRVerifier(beforeRegisterAllocation, lir, frameMap); - verifier.verify(); - return true; - } - - - private LIRVerifier(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap) { - this.beforeRegisterAllocation = beforeRegisterAllocation; - this.lir = lir; - this.frameMap = frameMap; - this.blockLiveOut = new BitSet[lir.linearScanOrder().size()]; - this.variableDefinitions = new Object[lir.numVariables()]; - } - - private BitSet curVariablesLive; - private CiValue[] curRegistersLive; - - private LIRBlock curBlock; - private Object curInstruction; - private BitSet curRegistersDefined; - - private void verify() { - PhiValueProcedure useProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { return use(value, mode, flags); } }; - ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { return def(value, mode, flags); } }; - - curRegistersDefined = new BitSet(); - for (LIRBlock block : lir.linearScanOrder()) { - curBlock = block; - curVariablesLive = new BitSet(); - curRegistersLive = new CiValue[maxRegisterNum()]; - - if (block.dominator() != null) { - curVariablesLive.or(liveOutFor(block.dominator())); - } - - if (block.phis != null) { - assert beforeRegisterAllocation; - curInstruction = block.phis; - block.phis.forEachOutput(defProc); - } - - for (LIRInstruction op : block.lir()) { - curInstruction = op; - - op.forEachInput(useProc); - if (op.hasCall()) { - for (CiRegister register : frameMap.registerConfig.getCallerSaveRegisters()) { - curRegistersLive[register.number] = null; - } - } - curRegistersDefined.clear(); - op.forEachAlive(useProc); - op.forEachState(useProc); - op.forEachTemp(defProc); - op.forEachOutput(defProc); - - curInstruction = null; - } - - for (LIRBlock sux : block.getLIRSuccessors()) { - if (sux.phis != null) { - assert beforeRegisterAllocation; - curInstruction = sux.phis; - sux.phis.forEachInput(block, useProc); - } - } - - setLiveOutFor(block, curVariablesLive); - } - } - - private CiValue use(CiValue value, OperandMode mode, EnumSet flags) { - allowed(curInstruction, value, mode, flags); - - if (isVariable(value)) { - assert beforeRegisterAllocation; - - int variableIdx = asVariable(value).index; - if (!curVariablesLive.get(variableIdx)) { - TTY.println("block %s instruction %s", curBlock, curInstruction); - TTY.println("live variables: %s", curVariablesLive); - if (variableDefinitions[variableIdx] != null) { - TTY.println("definition of %s: %s", value, variableDefinitions[variableIdx]); - } - TTY.println("ERROR: Use of variable %s that is not defined in dominator", value); - throw Util.shouldNotReachHere(); - } - - } else if (isAllocatableRegister(value)) { - int regNum = asRegister(value).number; - if (mode == OperandMode.Alive) { - curRegistersDefined.set(regNum); - } - - if (beforeRegisterAllocation && curRegistersLive[regNum] != value) { - TTY.println("block %s instruction %s", curBlock, curInstruction); - TTY.println("live registers: %s", Arrays.toString(curRegistersLive)); - TTY.println("ERROR: Use of fixed register %s that is not defined in this block", value); - throw Util.shouldNotReachHere(); - } - } - return value; - } - - private CiValue def(CiValue value, OperandMode mode, EnumSet flags) { - allowed(curInstruction, value, mode, flags); - - if (isVariable(value)) { - assert beforeRegisterAllocation; - - int variableIdx = asVariable(value).index; - if (variableDefinitions[variableIdx] != null) { - TTY.println("block %s instruction %s", curBlock, curInstruction); - TTY.println("live variables: %s", curVariablesLive); - TTY.println("definition of %s: %s", value, variableDefinitions[variableIdx]); - TTY.println("ERROR: Variable %s defined multiple times", value); - throw Util.shouldNotReachHere(); - } - assert curInstruction != null; - variableDefinitions[variableIdx] = curInstruction; - assert !curVariablesLive.get(variableIdx); - if (mode == OperandMode.Output) { - curVariablesLive.set(variableIdx); - } - - } else if (isAllocatableRegister(value)) { - int regNum = asRegister(value).number; - if (curRegistersDefined.get(regNum)) { - TTY.println("block %s instruction %s", curBlock, curInstruction); - TTY.println("ERROR: Same register defined twice in the same instruction: %s", value); - throw Util.shouldNotReachHere(); - } - curRegistersDefined.set(regNum); - - if (beforeRegisterAllocation) { - if (mode == OperandMode.Output) { - curRegistersLive[regNum] = value; - } else { - curRegistersLive[regNum] = null; - } - } - } - return value; - } - - private static CiValue allowed(Object op, CiValue value, OperandMode mode, EnumSet flags) { - if ((isVariable(value) && flags.contains(OperandFlag.Register)) || - (isRegister(value) && flags.contains(OperandFlag.Register)) || - (isStackSlot(value) && flags.contains(OperandFlag.Stack)) || - (isConstant(value) && flags.contains(OperandFlag.Constant) && mode != OperandMode.Output) || - (isIllegal(value) && flags.contains(OperandFlag.Illegal))) { - return value; - } - TTY.println("instruction %s", op); - TTY.println("mode: %s flags: %s", mode, flags); - TTY.println("Unexpected value: %s %s", value.getClass().getSimpleName(), value); - throw Util.shouldNotReachHere(); - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java Thu Jan 26 12:23:00 2012 +0100 @@ -34,6 +34,7 @@ import com.oracle.max.graal.compiler.util.*; public abstract class MoveResolver { + private final LIR lir; private final FrameMap frameMap; private final int[] registersBlocked; private final Map valuesBlocked; @@ -42,7 +43,8 @@ private final LIRInsertionBuffer insertionBuffer; private int insertPos; - public MoveResolver(FrameMap frameMap) { + public MoveResolver(LIR lir, FrameMap frameMap) { + this.lir = lir; this.frameMap = frameMap; registersBlocked = new int[frameMap.target.arch.registers.length]; @@ -292,7 +294,7 @@ } else { assert trace("mr MOV %s -> %s", src, dst); - insertionBuffer.append(insertPos, StandardOpcode.SPILL_MOVE.create(dst, src)); + insertionBuffer.append(insertPos, lir.spillMoveFactory.createMove(dst, src)); } } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java Thu Jan 26 12:23:00 2012 +0100 @@ -203,14 +203,18 @@ } private CiValue temp(CiValue value) { - assert trace(" temp %s -> remove key %s", value, key(value)); - curInputState.remove(key(value)); + if (!isConstant(value) && value != CiValue.IllegalValue && !isIgnoredRegister(value)) { + assert trace(" temp %s -> remove key %s", value, key(value)); + curInputState.remove(key(value)); + } return value; } private CiValue output(CiValue value) { - assert trace(" output %s -> set key %s", value, key(value)); - curInputState.put(key(value), value); + if (value != CiValue.IllegalValue && !isIgnoredRegister(value)) { + assert trace(" output %s -> set key %s", value, key(value)); + curInputState.put(key(value), value); + } return value; } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Thu Jan 26 12:23:00 2012 +0100 @@ -102,9 +102,9 @@ List instructions = block.lir(); assert instructions.size() >= 2 : "block must have label and branch"; - assert instructions.get(0).code == StandardOpcode.LABEL : "first instruction must always be a label"; - assert instructions.get(instructions.size() - 1).code == StandardOpcode.JUMP : "last instruction must always be a branch"; - assert ((LIRBranch) instructions.get(instructions.size() - 1)).destination().label() == block.suxAt(0).label() : "branch target must be the successor " + ((LIRBranch) instructions.get(instructions.size() - 1)).destination(); + assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label"; + assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "last instruction must always be a branch"; + assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == block.suxAt(0).label() : "branch target must be the successor"; // block must have exactly one successor @@ -147,22 +147,22 @@ List instructions = block.lir(); LIRInstruction lastOp = instructions.get(instructions.size() - 1); - if (lastOp instanceof LIRBranch) { - LIRBranch lastBranch = (LIRBranch) lastOp; + if (lastOp instanceof StandardOp.JumpOp) { + StandardOp.JumpOp lastJump = (StandardOp.JumpOp) lastOp; - if (lastBranch.info == null) { - if (lastBranch.destination().label() == code.get(i + 1).label()) { + if (lastOp.info == null) { + if (lastJump.destination().label() == code.get(i + 1).label()) { // delete last branch instruction Util.truncate(instructions, instructions.size() - 1); } else { LIRInstruction prevOp = instructions.get(instructions.size() - 2); - if (prevOp instanceof LIRBranch) { - LIRBranch prevBranch = (LIRBranch) prevOp; + if (prevOp instanceof StandardOp.BranchOp) { + StandardOp.BranchOp prevBranch = (StandardOp.BranchOp) prevOp; - if (prevBranch.destination().label() == code.get(i + 1).label && prevBranch.info == null) { + if (prevBranch.destination().label() == code.get(i + 1).label && prevOp.info == null) { // eliminate a conditional branch to the immediate successor - prevBranch.negate(lastBranch.destination()); + prevBranch.negate(lastJump.destination()); Util.truncate(instructions, instructions.size() - 1); } } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java Thu Jan 26 12:23:00 2012 +0100 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.lir.StandardOp.*; /** * This class optimizes moves, particularly those that result from eliminating SSA form. @@ -88,10 +89,10 @@ assert op1 != null; assert op2 != null; - if (op1 instanceof MoveInstruction && op2 instanceof MoveInstruction) { - MoveInstruction move1 = (MoveInstruction) op1; - MoveInstruction move2 = (MoveInstruction) op2; - if (move1.getSource() == move2.getSource() && move1.getDest() == move2.getDest()) { + if (op1 instanceof MoveOp && op2 instanceof MoveOp) { + MoveOp move1 = (MoveOp) op1; + MoveOp move2 = (MoveOp) op2; + if (move1.getInput() == move2.getInput() && move1.getResult() == move2.getResult()) { // these moves are exactly equal and can be optimized return true; } @@ -128,12 +129,12 @@ return; } - if (predInstructions.get(predInstructions.size() - 1).code == StandardOpcode.XIR) { + if (predInstructions.get(predInstructions.size() - 1) instanceof LIRXirInstruction) { return; } assert pred.suxAt(0) == block : "invalid control flow"; - assert predInstructions.get(predInstructions.size() - 1).code == StandardOpcode.JUMP : "block must end with unconditional jump"; + assert predInstructions.get(predInstructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump"; if (predInstructions.get(predInstructions.size() - 1).info != null) { // can not optimize instructions that have debug info @@ -185,12 +186,12 @@ assert numSux == 2 : "method should not be called otherwise"; - if (instructions.get(instructions.size() - 1).code == StandardOpcode.XIR) { + if (instructions.get(instructions.size() - 1) instanceof LIRXirInstruction) { // cannot optimize when last instruction is Xir. return; } - assert instructions.get(instructions.size() - 1).code == StandardOpcode.JUMP : "block must end with unconditional jump"; + assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump"; if (instructions.get(instructions.size() - 1).info != null) { // cannot optimize instructions when debug info is needed @@ -198,7 +199,7 @@ } LIRInstruction branch = instructions.get(instructions.size() - 2); - if (!(branch instanceof LIRBranch) || branch.info != null) { + if (!(branch instanceof StandardOp.BranchOp) || branch.info != null) { // not a valid case for optimization // currently, only blocks that end with two branches (conditional branch followed // by unconditional branch) are optimized @@ -214,7 +215,7 @@ LIRBlock sux = block.suxAt(i); List suxInstructions = sux.lir(); - assert suxInstructions.get(0).code == StandardOpcode.LABEL : "block must start with label"; + assert suxInstructions.get(0) instanceof StandardOp.LabelOp : "block must start with label"; if (sux.numberOfPreds() != 1) { // this can happen with switch-statements where multiple edges are between diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Thu Jan 26 12:23:00 2012 +0100 @@ -43,6 +43,7 @@ import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; +import com.oracle.max.graal.compiler.lir.StandardOp.*; /** * An implementation of the linear scan register allocator algorithm described @@ -376,7 +377,7 @@ case NoSpillStore: assert defPos <= interval.spillDefinitionPos() : "positions are processed in reverse order when intervals are created"; - if (defPos < interval.spillDefinitionPos() - 2 || instructionForId(interval.spillDefinitionPos()).code == StandardOpcode.XIR) { + if (defPos < interval.spillDefinitionPos() - 2 || instructionForId(interval.spillDefinitionPos()) instanceof LIRXirInstruction) { // second definition found, so no spill optimization possible for this interval interval.setSpillState(SpillState.NoOptimization); } else { @@ -471,17 +472,17 @@ int opId = op.id(); if (opId == -1) { - MoveInstruction move = (MoveInstruction) op; + MoveOp move = (MoveOp) op; // remove move from register to stack if the stack slot is guaranteed to be correct. // only moves that have been inserted by LinearScan can be removed. - assert isVariable(move.getDest()) : "LinearScan inserts only moves to variables"; + assert isVariable(move.getResult()) : "LinearScan inserts only moves to variables"; - Interval curInterval = intervalFor(move.getDest()); + Interval curInterval = intervalFor(move.getResult()); if (!isRegister(curInterval.location()) && curInterval.alwaysInMemory()) { // move target is a stack slot that is always correct, so eliminate instruction if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println("eliminating move from interval %d to %d", operandNumber(move.getSource()), operandNumber(move.getDest())); + TTY.println("eliminating move from interval %d to %d", operandNumber(move.getInput()), operandNumber(move.getResult())); } instructions.set(j, null); // null-instructions are deleted by assignRegNum } @@ -503,7 +504,7 @@ assert isRegister(fromLocation) : "from operand must be a register but is: " + fromLocation + " toLocation=" + toLocation + " spillState=" + interval.spillState(); assert isStackSlot(toLocation) : "to operand must be a stack slot"; - insertionBuffer.append(j + 1, StandardOpcode.SPILL_MOVE.create(toLocation, fromLocation)); + insertionBuffer.append(j + 1, ir.spillMoveFactory.createMove(toLocation, fromLocation)); if (GraalOptions.TraceLinearScanLevel >= 4) { CiStackSlot slot = interval.spillSlot(); @@ -988,9 +989,9 @@ * Determines the register priority for an instruction's output/result operand. */ static RegisterPriority registerPriorityOfOutputOperand(LIRInstruction op) { - if (op instanceof MoveInstruction) { - MoveInstruction move = (MoveInstruction) op; - if (isStackSlot(move.getSource()) && move.getSource().kind != CiKind.Object) { + if (op instanceof MoveOp) { + MoveOp move = (MoveOp) op; + if (isStackSlot(move.getInput()) && move.getInput().kind != CiKind.Object) { // method argument (condition must be equal to handleMethodArguments) return RegisterPriority.None; } @@ -1018,21 +1019,21 @@ * spill slot. */ void handleMethodArguments(LIRInstruction op) { - if (op instanceof MoveInstruction) { - MoveInstruction move = (MoveInstruction) op; - if (isStackSlot(move.getSource()) && move.getSource().kind != CiKind.Object) { - CiStackSlot slot = (CiStackSlot) move.getSource(); + if (op instanceof MoveOp) { + MoveOp move = (MoveOp) op; + if (isStackSlot(move.getInput()) && move.getInput().kind != CiKind.Object) { + CiStackSlot slot = (CiStackSlot) move.getInput(); if (GraalOptions.DetailedAsserts) { - assert move.id() > 0 : "invalid id"; - assert blockForId(move.id()).numberOfPreds() == 0 : "move from stack must be in first block"; - assert isVariable(move.getDest()) : "result of move must be a variable"; + assert op.id() > 0 : "invalid id"; + assert blockForId(op.id()).numberOfPreds() == 0 : "move from stack must be in first block"; + assert isVariable(move.getResult()) : "result of move must be a variable"; if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println("found move from stack slot %s to %s", slot, move.getDest()); + TTY.println("found move from stack slot %s to %s", slot, move.getResult()); } } - Interval interval = intervalFor(move.getDest()); + Interval interval = intervalFor(move.getResult()); interval.setSpillSlot(slot); interval.assignLocation(slot); } @@ -1420,9 +1421,8 @@ List instructions = fromBlock.lir(); LIRInstruction instr = instructions.get(instructions.size() - 1); - if (instr instanceof LIRBranch) { + if (instr instanceof StandardOp.JumpOp) { // insert moves before branch - assert instr.code == StandardOpcode.JUMP : "block does not end with an unconditional jump"; moveResolver.setInsertPosition(fromBlock.lir(), instructions.size() - 1); } else { moveResolver.setInsertPosition(fromBlock.lir(), instructions.size()); @@ -1434,7 +1434,7 @@ } if (GraalOptions.DetailedAsserts) { - assert fromBlock.lir().get(0).code == StandardOpcode.LABEL : "block does not start with a label"; + assert fromBlock.lir().get(0) instanceof StandardOp.LabelOp : "block does not start with a label"; // because the number of predecessor edges matches the number of // successor edges, blocks which are reached by switch statements @@ -1466,8 +1466,8 @@ // check if block has only one predecessor and only one successor if (block.numberOfPreds() == 1 && block.numberOfSux() == 1) { List instructions = block.lir(); - assert instructions.get(0).code == StandardOpcode.LABEL : "block must start with label"; - assert instructions.get(instructions.size() - 1).code == StandardOpcode.JUMP : "block with successor must end with unconditional jump"; + assert instructions.get(0) instanceof StandardOp.LabelOp : "block must start with label"; + assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "block with successor must end with unconditional jump"; // check if block is empty (only label and branch) if (instructions.size() == 2) { @@ -1591,10 +1591,8 @@ // before the branch instruction. So the split child information for this branch would // be incorrect. LIRInstruction instr = block.lir().get(block.lir().size() - 1); - if (instr instanceof LIRBranch) { - LIRBranch branch = (LIRBranch) instr; + if (instr instanceof StandardOp.JumpOp) { if (block.liveOut.get(operandNumber(operand))) { - assert branch.code == StandardOpcode.JUMP : "block does not end with an unconditional jump"; assert false : "can't get split child for the last branch of a block because the information would be incorrect (moves are inserted before the branch in resolveDataFlow)"; } } @@ -1702,7 +1700,7 @@ // considered in the live ranges of intervals) // Solution: use the first opId of the branch target block instead. final LIRInstruction instr = block.lir().get(block.lir().size() - 1); - if (instr instanceof LIRBranch) { + if (instr instanceof StandardOp.JumpOp) { if (block.liveOut.get(operandNumber(operand))) { tempOpId = block.suxAt(0).firstLirInstructionId(); mode = OperandMode.Output; @@ -1754,9 +1752,9 @@ } // remove useless moves - if (op instanceof MoveInstruction) { - MoveInstruction move = (MoveInstruction) op; - if (move.getSource() == move.getDest()) { + if (op instanceof MoveOp) { + MoveOp move = (MoveOp) op; + if (move.getInput() == move.getResult()) { instructions.set(j, null); hasDead = true; } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java Thu Jan 26 12:23:00 2012 +0100 @@ -37,6 +37,7 @@ import com.oracle.max.graal.compiler.alloc.Interval.State; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.compiler.lir.StandardOp.*; /** */ @@ -824,9 +825,9 @@ } static boolean isMove(LIRInstruction op, Interval from, Interval to) { - if (op instanceof MoveInstruction) { - MoveInstruction move = (MoveInstruction) op; - return isVariable(move.getSource()) && isVariable(move.getDest()) && move.getSource() == from.operand && move.getDest() == to.operand; + if (op instanceof MoveOp) { + MoveOp move = (MoveOp) op; + return isVariable(move.getInput()) && isVariable(move.getResult()) && move.getInput() == from.operand && move.getResult() == to.operand; } return false; } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java Thu Jan 26 12:23:00 2012 +0100 @@ -198,7 +198,7 @@ CiValue fromOpr = fromInterval.operand; CiValue toOpr = toInterval.operand; - insertionBuffer.append(insertIdx, StandardOpcode.SPILL_MOVE.create(toOpr, fromOpr)); + insertionBuffer.append(insertIdx, allocator.ir.spillMoveFactory.createMove(toOpr, fromOpr)); if (GraalOptions.TraceLinearScanLevel >= 4) { TTY.println("MoveResolver: inserted move from %d (%s) to %d (%s)", fromInterval.operandNumber, fromInterval.location(), toInterval.operandNumber, toInterval.location()); @@ -210,7 +210,7 @@ assert insertIdx != -1 : "must setup insert position first"; CiValue toOpr = toInterval.operand; - insertionBuffer.append(insertIdx, StandardOpcode.SPILL_MOVE.create(toOpr, fromOpr)); + insertionBuffer.append(insertIdx, allocator.ir.spillMoveFactory.createMove(toOpr, fromOpr)); if (GraalOptions.TraceLinearScanLevel >= 4) { TTY.print("MoveResolver: inserted move from constant %s to %d (%s)", fromOpr, toInterval.operandNumber, toInterval.location()); diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/TargetMethodAssembler.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/TargetMethodAssembler.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/asm/TargetMethodAssembler.java Thu Jan 26 12:23:00 2012 +0100 @@ -242,6 +242,31 @@ return recordDataReferenceInCode((CiConstant) value, 8); } + public CiAddress asIntAddr(CiValue value) { + assert value.kind == CiKind.Int; + return asAddress(value); + } + + public CiAddress asLongAddr(CiValue value) { + assert value.kind == CiKind.Long; + return asAddress(value); + } + + public CiAddress asObjectAddr(CiValue value) { + assert value.kind == CiKind.Object; + return asAddress(value); + } + + public CiAddress asFloatAddr(CiValue value) { + assert value.kind == CiKind.Float; + return asAddress(value); + } + + public CiAddress asDoubleAddr(CiValue value) { + assert value.kind == CiKind.Double; + return asAddress(value); + } + public CiAddress asAddress(CiValue value) { if (isStackSlot(value)) { CiStackSlot slot = (CiStackSlot) value; diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Thu Jan 26 12:23:00 2012 +0100 @@ -27,26 +27,27 @@ import static com.oracle.max.cri.ci.CiValueUtil.*; import static com.oracle.max.cri.util.MemoryBarriers.*; import static com.oracle.max.graal.alloc.util.ValueUtil.*; -import static com.oracle.max.graal.compiler.lir.StandardOpcode.*; import java.lang.reflect.*; import java.util.*; import com.oracle.max.asm.*; import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiTargetMethod.Mark; import com.oracle.max.cri.ri.*; import com.oracle.max.cri.ri.RiType.Representation; import com.oracle.max.cri.xir.CiXirAssembler.XirConstant; import com.oracle.max.cri.xir.CiXirAssembler.XirInstruction; +import com.oracle.max.cri.xir.CiXirAssembler.XirMark; import com.oracle.max.cri.xir.CiXirAssembler.XirOperand; import com.oracle.max.cri.xir.CiXirAssembler.XirParameter; import com.oracle.max.cri.xir.CiXirAssembler.XirRegister; import com.oracle.max.cri.xir.CiXirAssembler.XirTemp; import com.oracle.max.cri.xir.*; import com.oracle.max.criutils.*; -import com.oracle.max.graal.alloc.util.*; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.lir.StandardOp.ParametersOp; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; @@ -444,11 +445,11 @@ for (int i = 0; i < params.length; i++) { params[i] = toStackKind(incomingArguments.locations[i]); } - append(PARAMS.create(params)); + append(new ParametersOp(params)); XirSnippet prologue = xir.genPrologue(null, method); if (prologue != null) { - emitXir(prologue, null, null, null, false); + emitXir(prologue, null, null, false); } for (LocalNode local : graph.getNodes(LocalNode.class)) { @@ -481,14 +482,14 @@ public void visitArrayLength(ArrayLengthNode x) { XirArgument array = toXirArgument(x.array()); XirSnippet snippet = xir.genArrayLength(site(x), array); - emitXir(snippet, x, state(), null, true); + emitXir(snippet, x, state(), true); operand(x); } @Override public void visitCheckCast(CheckCastNode x) { XirSnippet snippet = xir.genCheckCast(site(x), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass()); - emitXir(snippet, x, state(), null, true); + emitXir(snippet, x, state(), true); // The result of a checkcast is the unmodified object, so no need to allocate a new variable for it. setResult(x, operand(x.object())); } @@ -513,7 +514,7 @@ LIRDebugInfo stateAfter = stateFor(x.stateAfter()); XirSnippet snippet = xir.genMonitorEnter(site(x), obj, lockAddress); - emitXir(snippet, x, stateBefore, stateAfter, null, true); + emitXir(snippet, x, stateBefore, stateAfter, true, null, null); } @Override @@ -534,7 +535,7 @@ curLocks = curLocks.outer; XirSnippet snippet = xir.genMonitorExit(site(x), obj, lockAddress); - emitXir(snippet, x, stateBefore, null, true); + emitXir(snippet, x, stateBefore, true); } @Override @@ -546,7 +547,7 @@ } XirArgument receiver = toXirArgument(x.object()); XirSnippet snippet = x.isStatic() ? xir.genGetStatic(site(x), receiver, field) : xir.genGetField(site(x), receiver, field); - emitXir(snippet, x, info, null, true); + emitXir(snippet, x, info, true); if (x.isVolatile()) { emitMembar(JMM_POST_VOLATILE_READ); } @@ -562,7 +563,7 @@ XirArgument receiver = toXirArgument(x.object()); XirArgument value = toXirArgument(x.value()); XirSnippet snippet = x.isStatic() ? xir.genPutStatic(site(x), receiver, field, value) : xir.genPutField(site(x), receiver, field, value); - emitXir(snippet, x, info, null, true); + emitXir(snippet, x, info, true); if (x.isVolatile()) { emitMembar(JMM_POST_VOLATILE_WRITE); } @@ -573,7 +574,7 @@ XirArgument array = toXirArgument(x.array()); XirArgument index = toXirArgument(x.index()); XirSnippet snippet = xir.genArrayLoad(site(x), array, index, x.elementKind(), null); - emitXir(snippet, x, state(), null, true); + emitXir(snippet, x, state(), true); } @Override @@ -582,27 +583,27 @@ XirArgument index = toXirArgument(x.index()); XirArgument value = toXirArgument(x.value()); XirSnippet snippet = xir.genArrayStore(site(x), array, index, value, x.elementKind(), null); - emitXir(snippet, x, state(), null, true); + emitXir(snippet, x, state(), true); } @Override public void visitNewInstance(NewInstanceNode x) { XirSnippet snippet = xir.genNewInstance(site(x), x.instanceClass()); - emitXir(snippet, x, state(), null, true); + emitXir(snippet, x, state(), true); } @Override public void visitNewTypeArray(NewTypeArrayNode x) { XirArgument length = toXirArgument(x.length()); XirSnippet snippet = xir.genNewArray(site(x), length, x.elementType().kind(true), null, null); - emitXir(snippet, x, state(), null, true); + emitXir(snippet, x, state(), true); } @Override public void visitNewObjectArray(NewObjectArrayNode x) { XirArgument length = toXirArgument(x.length()); XirSnippet snippet = xir.genNewArray(site(x), length, CiKind.Object, x.elementType(), x.exactType()); - emitXir(snippet, x, state(), null, true); + emitXir(snippet, x, state(), true); } @Override @@ -612,14 +613,14 @@ dims[i] = toXirArgument(x.dimension(i)); } XirSnippet snippet = xir.genNewMultiArray(site(x), dims, x.type()); - emitXir(snippet, x, state(), null, true); + emitXir(snippet, x, state(), true); } @Override public void visitExceptionObject(ExceptionObjectNode x) { XirSnippet snippet = xir.genExceptionObject(site(x)); LIRDebugInfo info = state(); - emitXir(snippet, x, info, null, true); + emitXir(snippet, x, info, true); } @Override @@ -631,16 +632,18 @@ } XirSnippet epilogue = xir.genEpilogue(site(x), method); if (epilogue != null) { - emitXir(epilogue, x, null, method, false); - append(StandardOpcode.RETURN.create(operand)); + emitXir(epilogue, x, null, false); + emitReturn(operand); } } + protected abstract void emitReturn(CiValue input); + @SuppressWarnings("unused") protected void postGCWriteBarrier(CiValue addr, CiValue newVal) { XirSnippet writeBarrier = xir.genWriteBarrier(toXirArgument(addr)); if (writeBarrier != null) { - emitXir(writeBarrier, null, null, null, false); + emitXir(writeBarrier, null, null, false); } } @@ -677,7 +680,7 @@ public void emitSafepointPoll(FixedNode x) { if (!lastState.method().noSafepointPolls()) { XirSnippet snippet = xir.genSafepointPoll(site(x)); - emitXir(snippet, x, state(), null, false); + emitXir(snippet, x, state(), false); } } @@ -703,20 +706,14 @@ } } - private void emitNullCheckGuard(NullCheckNode node) { - assert !node.expectedNull; - NullCheckNode x = node; - Variable value = load(operand(x.object())); - LIRDebugInfo info = state(); - append(StandardOpcode.NULL_CHECK.create(value, info)); - } + protected abstract void emitNullCheckGuard(NullCheckNode node); private void emitTypeGuard(IsTypeNode node) { load(operand(node.object())); LIRDebugInfo info = state(); XirArgument clazz = toXirArgument(node.type().getEncoding(Representation.ObjectHub)); XirSnippet typeCheck = xir.genTypeCheck(site(node), toXirArgument(node.object()), clazz, node.type()); - emitXir(typeCheck, node, info, method, false); + emitXir(typeCheck, node, info, false); } @@ -752,10 +749,7 @@ private void emitInstanceOfBranch(InstanceOfNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) { XirArgument obj = toXirArgument(x.object()); XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass()); - emitXir(snippet, x, info, null, false); - LIRXirInstruction instr = (LIRXirInstruction) currentBlock.lir().get(currentBlock.lir().size() - 1); - instr.setTrueSuccessor(x.negated ? falseSuccessor : trueSuccessor); - instr.setFalseSuccessor(x.negated ? trueSuccessor : falseSuccessor); + emitXir(snippet, x, info, null, false, x.negated ? falseSuccessor : trueSuccessor, x.negated ? trueSuccessor : falseSuccessor); } @@ -800,7 +794,7 @@ XirArgument trueArg = toXirArgument(x.negated ? falseValue : trueValue); XirArgument falseArg = toXirArgument(x.negated ? trueValue : falseValue); XirSnippet snippet = xir.genMaterializeInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), trueArg, falseArg, x.targetClass()); - return (Variable) emitXir(snippet, null, null, null, false); + return (Variable) emitXir(snippet, null, null, false); } private Variable emitConstantConditional(boolean value, CiValue trueValue, CiValue falseValue) { @@ -882,7 +876,7 @@ // TODO This is the version currently necessary for Maxine: since the invokeinterface-snippet uses a division, it // destroys rdx, which is also used to pass a parameter. Therefore, the snippet must be before the parameters are assigned to their locations. LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci())); - destinationAddress = emitXir(snippet, x.node(), addrInfo, null, callTarget.targetMethod(), false); + destinationAddress = emitXir(snippet, x.node(), addrInfo, false); } CiValue resultOperand = resultOperandFor(x.node().kind()); @@ -896,26 +890,20 @@ if (target().invokeSnippetAfterArguments) { // TODO This is the version currently active for HotSpot. LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), pointerSlots, null); - destinationAddress = emitXir(snippet, x.node(), addrInfo, null, callTarget.targetMethod(), false); + destinationAddress = emitXir(snippet, x.node(), addrInfo, false); } LIRDebugInfo callInfo = stateFor(x.stateDuring(), pointerSlots, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null); - - // emit direct or indirect call to the destination address - if (destinationAddress instanceof CiConstant) { - // Direct call - assert ((CiConstant) destinationAddress).isDefaultValue() : "destination address should be zero"; - append(StandardOpcode.DIRECT_CALL.create(targetMethod, resultOperand, argList, null, callInfo, snippet.marks)); - } else { - // Indirect call - append(StandardOpcode.INDIRECT_CALL.create(targetMethod, resultOperand, argList, destinationAddress, callInfo, snippet.marks)); - } + emitCall(targetMethod, resultOperand, argList, destinationAddress, callInfo, snippet.marks); if (isLegal(resultOperand)) { setResult(x.node(), emitMove(resultOperand)); } } + protected abstract void emitCall(Object targetMethod, CiValue result, List arguments, CiValue targetAddress, LIRDebugInfo info, Map marks); + + private static CiValue toStackKind(CiValue value) { if (value.kind.stackKind() != value.kind) { // We only have stack-kinds in the LIR, so convert the operand kind for values from the calling convention. @@ -983,7 +971,7 @@ argumentList = Collections.emptyList(); } - append(StandardOpcode.DIRECT_CALL.create(runtimeCall, physReg, argumentList, null, info, null)); + emitCall(runtimeCall, physReg, argumentList, CiConstant.forLong(0), info, null); if (isLegal(physReg)) { return emitMove(physReg); @@ -1012,7 +1000,7 @@ info = stateFor(stateBeforeReturn); } - append(StandardOpcode.DIRECT_CALL.create(x.call(), resultOperand, argList, null, info, null)); + emitCall(x.call(), resultOperand, argList, CiConstant.forLong(0), info, null); if (isLegal(resultOperand)) { setResult(x, emitMove(resultOperand)); @@ -1211,11 +1199,11 @@ return variable; } - protected CiValue emitXir(XirSnippet snippet, ValueNode x, LIRDebugInfo info, RiMethod currentMethod, boolean setInstructionResult) { - return emitXir(snippet, x, info, null, currentMethod, setInstructionResult); + protected CiValue emitXir(XirSnippet snippet, ValueNode x, LIRDebugInfo info, boolean setInstructionResult) { + return emitXir(snippet, x, info, null, setInstructionResult, null, null); } - protected CiValue emitXir(XirSnippet snippet, ValueNode instruction, LIRDebugInfo info, LIRDebugInfo infoAfter, RiMethod currentMethod, boolean setInstructionResult) { + protected CiValue emitXir(XirSnippet snippet, ValueNode instruction, LIRDebugInfo info, LIRDebugInfo infoAfter, boolean setInstructionResult, LabelRef trueSuccessor, LabelRef falseSuccessor) { if (GraalOptions.PrintXirTemplates) { TTY.println("Emit XIR template " + snippet.template.name); } @@ -1312,10 +1300,10 @@ XirInstruction[] slowPath = snippet.template.slowPath; if (!isConstant(operandsArray[resultOperand.index]) || snippet.template.fastPath.length != 0 || (slowPath != null && slowPath.length > 0)) { // XIR instruction is only needed when the operand is not a constant! - append(StandardOpcode.XIR.create(snippet, operandsArray, allocatedResultOperand, + emitXir(snippet, operandsArray, allocatedResultOperand, inputOperandArray, tempOperandArray, inputOperandIndicesArray, tempOperandIndicesArray, (allocatedResultOperand == IllegalValue) ? -1 : resultOperand.index, - info, infoAfter, currentMethod)); + info, infoAfter, trueSuccessor, falseSuccessor); if (GraalOptions.Meter) { context.metrics.LIRXIRInstructions++; } @@ -1324,6 +1312,9 @@ return operandsArray[resultOperand.index]; } + protected abstract void emitXir(XirSnippet snippet, CiValue[] operands, CiValue outputOperand, CiValue[] inputs, CiValue[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex, + LIRDebugInfo info, LIRDebugInfo infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor); + protected final CiValue callRuntime(CiRuntimeCall runtimeCall, LIRDebugInfo info, CiValue... args) { // get a result register CiKind result = runtimeCall.resultKind; @@ -1349,7 +1340,7 @@ argumentList = Util.uncheckedCast(Collections.emptyList()); } - append(StandardOpcode.DIRECT_CALL.create(runtimeCall, physReg, argumentList, null, info, null)); + emitCall(runtimeCall, physReg, argumentList, CiConstant.forLong(0), info, null); return physReg; } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIR.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIR.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIR.java Thu Jan 26 12:23:00 2012 +0100 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.max.cri.ci.*; import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.asm.*; @@ -67,6 +68,12 @@ private final int loopCount; + public SpillMoveFactory spillMoveFactory; + + public interface SpillMoveFactory { + LIRInstruction createMove(CiValue result, CiValue input); + LIRInstruction createExchange(CiValue input1, CiValue input2); + } public interface SlowPath { void emitCode(TargetMethodAssembler tasm); diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java Thu Jan 26 12:23:00 2012 +0100 @@ -205,9 +205,9 @@ LIRInstruction lirInstruction = lir.get(lir.size() - 1); if (lirInstruction instanceof LIRXirInstruction) { LIRXirInstruction lirXirInstruction = (LIRXirInstruction) lirInstruction; - return (lirXirInstruction.falseSuccessor() != null) && (lirXirInstruction.trueSuccessor() != null); + return (lirXirInstruction.falseSuccessor != null) && (lirXirInstruction.trueSuccessor != null); } - return lirInstruction instanceof LIRBranch; + return lirInstruction instanceof StandardOp.JumpOp; } public boolean isExceptionEntry() { diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBranch.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBranch.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.lir; - -import com.oracle.max.graal.nodes.calc.*; - -public abstract class LIRBranch extends LIRInstruction { - - /** - * The condition when this branch is taken, or {@code null} if it is an unconditional branch. - */ - protected Condition cond; - - /** - * For floating point branches only. True when the branch should be taken when the comparison is unordered. - */ - protected boolean unorderedIsTrue; - - /** - * The target of this branch. - */ - protected LabelRef destination; - - - public LIRBranch(LIROpcode code, Condition cond, boolean unorderedIsTrue, LabelRef destination, LIRDebugInfo info) { - super(code, LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - this.cond = cond; - this.unorderedIsTrue = unorderedIsTrue; - this.destination = destination; - } - - public LabelRef destination() { - return destination; - } - - public void negate(LabelRef newDestination) { - destination = newDestination; - cond = cond.negate(); - unorderedIsTrue = !unorderedIsTrue; - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRCall.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRCall.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.lir; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiTargetMethod.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.cri.xir.CiXirAssembler.*; -import com.oracle.max.graal.compiler.util.*; - -/** - * This class represents a call instruction; either to a {@linkplain CiRuntimeCall runtime method}, - * a {@linkplain RiMethod Java method}, a native function or a global stub. - */ -public abstract class LIRCall extends LIRInstruction { - - /** - * The target of the call. This will be a {@link CiRuntimeCall}, {@link RiMethod} or {@link CiValue} - * object denoting a call to the runtime, a Java method or a native function respectively. - */ - public final Object target; - /** - * The call site needs to be marked if this is non-null. - */ - public final Map marks; - - private final int targetAddressIndex; - - private static CiValue[] toArray(List arguments, CiValue targetAddress) { - CiValue[] result = new CiValue[arguments.size() + (targetAddress != null ? 1 : 0)]; - arguments.toArray(result); - if (targetAddress != null) { - result[arguments.size()] = targetAddress; - } - return result; - } - - public LIRCall(LIROpcode opcode, - Object target, - CiValue result, - List arguments, - CiValue targetAddress, - LIRDebugInfo info, - Map marks) { - super(opcode, isLegal(result) ? new CiValue[] {result} : LIRInstruction.NO_OPERANDS, info, toArray(arguments, targetAddress), LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - this.marks = marks; - if (targetAddress == null) { - this.targetAddressIndex = -1; - } else { - // The last argument is the operand holding the address for the indirect call - assert inputs.length - 1 == arguments.size(); - this.targetAddressIndex = arguments.size(); - } - this.target = target; - } - - public CiValue targetAddress() { - if (targetAddressIndex >= 0) { - return input(targetAddressIndex); - } - return null; - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - } else if (mode == OperandMode.Output) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); - } - throw Util.shouldNotReachHere(); - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java Thu Jan 26 12:23:00 2012 +0100 @@ -157,7 +157,7 @@ /** * The opcode of this instruction. */ - public final LIROpcode code; + protected final Object code; /** * The output operands for this instruction (modified by the register allocator). @@ -198,7 +198,7 @@ * @param inputs the input operands for the instruction. * @param temps the temp operands for the instruction. */ - public LIRInstruction(LIROpcode opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { + public LIRInstruction(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { this.code = opcode; this.outputs = outputs; this.inputs = inputs; @@ -319,8 +319,8 @@ /** * Returns true when this instruction is a call instruction that destroys all caller-saved registers. */ - public boolean hasCall() { - return false; + public final boolean hasCall() { + return this instanceof StandardOp.CallOp; } /** @@ -362,8 +362,9 @@ * @return The flags for the operand. */ // TODO this method will go away when we have named operands, the flags will be specified as annotations instead. - protected EnumSet flagsFor(OperandMode mode, int index) { - return EnumSet.of(OperandFlag.Register); + protected abstract EnumSet flagsFor(OperandMode mode, int index); + + protected void verify() { } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.lir; - -public interface LIROpcode { -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRVerifier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRVerifier.java Thu Jan 26 12:23:00 2012 +0100 @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.lir; + +import static com.oracle.max.cri.ci.CiValueUtil.*; +import static com.oracle.max.graal.alloc.util.ValueUtil.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.criutils.*; +import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; +import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; +import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; +import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; +import com.oracle.max.graal.compiler.schedule.*; +import com.oracle.max.graal.compiler.util.*; + +public final class LIRVerifier { + private final LIR lir; + private final FrameMap frameMap; + + private final boolean beforeRegisterAllocation; + + private final BitSet[] blockLiveOut; + private final Object[] variableDefinitions; + + private BitSet liveOutFor(Block block) { + return blockLiveOut[block.blockID()]; + } + private void setLiveOutFor(Block block, BitSet liveOut) { + blockLiveOut[block.blockID()] = liveOut; + } + + private int maxRegisterNum() { + return frameMap.target.arch.registers.length; + } + + private boolean isAllocatableRegister(CiValue value) { + return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; + } + + public static boolean verify(final LIRInstruction op) { + ValueProcedure allowedProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { return allowed(op, value, mode, flags); } }; + + op.forEachInput(allowedProc); + op.forEachAlive(allowedProc); + op.forEachState(allowedProc); + op.forEachTemp(allowedProc); + op.forEachOutput(allowedProc); + + op.verify(); + return true; + } + + public static boolean verify(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap) { + LIRVerifier verifier = new LIRVerifier(beforeRegisterAllocation, lir, frameMap); + verifier.verify(); + return true; + } + + + private LIRVerifier(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap) { + this.beforeRegisterAllocation = beforeRegisterAllocation; + this.lir = lir; + this.frameMap = frameMap; + this.blockLiveOut = new BitSet[lir.linearScanOrder().size()]; + this.variableDefinitions = new Object[lir.numVariables()]; + } + + private BitSet curVariablesLive; + private CiValue[] curRegistersLive; + + private LIRBlock curBlock; + private Object curInstruction; + private BitSet curRegistersDefined; + + private void verify() { + PhiValueProcedure useProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { return use(value, mode, flags); } }; + ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { return def(value, mode, flags); } }; + + curRegistersDefined = new BitSet(); + for (LIRBlock block : lir.linearScanOrder()) { + curBlock = block; + curVariablesLive = new BitSet(); + curRegistersLive = new CiValue[maxRegisterNum()]; + + if (block.dominator() != null) { + curVariablesLive.or(liveOutFor(block.dominator())); + } + + if (block.phis != null) { + assert beforeRegisterAllocation; + curInstruction = block.phis; + block.phis.forEachOutput(defProc); + } + + assert block.lir().get(0) instanceof StandardOp.LabelOp : "block must start with label"; + if (block.numberOfSux() > 0) { + LIRInstruction last = block.lir().get(block.lir().size() - 1); + assert last instanceof StandardOp.JumpOp || last instanceof LIRXirInstruction : "block with successor must end with unconditional jump"; + } + + for (LIRInstruction op : block.lir()) { + curInstruction = op; + + op.forEachInput(useProc); + if (op.hasCall()) { + for (CiRegister register : frameMap.registerConfig.getCallerSaveRegisters()) { + curRegistersLive[register.number] = null; + } + } + curRegistersDefined.clear(); + op.forEachAlive(useProc); + op.forEachState(useProc); + op.forEachTemp(defProc); + op.forEachOutput(defProc); + + curInstruction = null; + } + + for (LIRBlock sux : block.getLIRSuccessors()) { + if (sux.phis != null) { + assert beforeRegisterAllocation; + curInstruction = sux.phis; + sux.phis.forEachInput(block, useProc); + } + } + + setLiveOutFor(block, curVariablesLive); + } + } + + private CiValue use(CiValue value, OperandMode mode, EnumSet flags) { + allowed(curInstruction, value, mode, flags); + + if (isVariable(value)) { + assert beforeRegisterAllocation; + + int variableIdx = asVariable(value).index; + if (!curVariablesLive.get(variableIdx)) { + TTY.println("block %s instruction %s", curBlock, curInstruction); + TTY.println("live variables: %s", curVariablesLive); + if (variableDefinitions[variableIdx] != null) { + TTY.println("definition of %s: %s", value, variableDefinitions[variableIdx]); + } + TTY.println("ERROR: Use of variable %s that is not defined in dominator", value); + throw Util.shouldNotReachHere(); + } + + } else if (isAllocatableRegister(value)) { + int regNum = asRegister(value).number; + if (mode == OperandMode.Alive) { + curRegistersDefined.set(regNum); + } + + if (beforeRegisterAllocation && curRegistersLive[regNum] != value) { + TTY.println("block %s instruction %s", curBlock, curInstruction); + TTY.println("live registers: %s", Arrays.toString(curRegistersLive)); + TTY.println("ERROR: Use of fixed register %s that is not defined in this block", value); + throw Util.shouldNotReachHere(); + } + } + return value; + } + + private CiValue def(CiValue value, OperandMode mode, EnumSet flags) { + allowed(curInstruction, value, mode, flags); + + if (isVariable(value)) { + assert beforeRegisterAllocation; + + int variableIdx = asVariable(value).index; + if (variableDefinitions[variableIdx] != null) { + TTY.println("block %s instruction %s", curBlock, curInstruction); + TTY.println("live variables: %s", curVariablesLive); + TTY.println("definition of %s: %s", value, variableDefinitions[variableIdx]); + TTY.println("ERROR: Variable %s defined multiple times", value); + throw Util.shouldNotReachHere(); + } + assert curInstruction != null; + variableDefinitions[variableIdx] = curInstruction; + assert !curVariablesLive.get(variableIdx); + if (mode == OperandMode.Output) { + curVariablesLive.set(variableIdx); + } + + } else if (isAllocatableRegister(value)) { + int regNum = asRegister(value).number; + if (curRegistersDefined.get(regNum)) { + TTY.println("block %s instruction %s", curBlock, curInstruction); + TTY.println("ERROR: Same register defined twice in the same instruction: %s", value); + throw Util.shouldNotReachHere(); + } + curRegistersDefined.set(regNum); + + if (beforeRegisterAllocation) { + if (mode == OperandMode.Output) { + curRegistersLive[regNum] = value; + } else { + curRegistersLive[regNum] = null; + } + } + } + return value; + } + + private static CiValue allowed(Object op, CiValue value, OperandMode mode, EnumSet flags) { + if ((isVariable(value) && flags.contains(OperandFlag.Register)) || + (isRegister(value) && flags.contains(OperandFlag.Register)) || + (isStackSlot(value) && flags.contains(OperandFlag.Stack)) || + (isConstant(value) && flags.contains(OperandFlag.Constant) && mode != OperandMode.Output) || + (isIllegal(value) && flags.contains(OperandFlag.Illegal))) { + return value; + } + TTY.println("instruction %s", op); + TTY.println("mode: %s flags: %s", mode, flags); + TTY.println("Unexpected value: %s %s", value.getClass().getSimpleName(), value); + throw Util.shouldNotReachHere(); + } +} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRXirInstruction.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRXirInstruction.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRXirInstruction.java Thu Jan 26 12:23:00 2012 +0100 @@ -27,8 +27,8 @@ import java.util.*; import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; import com.oracle.max.cri.xir.*; +import com.oracle.max.graal.compiler.util.*; public abstract class LIRXirInstruction extends LIRInstruction { @@ -37,12 +37,11 @@ public final int[] inputOperandIndices; public final int[] tempOperandIndices; public final XirSnippet snippet; - public final RiMethod method; public final LIRDebugInfo infoAfter; - private LabelRef trueSuccessor; - private LabelRef falseSuccessor; + public final LabelRef trueSuccessor; + public final LabelRef falseSuccessor; - public LIRXirInstruction(LIROpcode opcode, + public LIRXirInstruction(Object opcode, XirSnippet snippet, CiValue[] originalOperands, CiValue outputOperand, @@ -51,17 +50,19 @@ int outputOperandIndex, LIRDebugInfo info, LIRDebugInfo infoAfter, - RiMethod method) { + LabelRef trueSuccessor, + LabelRef falseSuccessor) { // Note that we register the XIR input operands as Alive, because the XIR specification allows that input operands // are used at any time, even when the temp operands and the actual output operands have already be assigned. super(opcode, isLegal(outputOperand) ? new CiValue[] {outputOperand} : LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, inputs, temps); this.infoAfter = infoAfter; - this.method = method; this.snippet = snippet; this.inputOperandIndices = inputOperandIndices; this.tempOperandIndices = tempOperandIndices; this.outputOperandIndex = outputOperandIndex; this.originalOperands = originalOperands; + this.falseSuccessor = falseSuccessor; + this.trueSuccessor = trueSuccessor; assert isLegal(outputOperand) || outputOperandIndex == -1; } @@ -69,25 +70,10 @@ protected EnumSet flagsFor(OperandMode mode, int index) { if (mode == OperandMode.Alive || mode == OperandMode.Temp) { return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Illegal); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register); } - return super.flagsFor(mode, index); - } - - public void setFalseSuccessor(LabelRef falseSuccessor) { - this.falseSuccessor = falseSuccessor; - } - - - public void setTrueSuccessor(LabelRef trueSuccessor) { - this.trueSuccessor = trueSuccessor; - } - - public LabelRef falseSuccessor() { - return falseSuccessor; - } - - public LabelRef trueSuccessor() { - return trueSuccessor; + throw Util.shouldNotReachHere(); } public CiValue[] getOperands() { diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/MoveInstruction.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/MoveInstruction.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.lir; - -import com.oracle.max.cri.ci.*; - -public abstract class MoveInstruction extends LIRInstruction { - public MoveInstruction(LIROpcode opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { - super(opcode, outputs, info, inputs, alives, temps); - } - - public abstract CiValue getSource(); - public abstract CiValue getDest(); -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOp.java Thu Jan 26 12:23:00 2012 +0100 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.lir; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.compiler.asm.*; +import com.oracle.max.graal.compiler.util.*; + +/** + * A collection of machine-independent LIR operations, as well as interfaces to be implemented for specific kinds or LIR + * operations. + */ +public class StandardOp { + + /** + * Marker interface for a LIR operation that defines the position of a label. + * The first operation of every block must implement this interface. + */ + public interface LabelOp { + } + + /** + * Marker interface for a LIR operation that is an unconditional jump to {@link #destination()}. + * When the LIR is constructed, the last operation of every block must implement this interface. After + * register allocation, unnecessary jumps can be deleted. + * + * TODO Currently, a block can also end with an XIR operation. + */ + public interface JumpOp { + LabelRef destination(); + } + + /** + * Marker interface for a LIR operation that is a conditional jump to {@link #destination()}. + * Conditional jumps may be negated or optimized away after register allocation. + */ + public interface BranchOp { + LabelRef destination(); + void negate(LabelRef newDestination); + } + + /** + * Marker interface for a LIR operation that moves a value from {@link #getInput()} to {@link #getResult()}. + */ + public interface MoveOp { + CiValue getInput(); + CiValue getResult(); + } + + /** + * Marker interface for a LIR operation that calls a method, i.e., destroys all caller-saved registers. + */ + public interface CallOp { + } + + + /** + * Meta-operation that defines the incoming method parameters. In the LIR, every register and variable must be + * defined before it is used. This operation is the definition point of method parameters, but is otherwise a no-op. + * In particular, it is not the actual method prologue. + */ + public static final class ParametersOp extends LIRInstruction { + public ParametersOp(CiValue[] params) { + super("PARAMS", params, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm) { + // No code to emit. + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Output) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + } + throw Util.shouldNotReachHere(); + } + } +} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.lir; - -import java.util.*; - -import com.oracle.max.cri.ci.CiTargetMethod.Mark; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.cri.xir.CiXirAssembler.XirMark; -import com.oracle.max.cri.xir.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.util.*; - -public class StandardOpcode { - // Checkstyle: stop - public static MoveOpcode SPILL_MOVE; - public static NullCheckOpcode NULL_CHECK; - public static CallOpcode DIRECT_CALL; - public static CallOpcode INDIRECT_CALL; - public static LIROpcode LABEL; - public static LIROpcode JUMP; - public static ReturnOpcode RETURN; - public static XirOpcode XIR; - public static ParametersOpcode PARAMS = ParametersOpcode.PARAMS; - // Checkstyle: resume - - public interface MoveOpcode extends LIROpcode { - MoveInstruction create(CiValue result, CiValue input); - } - - public interface NullCheckOpcode extends LIROpcode { - LIRInstruction create(Variable input, LIRDebugInfo info); - } - - public interface CallOpcode extends LIROpcode { - LIRInstruction create(Object target, CiValue result, List arguments, CiValue targetAddress, LIRDebugInfo info, Map marks); - } - - public interface ReturnOpcode extends LIROpcode { - LIRInstruction create(CiValue input); - } - - public interface XirOpcode extends LIROpcode { - LIRInstruction create(XirSnippet snippet, CiValue[] operands, CiValue outputOperand, CiValue[] inputs, CiValue[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex, - LIRDebugInfo info, LIRDebugInfo infoAfter, RiMethod method); - } - - - public enum ParametersOpcode implements LIROpcode { - @SuppressWarnings("hiding") - PARAMS; - - public LIRInstruction create(CiValue[] params) { - return new LIRInstruction(this, params, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm) { - // No code to emit. This is not the actual method prologue, but only a meta-instruction that defines the incoming method parameters. - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Output) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - } - throw Util.shouldNotReachHere(); - } - }; - } - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/package-info.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/package-info.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * - * Port of the backend (LIR) of the client compiler to Java. - */ -package com.oracle.max.graal.compiler.lir; diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Arithmetic.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Arithmetic.java Thu Jan 26 12:23:00 2012 +0100 @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.target.amd64; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.compiler.asm.*; +import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.util.*; + +public enum AMD64Arithmetic { + IADD, ISUB, IMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, + LADD, LSUB, LMUL, LDIV, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR, + FADD, FSUB, FMUL, FDIV, FAND, FOR, FXOR, + DADD, DSUB, DMUL, DDIV, DAND, DOR, DXOR, + INEG, LNEG, + I2L, L2I, I2B, I2C, I2S, + F2D, D2F, + I2F, I2D, F2I, D2I, + L2F, L2D, F2L, D2L, + MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L; + + + public static class Op1Reg extends AMD64LIRInstruction { + public Op1Reg(AMD64Arithmetic opcode, CiValue result, CiValue x) { + super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue result = output(0); + CiValue x = input(0); + + emit(tasm, masm, (AMD64Arithmetic) code, result, x, null); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register); + } + throw Util.shouldNotReachHere(); + } + } + + public static class Op1Stack extends AMD64LIRInstruction { + public Op1Stack(AMD64Arithmetic opcode, CiValue result, CiValue x) { + super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue result = output(0); + CiValue x = input(0); + + AMD64Move.move(tasm, masm, result, x); + emit(tasm, masm, (AMD64Arithmetic) code, result); + } + + @Override + public EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + throw Util.shouldNotReachHere(); + } + } + + public static class Op2Stack extends AMD64LIRInstruction { + public Op2Stack(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { + super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = alive(0); + + AMD64Move.move(tasm, masm, result, x); + emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Alive && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + throw Util.shouldNotReachHere(); + } + + @Override + public void verify() { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = alive(0); + + super.verify(); + assert differentRegisters(result, y) || sameRegister(x, y); + verifyKind((AMD64Arithmetic) code, result, x, y); + } + } + + public static class Op2RegCommutative extends AMD64LIRInstruction { + public Op2RegCommutative(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { + super(opcode, new CiValue[] {result}, null, new CiValue[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = input(1); + + if (sameRegister(result, y)) { + emit(tasm, masm, (AMD64Arithmetic) code, result, x, null); + } else { + AMD64Move.move(tasm, masm, result, x); + emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); + } + } + + @Override + public EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Input && index == 1) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + throw Util.shouldNotReachHere(); + } + + @Override + protected void verify() { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = input(1); + + super.verify(); + assert differentRegisters(result, y) || sameRegister(x, y); + verifyKind((AMD64Arithmetic) code, result, x, y); + } + } + + public static class ShiftOp extends AMD64LIRInstruction { + public ShiftOp(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { + super(opcode, new CiValue[] {result}, null, new CiValue[] {x}, new CiValue[] {y}, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = alive(0); + + AMD64Move.move(tasm, masm, result, x); + emit(tasm, masm, (AMD64Arithmetic) code, result, y, null); + } + + @Override + public EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Alive && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + throw Util.shouldNotReachHere(); + } + + @Override + public void verify() { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = alive(0); + + super.verify(); + assert isConstant(y) || asRegister(y) == AMD64.rcx; + assert differentRegisters(result, y) || sameRegister(x, y); + verifyKind((AMD64Arithmetic) code, result, x, x); + assert y.kind.stackKind() == CiKind.Int; + } + } + + public static class DivOp extends AMD64LIRInstruction { + public DivOp(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y, LIRDebugInfo info) { + super(opcode, new CiValue[] {result}, info, new CiValue[] {x}, new CiValue[] {y}, new CiValue[] {asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.kind) : AMD64.rax.asValue(result.kind)}); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue result = output(0); + CiValue y = alive(0); + + emit(tasm, masm, (AMD64Arithmetic) code, result, y, info); + } + + @Override + public EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Alive && index == 0) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Temp && index == 0) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register); + } + throw Util.shouldNotReachHere(); + } + + @Override + protected void verify() { + CiValue result = output(0); + CiValue x = input(0); + CiValue y = alive(0); + + super.verify(); + // left input in rax, right input in any register but rax and rdx, result quotient in rax, result remainder in rdx + assert asRegister(x) == AMD64.rax; + assert differentRegisters(y, AMD64.rax.asValue(), AMD64.rdx.asValue()); + assert (name().endsWith("DIV") && asRegister(result) == AMD64.rax) || (name().endsWith("REM") && asRegister(result) == AMD64.rdx); + verifyKind((AMD64Arithmetic) code, result, x, y); + } + } + + + @SuppressWarnings("unused") + protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, CiValue result) { + switch (opcode) { + case INEG: masm.negl(asIntReg(result)); break; + case LNEG: masm.negq(asLongReg(result)); break; + case L2I: masm.andl(asIntReg(result), 0xFFFFFFFF); break; + case I2B: masm.signExtendByte(asIntReg(result)); break; + case I2C: masm.andl(asIntReg(result), 0xFFFF); break; + case I2S: masm.signExtendShort(asIntReg(result)); break; + default: throw Util.shouldNotReachHere(); + } + } + + protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, CiValue dst, CiValue src, LIRDebugInfo info) { + int exceptionOffset = -1; + if (isRegister(src)) { + switch (opcode) { + case IADD: masm.addl(asIntReg(dst), asIntReg(src)); break; + case ISUB: masm.subl(asIntReg(dst), asIntReg(src)); break; + case IAND: masm.andl(asIntReg(dst), asIntReg(src)); break; + case IMUL: masm.imull(asIntReg(dst), asIntReg(src)); break; + case IOR: masm.orl(asIntReg(dst), asIntReg(src)); break; + case IXOR: masm.xorl(asIntReg(dst), asIntReg(src)); break; + case ISHL: masm.shll(asIntReg(dst)); break; + case ISHR: masm.sarl(asIntReg(dst)); break; + case IUSHR:masm.shrl(asIntReg(dst)); break; + + case LADD: masm.addq(asLongReg(dst), asLongReg(src)); break; + case LSUB: masm.subq(asLongReg(dst), asLongReg(src)); break; + case LMUL: masm.imulq(asLongReg(dst), asLongReg(src)); break; + case LAND: masm.andq(asLongReg(dst), asLongReg(src)); break; + case LOR: masm.orq(asLongReg(dst), asLongReg(src)); break; + case LXOR: masm.xorq(asLongReg(dst), asLongReg(src)); break; + case LSHL: masm.shlq(asLongReg(dst)); break; + case LSHR: masm.sarq(asLongReg(dst)); break; + case LUSHR:masm.shrq(asLongReg(dst)); break; + + case FADD: masm.addss(asFloatReg(dst), asFloatReg(src)); break; + case FSUB: masm.subss(asFloatReg(dst), asFloatReg(src)); break; + case FMUL: masm.mulss(asFloatReg(dst), asFloatReg(src)); break; + case FDIV: masm.divss(asFloatReg(dst), asFloatReg(src)); break; + case FAND: masm.andps(asFloatReg(dst), asFloatReg(src)); break; + case FOR: masm.orps(asFloatReg(dst), asFloatReg(src)); break; + case FXOR: masm.xorps(asFloatReg(dst), asFloatReg(src)); break; + + case DADD: masm.addsd(asDoubleReg(dst), asDoubleReg(src)); break; + case DSUB: masm.subsd(asDoubleReg(dst), asDoubleReg(src)); break; + case DMUL: masm.mulsd(asDoubleReg(dst), asDoubleReg(src)); break; + case DDIV: masm.divsd(asDoubleReg(dst), asDoubleReg(src)); break; + case DAND: masm.andpd(asDoubleReg(dst), asDoubleReg(src)); break; + case DOR: masm.orpd(asDoubleReg(dst), asDoubleReg(src)); break; + case DXOR: masm.xorpd(asDoubleReg(dst), asDoubleReg(src)); break; + + case I2L: masm.movslq(asLongReg(dst), asIntReg(src)); break; + case F2D: masm.cvtss2sd(asDoubleReg(dst), asFloatReg(src)); break; + case D2F: masm.cvtsd2ss(asFloatReg(dst), asDoubleReg(src)); break; + case I2F: masm.cvtsi2ssl(asFloatReg(dst), asIntReg(src)); break; + case I2D: masm.cvtsi2sdl(asDoubleReg(dst), asIntReg(src)); break; + case L2F: masm.cvtsi2ssq(asFloatReg(dst), asLongReg(src)); break; + case L2D: masm.cvtsi2sdq(asDoubleReg(dst), asLongReg(src)); break; + case F2I: + masm.cvttss2sil(asIntReg(dst), asFloatReg(src)); + emitConvertFixup(tasm, masm, dst, src); + break; + case D2I: + masm.cvttsd2sil(asIntReg(dst), asDoubleReg(src)); + emitConvertFixup(tasm, masm, dst, src); + break; + case F2L: + masm.cvttss2siq(asLongReg(dst), asFloatReg(src)); + emitConvertFixup(tasm, masm, dst, src); + break; + case D2L: + masm.cvttsd2siq(asLongReg(dst), asDoubleReg(src)); + emitConvertFixup(tasm, masm, dst, src); + break; + case MOV_I2F: masm.movdl(asFloatReg(dst), asIntReg(src)); break; + case MOV_L2D: masm.movdq(asDoubleReg(dst), asLongReg(src)); break; + case MOV_F2I: masm.movdl(asIntReg(dst), asFloatReg(src)); break; + case MOV_D2L: masm.movdq(asLongReg(dst), asDoubleReg(src)); break; + + case IDIV: + case IREM: + masm.cdql(); + exceptionOffset = masm.codeBuffer.position(); + masm.idivl(asRegister(src)); + break; + + case LDIV: + case LREM: + Label continuation = new Label(); + if (opcode == LDIV) { + // check for special case of Long.MIN_VALUE / -1 + Label normalCase = new Label(); + masm.movq(AMD64.rdx, java.lang.Long.MIN_VALUE); + masm.cmpq(AMD64.rax, AMD64.rdx); + masm.jcc(ConditionFlag.notEqual, normalCase); + masm.cmpl(asRegister(src), -1); + masm.jcc(ConditionFlag.equal, continuation); + masm.bind(normalCase); + } + + masm.cdqq(); + exceptionOffset = masm.codeBuffer.position(); + masm.idivq(asRegister(src)); + masm.bind(continuation); + break; + + case IUDIV: + case IUREM: + // Must zero the high 64-bit word (in RDX) of the dividend + masm.xorq(AMD64.rdx, AMD64.rdx); + exceptionOffset = masm.codeBuffer.position(); + masm.divl(asRegister(src)); + break; + + case LUDIV: + case LUREM: + // Must zero the high 64-bit word (in RDX) of the dividend + masm.xorq(AMD64.rdx, AMD64.rdx); + exceptionOffset = masm.codeBuffer.position(); + masm.divq(asRegister(src)); + break; + default: + throw Util.shouldNotReachHere(); + } + } else if (isConstant(src)) { + switch (opcode) { + case IADD: masm.incrementl(asIntReg(dst), tasm.asIntConst(src)); break; + case ISUB: masm.decrementl(asIntReg(dst), tasm.asIntConst(src)); break; + case IMUL: masm.imull(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break; + case IAND: masm.andl(asIntReg(dst), tasm.asIntConst(src)); break; + case IOR: masm.orl(asIntReg(dst), tasm.asIntConst(src)); break; + case IXOR: masm.xorl(asIntReg(dst), tasm.asIntConst(src)); break; + case ISHL: masm.shll(asIntReg(dst), tasm.asIntConst(src) & 31); break; + case ISHR: masm.sarl(asIntReg(dst), tasm.asIntConst(src) & 31); break; + case IUSHR:masm.shrl(asIntReg(dst), tasm.asIntConst(src) & 31); break; + + case LADD: masm.addq(asLongReg(dst), tasm.asIntConst(src)); break; + case LSUB: masm.subq(asLongReg(dst), tasm.asIntConst(src)); break; + case LMUL: masm.imulq(asLongReg(dst), asLongReg(dst), tasm.asIntConst(src)); break; + case LAND: masm.andq(asLongReg(dst), tasm.asIntConst(src)); break; + case LOR: masm.orq(asLongReg(dst), tasm.asIntConst(src)); break; + case LXOR: masm.xorq(asLongReg(dst), tasm.asIntConst(src)); break; + case LSHL: masm.shlq(asLongReg(dst), tasm.asIntConst(src) & 63); break; + case LSHR: masm.sarq(asLongReg(dst), tasm.asIntConst(src) & 63); break; + case LUSHR:masm.shrq(asLongReg(dst), tasm.asIntConst(src) & 63); break; + + case FADD: masm.addss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; + case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; + case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; + case FAND: masm.andps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break; + case FOR: masm.orps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break; + case FXOR: masm.xorps(asFloatReg(dst), tasm.asFloatConstRef(src, 16)); break; + case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatConstRef(src)); break; + + case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; + case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; + case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; + case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleConstRef(src)); break; + case DAND: masm.andpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break; + case DOR: masm.orpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break; + case DXOR: masm.xorpd(asDoubleReg(dst), tasm.asDoubleConstRef(src, 16)); break; + default: throw Util.shouldNotReachHere(); + } + } else { + switch (opcode) { + case IADD: masm.addl(asIntReg(dst), tasm.asIntAddr(src)); break; + case ISUB: masm.subl(asIntReg(dst), tasm.asIntAddr(src)); break; + case IAND: masm.andl(asIntReg(dst), tasm.asIntAddr(src)); break; + case IOR: masm.orl(asIntReg(dst), tasm.asIntAddr(src)); break; + case IXOR: masm.xorl(asIntReg(dst), tasm.asIntAddr(src)); break; + + case LADD: masm.addq(asLongReg(dst), tasm.asLongAddr(src)); break; + case LSUB: masm.subq(asLongReg(dst), tasm.asLongAddr(src)); break; + case LAND: masm.andq(asLongReg(dst), tasm.asLongAddr(src)); break; + case LOR: masm.orq(asLongReg(dst), tasm.asLongAddr(src)); break; + case LXOR: masm.xorq(asLongReg(dst), tasm.asLongAddr(src)); break; + + case FADD: masm.addss(asFloatReg(dst), tasm.asFloatAddr(src)); break; + case FSUB: masm.subss(asFloatReg(dst), tasm.asFloatAddr(src)); break; + case FMUL: masm.mulss(asFloatReg(dst), tasm.asFloatAddr(src)); break; + case FDIV: masm.divss(asFloatReg(dst), tasm.asFloatAddr(src)); break; + + case DADD: masm.addsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; + case DSUB: masm.subsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; + case DMUL: masm.mulsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; + case DDIV: masm.divsd(asDoubleReg(dst), tasm.asDoubleAddr(src)); break; + default: throw Util.shouldNotReachHere(); + } + } + + if (info != null) { + assert exceptionOffset != -1; + tasm.recordImplicitException(exceptionOffset, info); + } + } + + private static void emitConvertFixup(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue x) { + ConvertSlowPath slowPath = new ConvertSlowPath(result, x); + tasm.slowPaths.add(slowPath); + switch (result.kind) { + case Int: masm.cmpl(asIntReg(result), Integer.MIN_VALUE); break; + case Long: masm.cmpq(asLongReg(result), tasm.asLongConstRef(CiConstant.forLong(java.lang.Long.MIN_VALUE))); break; + default: throw Util.shouldNotReachHere(); + } + masm.jcc(ConditionFlag.equal, slowPath.start); + masm.bind(slowPath.continuation); + } + + private static class ConvertSlowPath extends AMD64SlowPath { + public final Label start = new Label(); + public final Label continuation = new Label(); + private final CiValue result; + private final CiValue x; + + public ConvertSlowPath(CiValue result, CiValue x) { + this.result = result; + this.x = x; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + masm.bind(start); + switch (x.kind) { + case Float: masm.ucomiss(asFloatReg(x), tasm.asFloatConstRef(CiConstant.FLOAT_0)); break; + case Double: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(CiConstant.DOUBLE_0)); break; + default: throw Util.shouldNotReachHere(); + } + Label nan = new Label(); + masm.jcc(ConditionFlag.parity, nan); + masm.jcc(ConditionFlag.below, continuation); + + // input is > 0 -> return maxInt + // result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff + switch (result.kind) { + case Int: masm.decrementl(asIntReg(result), 1); break; + case Long: masm.decrementq(asLongReg(result), 1); break; + default: throw Util.shouldNotReachHere(); + } + masm.jmp(continuation); + + // input is NaN -> return 0 + masm.bind(nan); + masm.xorptr(asRegister(result), asRegister(result)); + masm.jmp(continuation); + } + } + + + private static void verifyKind(AMD64Arithmetic opcode, CiValue result, CiValue x, CiValue y) { + assert (opcode.name().startsWith("I") && result.kind == CiKind.Int && x.kind.stackKind() == CiKind.Int && y.kind.stackKind() == CiKind.Int) + || (opcode.name().startsWith("L") && result.kind == CiKind.Long && x.kind == CiKind.Long && y.kind == CiKind.Long) + || (opcode.name().startsWith("F") && result.kind == CiKind.Float && x.kind == CiKind.Float && y.kind == CiKind.Float) + || (opcode.name().startsWith("D") && result.kind == CiKind.Double && x.kind == CiKind.Double && y.kind == CiKind.Double); + } +} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ArithmeticOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ArithmeticOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public enum AMD64ArithmeticOpcode implements LIROpcode { - IADD, ISUB, IAND, IOR, IXOR, - LADD, LSUB, LAND, LOR, LXOR, - FADD, FSUB, FMUL, FDIV, - DADD, DSUB, DMUL, DDIV; - - public LIRInstruction create(CiValue result, CiValue x, CiValue y) { - assert (name().startsWith("I") && result.kind == CiKind.Int && x.kind.stackKind() == CiKind.Int && y.kind.stackKind() == CiKind.Int) - || (name().startsWith("L") && result.kind == CiKind.Long && x.kind == CiKind.Long && y.kind == CiKind.Long) - || (name().startsWith("F") && result.kind == CiKind.Float && x.kind == CiKind.Float && y.kind == CiKind.Float) - || (name().startsWith("D") && result.kind == CiKind.Double && x.kind == CiKind.Double && y.kind == CiKind.Double); - - CiValue[] inputs = new CiValue[] {x}; - CiValue[] alives = new CiValue[] {y}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, null, inputs, alives, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - emit(tasm, masm, output(0), input(0), alive(0)); - } - - @Override - public EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Alive && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - return super.flagsFor(mode, index); - } - }; - } - - protected void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue x, CiValue y) { - assert sameRegister(x, y) || differentRegisters(result, y); - AMD64MoveOpcode.move(tasm, masm, result, x); - - CiRegister dst = asRegister(result); - if (isRegister(y)) { - CiRegister rreg = asRegister(y); - switch (this) { - case IADD: masm.addl(dst, rreg); break; - case ISUB: masm.subl(dst, rreg); break; - case IAND: masm.andl(dst, rreg); break; - case IOR: masm.orl(dst, rreg); break; - case IXOR: masm.xorl(dst, rreg); break; - case LADD: masm.addq(dst, rreg); break; - case LSUB: masm.subq(dst, rreg); break; - case LAND: masm.andq(dst, rreg); break; - case LOR: masm.orq(dst, rreg); break; - case LXOR: masm.xorq(dst, rreg); break; - case FADD: masm.addss(dst, rreg); break; - case FSUB: masm.subss(dst, rreg); break; - case FMUL: masm.mulss(dst, rreg); break; - case FDIV: masm.divss(dst, rreg); break; - case DADD: masm.addsd(dst, rreg); break; - case DSUB: masm.subsd(dst, rreg); break; - case DMUL: masm.mulsd(dst, rreg); break; - case DDIV: masm.divsd(dst, rreg); break; - default: throw Util.shouldNotReachHere(); - } - } else if (isConstant(y)) { - switch (this) { - case IADD: masm.incrementl(dst, tasm.asIntConst(y)); break; - case ISUB: masm.decrementl(dst, tasm.asIntConst(y)); break; - case IAND: masm.andl(dst, tasm.asIntConst(y)); break; - case IOR: masm.orl(dst, tasm.asIntConst(y)); break; - case IXOR: masm.xorl(dst, tasm.asIntConst(y)); break; - case LADD: masm.addq(dst, tasm.asIntConst(y)); break; - case LSUB: masm.subq(dst, tasm.asIntConst(y)); break; - case LAND: masm.andq(dst, tasm.asIntConst(y)); break; - case LOR: masm.orq(dst, tasm.asIntConst(y)); break; - case LXOR: masm.xorq(dst, tasm.asIntConst(y)); break; - case FADD: masm.addss(dst, tasm.asFloatConstRef(y)); break; - case FSUB: masm.subss(dst, tasm.asFloatConstRef(y)); break; - case FMUL: masm.mulss(dst, tasm.asFloatConstRef(y)); break; - case FDIV: masm.divss(dst, tasm.asFloatConstRef(y)); break; - case DADD: masm.addsd(dst, tasm.asDoubleConstRef(y)); break; - case DSUB: masm.subsd(dst, tasm.asDoubleConstRef(y)); break; - case DMUL: masm.mulsd(dst, tasm.asDoubleConstRef(y)); break; - case DDIV: masm.divsd(dst, tasm.asDoubleConstRef(y)); break; - default: throw Util.shouldNotReachHere(); - } - } else { - CiAddress raddr = tasm.asAddress(y); - switch (this) { - case IADD: masm.addl(dst, raddr); break; - case ISUB: masm.subl(dst, raddr); break; - case IAND: masm.andl(dst, raddr); break; - case IOR: masm.orl(dst, raddr); break; - case IXOR: masm.xorl(dst, raddr); break; - case LADD: masm.addq(dst, raddr); break; - case LSUB: masm.subq(dst, raddr); break; - case LAND: masm.andq(dst, raddr); break; - case LOR: masm.orq(dst, raddr); break; - case LXOR: masm.xorq(dst, raddr); break; - case FADD: masm.addss(dst, raddr); break; - case FSUB: masm.subss(dst, raddr); break; - case FMUL: masm.mulss(dst, raddr); break; - case FDIV: masm.divss(dst, raddr); break; - case DADD: masm.addsd(dst, raddr); break; - case DSUB: masm.subsd(dst, raddr); break; - case DMUL: masm.mulsd(dst, raddr); break; - case DDIV: masm.divsd(dst, raddr); break; - default: throw Util.shouldNotReachHere(); - } - } - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Call.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Call.java Thu Jan 26 12:23:00 2012 +0100 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.target.amd64; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiTargetMethod.Mark; +import com.oracle.max.cri.xir.CiXirAssembler.XirMark; +import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.asm.*; +import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.util.*; + +public class AMD64Call { + + public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { + private final Object targetMethod; + private final Map marks; + + public DirectCallOp(Object targetMethod, CiValue result, CiValue[] parameters, LIRDebugInfo info, Map marks) { + super("CALL_DIRECT", new CiValue[] {result}, info, parameters, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.targetMethod = targetMethod; + this.marks = marks; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + callAlignment(tasm, masm); + if (marks != null) { + marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0])); + } + directCall(tasm, masm, targetMethod, info); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + } else if (mode == OperandMode.Output) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); + } + throw Util.shouldNotReachHere(); + } + } + + public static class IndirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { + private final Object targetMethod; + private final Map marks; + + private static CiValue[] concat(CiValue[] parameters, CiValue targetAddress) { + CiValue[] result = Arrays.copyOf(parameters, parameters.length + 1); + result[result.length - 1] = targetAddress; + return result; + } + + public IndirectCallOp(Object targetMethod, CiValue result, CiValue[] parameters, CiValue targetAddress, LIRDebugInfo info, Map marks) { + super("CALL_INDIRECT", new CiValue[] {result}, info, concat(parameters, targetAddress), LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.targetMethod = targetMethod; + this.marks = marks; + } + + private CiValue targetAddress() { + return input(inputs.length - 1); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + callAlignment(tasm, masm); + if (marks != null) { + marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0])); + } + indirectCall(tasm, masm, asRegister(targetAddress()), targetMethod, info); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + } else if (mode == OperandMode.Output) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); + } + throw Util.shouldNotReachHere(); + } + } + + + public static void callAlignment(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + if (GraalOptions.AlignCallsForPatching) { + // make sure that the displacement word of the call ends up word aligned + int offset = masm.codeBuffer.position(); + offset += tasm.target.arch.machineCodeCallDisplacementOffset; + while (offset++ % tasm.target.wordSize != 0) { + masm.nop(); + } + } + } + + public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRDebugInfo info) { + int before = masm.codeBuffer.position(); + if (target instanceof CiRuntimeCall) { + long maxOffset = tasm.runtime.getMaxCallTargetOffset((CiRuntimeCall) target); + if (maxOffset != (int) maxOffset) { + // offset might not fit a 32-bit immediate, generate an + // indirect call with a 64-bit immediate + CiRegister scratch = tasm.frameMap.registerConfig.getScratchRegister(); + // TODO(cwi): we want to get rid of a generally reserved scratch register. + masm.movq(scratch, 0L); + masm.call(scratch); + } else { + masm.call(); + } + } else { + masm.call(); + } + int after = masm.codeBuffer.position(); + tasm.recordDirectCall(before, after, tasm.runtime.asCallTarget(target), info); + tasm.recordExceptionHandlers(after, info); + masm.ensureUniquePC(); + } + + public static void directJmp(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target) { + int before = masm.codeBuffer.position(); + masm.jmp(0, true); + int after = masm.codeBuffer.position(); + tasm.recordDirectCall(before, after, tasm.runtime.asCallTarget(target), null); + masm.ensureUniquePC(); + } + + public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiRegister dst, Object target, LIRDebugInfo info) { + int before = masm.codeBuffer.position(); + masm.call(dst); + int after = masm.codeBuffer.position(); + tasm.recordIndirectCall(before, after, tasm.runtime.asCallTarget(target), info); + tasm.recordExceptionHandlers(after, info); + masm.ensureUniquePC(); + } + + public static void shouldNotReachHere(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + if (GraalOptions.GenAssertionCode) { + directCall(tasm, masm, CiRuntimeCall.Debug, null); + masm.hlt(); + } + } +} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CallOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CallOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiTargetMethod.Mark; -import com.oracle.max.cri.xir.CiXirAssembler.XirMark; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public enum AMD64CallOpcode implements StandardOpcode.CallOpcode { - DIRECT_CALL, INDIRECT_CALL, NATIVE_CALL; - - public LIRInstruction create(Object target, CiValue result, List arguments, CiValue targetAddress, LIRDebugInfo info, Map marks) { - return new LIRCall(this, target, result, arguments, targetAddress, info, marks) { - @Override - public void emitCode(TargetMethodAssembler tasm) { - emit(tasm, (AMD64MacroAssembler) tasm.asm, this); - } - - @Override - public boolean hasCall() { - return true; - } - }; - } - - private void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, LIRCall op) { - switch (this) { - case DIRECT_CALL: { - callAlignment(tasm, masm); - if (op.marks != null) { - op.marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0])); - } - directCall(tasm, masm, op.target, op.info); - break; - } - case INDIRECT_CALL: { - callAlignment(tasm, masm); - if (op.marks != null) { - op.marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0])); - } - CiRegister reg = asRegister(op.targetAddress()); - indirectCall(tasm, masm, reg, op.target, op.info); - break; - } - case NATIVE_CALL: { - CiRegister reg = asRegister(op.targetAddress()); - indirectCall(tasm, masm, reg, op.target, op.info); - break; - } - default: - throw Util.shouldNotReachHere(); - } - } - - - public static void callAlignment(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - if (GraalOptions.AlignCallsForPatching) { - // make sure that the displacement word of the call ends up word aligned - int offset = masm.codeBuffer.position(); - offset += tasm.target.arch.machineCodeCallDisplacementOffset; - while (offset++ % tasm.target.wordSize != 0) { - masm.nop(); - } - } - } - - public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRDebugInfo info) { - int before = masm.codeBuffer.position(); - if (target instanceof CiRuntimeCall) { - long maxOffset = tasm.runtime.getMaxCallTargetOffset((CiRuntimeCall) target); - if (maxOffset != (int) maxOffset) { - // offset might not fit a 32-bit immediate, generate an - // indirect call with a 64-bit immediate - CiRegister scratch = tasm.frameMap.registerConfig.getScratchRegister(); - // TODO(cwi): we want to get rid of a generally reserved scratch register. - masm.movq(scratch, 0L); - masm.call(scratch); - } else { - masm.call(); - } - } else { - masm.call(); - } - int after = masm.codeBuffer.position(); - tasm.recordDirectCall(before, after, asCallTarget(tasm, target), info); - tasm.recordExceptionHandlers(after, info); - masm.ensureUniquePC(); - } - - public static void directJmp(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target) { - int before = masm.codeBuffer.position(); - masm.jmp(0, true); - int after = masm.codeBuffer.position(); - tasm.recordDirectCall(before, after, asCallTarget(tasm, target), null); - masm.ensureUniquePC(); - } - - public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiRegister dst, Object target, LIRDebugInfo info) { - int before = masm.codeBuffer.position(); - masm.call(dst); - int after = masm.codeBuffer.position(); - tasm.recordIndirectCall(before, after, asCallTarget(tasm, target), info); - tasm.recordExceptionHandlers(after, info); - masm.ensureUniquePC(); - } - - private static Object asCallTarget(TargetMethodAssembler tasm, Object o) { - return tasm.runtime.asCallTarget(o); - } - - public static void shouldNotReachHere(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - if (GraalOptions.GenAssertionCode) { - directCall(tasm, masm, CiRuntimeCall.Debug, null); - masm.hlt(); - } - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Compare.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Compare.java Thu Jan 26 12:23:00 2012 +0100 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.target.amd64; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.compiler.asm.*; +import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.util.*; + +public enum AMD64Compare { + ICMP, LCMP, ACMP, FCMP, DCMP; + + public static class CompareOp extends AMD64LIRInstruction { + public CompareOp(AMD64Compare opcode, CiValue x, CiValue y) { + super(opcode, LIRInstruction.NO_OPERANDS, null, new CiValue[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + CiValue x = input(0); + CiValue y = input(1); + emit(tasm, masm, (AMD64Compare) code, x, y); + } + + @Override + public EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Input && index == 1) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } + throw Util.shouldNotReachHere(); + } + + @Override + protected void verify() { + CiValue x = input(0); + CiValue y = input(1); + + super.verify(); + assert (name().startsWith("I") && x.kind == CiKind.Int && y.kind.stackKind() == CiKind.Int) + || (name().startsWith("I") && x.kind == CiKind.Jsr && y.kind == CiKind.Jsr) + || (name().startsWith("L") && x.kind == CiKind.Long && y.kind == CiKind.Long) + || (name().startsWith("A") && x.kind == CiKind.Object && y.kind == CiKind.Object) + || (name().startsWith("F") && x.kind == CiKind.Float && y.kind == CiKind.Float) + || (name().startsWith("D") && x.kind == CiKind.Double && y.kind == CiKind.Double); + } + } + + protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Compare opcode, CiValue x, CiValue y) { + if (isRegister(y)) { + switch (opcode) { + case ICMP: masm.cmpl(asIntReg(x), asIntReg(y)); break; + case LCMP: masm.cmpq(asLongReg(x), asLongReg(y)); break; + case ACMP: masm.cmpptr(asObjectReg(x), asObjectReg(y)); break; + case FCMP: masm.ucomiss(asFloatReg(x), asFloatReg(y)); break; + case DCMP: masm.ucomisd(asDoubleReg(x), asDoubleReg(y)); break; + default: throw Util.shouldNotReachHere(); + } + } else if (isConstant(y)) { + switch (opcode) { + case ICMP: masm.cmpl(asIntReg(x), tasm.asIntConst(y)); break; + case LCMP: masm.cmpq(asLongReg(x), tasm.asIntConst(y)); break; + case ACMP: + if (((CiConstant) y).isNull()) { + masm.cmpq(asObjectReg(x), 0); break; + } else { + throw Util.shouldNotReachHere("Only null object constants are allowed in comparisons"); + } + case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatConstRef(y)); break; + case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(y)); break; + default: throw Util.shouldNotReachHere(); + } + } else { + switch (opcode) { + case ICMP: masm.cmpl(asIntReg(x), tasm.asIntAddr(y)); break; + case LCMP: masm.cmpq(asLongReg(x), tasm.asLongAddr(y)); break; + case ACMP: masm.cmpptr(asObjectReg(x), tasm.asObjectAddr(y)); break; + case FCMP: masm.ucomiss(asFloatReg(x), tasm.asFloatAddr(y)); break; + case DCMP: masm.ucomisd(asDoubleReg(x), tasm.asDoubleAddr(y)); break; + default: throw Util.shouldNotReachHere(); + } + } + } +} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompareOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompareOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public enum AMD64CompareOpcode implements LIROpcode { - ICMP, LCMP, ACMP, FCMP, DCMP; - - public LIRInstruction create(CiValue x, CiValue y) { - assert (name().startsWith("I") && x.kind == CiKind.Int && y.kind.stackKind() == CiKind.Int) - || (name().startsWith("I") && x.kind == CiKind.Jsr && y.kind == CiKind.Jsr) - || (name().startsWith("L") && x.kind == CiKind.Long && y.kind == CiKind.Long) - || (name().startsWith("A") && x.kind == CiKind.Object && y.kind == CiKind.Object) - || (name().startsWith("F") && x.kind == CiKind.Float && y.kind == CiKind.Float) - || (name().startsWith("D") && x.kind == CiKind.Double && y.kind == CiKind.Double); - CiValue[] inputs = new CiValue[] {x, y}; - - return new AMD64LIRInstruction(this, LIRInstruction.NO_OPERANDS, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - emit(tasm, masm, input(0), input(1)); - } - - @Override - public EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 1) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } - return super.flagsFor(mode, index); - } - }; - } - - protected void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue x, CiValue y) { - CiRegister lreg = asRegister(x); - if (isRegister(y)) { - CiRegister rreg = asRegister(y); - switch (this) { - case ICMP: masm.cmpl(lreg, rreg); break; - case LCMP: masm.cmpq(lreg, rreg); break; - case ACMP: masm.cmpptr(lreg, rreg); break; - case FCMP: masm.ucomiss(lreg, rreg); break; - case DCMP: masm.ucomisd(lreg, rreg); break; - default: throw Util.shouldNotReachHere(); - } - } else if (isConstant(y)) { - switch (this) { - case ICMP: masm.cmpl(lreg, tasm.asIntConst(y)); break; - case LCMP: masm.cmpq(lreg, tasm.asIntConst(y)); break; - case ACMP: - if (((CiConstant) y).isNull()) { - masm.cmpq(lreg, 0); break; - } else { - throw Util.shouldNotReachHere("Only null object constants are allowed in comparisons"); - } - case FCMP: masm.ucomiss(lreg, tasm.asFloatConstRef(y)); break; - case DCMP: masm.ucomisd(lreg, tasm.asDoubleConstRef(y)); break; - default: throw Util.shouldNotReachHere(); - } - } else { - CiAddress raddr = tasm.asAddress(y); - switch (this) { - case ICMP: masm.cmpl(lreg, raddr); break; - case LCMP: masm.cmpq(lreg, raddr); break; - case ACMP: masm.cmpptr(lreg, raddr); break; - case FCMP: masm.ucomiss(lreg, raddr); break; - case DCMP: masm.ucomisd(lreg, raddr); break; - default: throw Util.shouldNotReachHere(); - } - } - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompareToIntOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompareToIntOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompareToIntOpcode.java Thu Jan 26 12:23:00 2012 +0100 @@ -24,6 +24,8 @@ import static com.oracle.max.cri.ci.CiValueUtil.*; +import java.util.*; + import com.oracle.max.asm.*; import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; import com.oracle.max.asm.target.amd64.*; @@ -37,7 +39,7 @@ * integer constants -1, 0, 1 on less, equal, or greater, respectively. For floating point compares, * unordered can be either greater {@link #CMP2INT_UG} or less {@link #CMP2INT_UL}. */ -public enum AMD64CompareToIntOpcode implements LIROpcode { +public enum AMD64CompareToIntOpcode { CMP2INT, CMP2INT_UG, CMP2INT_UL; public LIRInstruction create(CiValue result) { @@ -48,6 +50,14 @@ public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { emit(masm, output(0)); } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register); + } + throw Util.shouldNotReachHere(); + } }; } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlow.java Thu Jan 26 12:23:00 2012 +0100 @@ -0,0 +1,443 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.target.amd64; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiAddress.Scale; +import com.oracle.max.cri.ci.CiTargetMethod.JumpTable; +import com.oracle.max.graal.compiler.asm.*; +import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.nodes.calc.*; + +public class AMD64ControlFlow { + + public static class LabelOp extends AMD64LIRInstruction implements StandardOp.LabelOp { + private final Label label; + private final boolean align; + + public LabelOp(Label label, boolean align) { + super("LABEL", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.label = label; + this.align = align; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + if (align) { + masm.align(tasm.target.wordSize); + } + masm.bind(label); + } + + @Override + public String operationString() { + return label.toString(); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + throw Util.shouldNotReachHere(); + } + } + + + public static class ReturnOp extends AMD64LIRInstruction { + public ReturnOp(CiValue input) { + super("RETURN", LIRInstruction.NO_OPERANDS, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + masm.ret(0); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); + } + throw Util.shouldNotReachHere(); + } + } + + + public static class JumpOp extends AMD64LIRInstruction implements StandardOp.JumpOp { + private final LabelRef destination; + + public JumpOp(LabelRef destination, LIRDebugInfo info) { + super("JUMP", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.destination = destination; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + masm.jmp(destination.label()); + } + + @Override + public LabelRef destination() { + return destination; + } + + @Override + public String operationString() { + return "[" + destination + "]"; + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + throw Util.shouldNotReachHere(); + } + } + + + public static class BranchOp extends AMD64LIRInstruction implements StandardOp.BranchOp { + protected Condition condition; + protected LabelRef destination; + + public BranchOp(Condition condition, LabelRef destination, LIRDebugInfo info) { + super("BRANCH", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.condition = condition; + this.destination = destination; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + masm.jcc(intCond(condition), destination.label()); + } + + @Override + public LabelRef destination() { + return destination; + } + + @Override + public void negate(LabelRef newDestination) { + destination = newDestination; + condition = condition.negate(); + } + + @Override + public String operationString() { + return condition.operator + " [" + destination + "]"; + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + throw Util.shouldNotReachHere(); + } + } + + + public static class FloatBranchOp extends BranchOp { + protected boolean unorderedIsTrue; + + public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination, LIRDebugInfo info) { + super(condition, destination, info); + this.unorderedIsTrue = unorderedIsTrue; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + floatJcc(masm, condition, unorderedIsTrue, destination.label()); + } + + @Override + public void negate(LabelRef newDestination) { + super.negate(newDestination); + unorderedIsTrue = !unorderedIsTrue; + } + + @Override + public String operationString() { + return condition.operator + " [" + destination + "]" + (unorderedIsTrue ? " unorderedIsTrue" : " unorderedIsFalse"); + } + } + + + public static class TableSwitchOp extends AMD64LIRInstruction { + private final int lowKey; + private final LabelRef defaultTarget; + private final LabelRef[] targets; + + public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch) { + super("TABLE_SWITCH", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, new CiValue[] {index}, new CiValue[] {scratch}); + this.lowKey = lowKey; + this.defaultTarget = defaultTarget; + this.targets = targets; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(alive(0)), asLongReg(temp(0))); + } + + @Override + public String operationString() { + StringBuilder buf = new StringBuilder(super.operationString()); + buf.append("\ndefault: [").append(defaultTarget).append(']'); + int key = lowKey; + for (LabelRef l : targets) { + buf.append("\ncase ").append(key).append(": [").append(l).append(']'); + key++; + } + return buf.toString(); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Alive && index == 0) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Temp && index == 0) { + return EnumSet.of(OperandFlag.Register); + } + throw Util.shouldNotReachHere(); + } + } + + + public static class CondMoveOp extends AMD64LIRInstruction { + private final Condition condition; + + public CondMoveOp(Variable result, Condition condition, Variable trueValue, CiValue falseValue) { + super("CMOVE", new CiValue[] {result}, null, new CiValue[] {falseValue}, new CiValue[] {trueValue}, LIRInstruction.NO_OPERANDS); + this.condition = condition; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + cmove(tasm, masm, output(0), false, condition, false, alive(0), input(0)); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Alive && index == 0) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + throw Util.shouldNotReachHere(); + } + + @Override + public String operationString() { + return condition.toString() + " " + super.operationString(); + } + } + + + public static class FloatCondMoveOp extends AMD64LIRInstruction { + private final Condition condition; + private final boolean unorderedIsTrue; + + public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) { + super("FLOAT_CMOVE", new CiValue[] {result}, null, LIRInstruction.NO_OPERANDS, new CiValue[] {trueValue, falseValue}, LIRInstruction.NO_OPERANDS); + this.condition = condition; + this.unorderedIsTrue = unorderedIsTrue; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + cmove(tasm, masm, output(0), true, condition, unorderedIsTrue, alive(0), alive(1)); + } + + @Override + public String operationString() { + return condition.toString() + " unordered=" + unorderedIsTrue + " " + super.operationString(); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Alive && index == 0) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Alive && index == 1) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register); + } + throw Util.shouldNotReachHere(); + } + } + + + private static void tableswitch(TargetMethodAssembler tasm, AMD64MacroAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, CiRegister value, CiRegister scratch) { + Buffer buf = masm.codeBuffer; + // Compare index against jump table bounds + int highKey = lowKey + targets.length - 1; + if (lowKey != 0) { + // subtract the low value from the switch value + masm.subl(value, lowKey); + masm.cmpl(value, highKey - lowKey); + } else { + masm.cmpl(value, highKey); + } + + // Jump to default target if index is not within the jump table + masm.jcc(ConditionFlag.above, defaultTarget.label()); + + // Set scratch to address of jump table + int leaPos = buf.position(); + masm.leaq(scratch, new CiAddress(tasm.target.wordKind, AMD64.rip.asValue(), 0)); + int afterLea = buf.position(); + + // Load jump table entry into scratch and jump to it + masm.movslq(value, new CiAddress(CiKind.Int, scratch.asValue(), value.asValue(), Scale.Times4, 0)); + masm.addq(scratch, value); + masm.jmp(scratch); + + // Inserting padding so that jump table address is 4-byte aligned + if ((buf.position() & 0x3) != 0) { + masm.nop(4 - (buf.position() & 0x3)); + } + + // Patch LEA instruction above now that we know the position of the jump table + int jumpTablePos = buf.position(); + buf.setPosition(leaPos); + masm.leaq(scratch, new CiAddress(tasm.target.wordKind, AMD64.rip.asValue(), jumpTablePos - afterLea)); + buf.setPosition(jumpTablePos); + + // Emit jump table entries + for (LabelRef target : targets) { + Label label = target.label(); + int offsetToJumpTableBase = buf.position() - jumpTablePos; + if (label.isBound()) { + int imm32 = label.position() - jumpTablePos; + buf.emitInt(imm32); + } else { + label.addPatchAt(buf.position()); + + buf.emitByte(0); // psuedo-opcode for jump table entry + buf.emitShort(offsetToJumpTableBase); + buf.emitByte(0); // padding to make jump table entry 4 bytes wide + } + } + + JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4); + tasm.targetMethod.addAnnotation(jt); + } + + private static void floatJcc(AMD64MacroAssembler masm, Condition condition, boolean unorderedIsTrue, Label label) { + ConditionFlag cond = floatCond(condition); + Label endLabel = new Label(); + if (unorderedIsTrue && !trueOnUnordered(cond)) { + masm.jcc(ConditionFlag.parity, label); + } else if (!unorderedIsTrue && trueOnUnordered(cond)) { + masm.jcc(ConditionFlag.parity, endLabel); + } + masm.jcc(cond, label); + masm.bind(endLabel); + } + + private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, boolean isFloat, Condition condition, boolean unorderedIsTrue, CiValue trueValue, CiValue falseValue) { + ConditionFlag cond = isFloat ? floatCond(condition) : intCond(condition); + // check that we don't overwrite an input operand before it is used. + assert !result.equals(trueValue); + + AMD64Move.move(tasm, masm, result, falseValue); + cmove(tasm, masm, result, cond, trueValue); + + if (isFloat) { + if (unorderedIsTrue && !trueOnUnordered(cond)) { + cmove(tasm, masm, result, ConditionFlag.parity, trueValue); + } else if (!unorderedIsTrue && trueOnUnordered(cond)) { + cmove(tasm, masm, result, ConditionFlag.parity, falseValue); + } + } + } + + private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, ConditionFlag cond, CiValue other) { + if (isRegister(other)) { + assert asRegister(other) != asRegister(result) : "other already overwritten by previous move"; + switch (other.kind) { + case Int: masm.cmovl(cond, asRegister(result), asRegister(other)); break; + case Long: masm.cmovq(cond, asRegister(result), asRegister(other)); break; + default: throw Util.shouldNotReachHere(); + } + } else { + switch (other.kind) { + case Int: masm.cmovl(cond, asRegister(result), tasm.asAddress(other)); break; + case Long: masm.cmovq(cond, asRegister(result), tasm.asAddress(other)); break; + default: throw Util.shouldNotReachHere(); + } + } + } + + private static ConditionFlag intCond(Condition cond) { + switch (cond) { + case EQ: return ConditionFlag.equal; + case NE: return ConditionFlag.notEqual; + case LT: return ConditionFlag.less; + case LE: return ConditionFlag.lessEqual; + case GE: return ConditionFlag.greaterEqual; + case GT: return ConditionFlag.greater; + case BE: return ConditionFlag.belowEqual; + case AE: return ConditionFlag.aboveEqual; + case AT: return ConditionFlag.above; + case BT: return ConditionFlag.below; + case OF: return ConditionFlag.overflow; + case NOF: return ConditionFlag.noOverflow; + default: throw Util.shouldNotReachHere(); + } + } + + private static ConditionFlag floatCond(Condition cond) { + switch (cond) { + case EQ: return ConditionFlag.equal; + case NE: return ConditionFlag.notEqual; + case BT: return ConditionFlag.below; + case BE: return ConditionFlag.belowEqual; + case AE: return ConditionFlag.aboveEqual; + case AT: return ConditionFlag.above; + default: throw Util.shouldNotReachHere(); + } + } + + private static boolean trueOnUnordered(ConditionFlag condition) { + switch(condition) { + case aboveEqual: + case notEqual: + case above: + case less: + case overflow: + return false; + case equal: + case belowEqual: + case below: + case greaterEqual: + case noOverflow: + return true; + default: + throw Util.shouldNotReachHere(); + } + } +} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlowOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlowOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,381 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.*; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiAddress.Scale; -import com.oracle.max.cri.ci.CiTargetMethod.JumpTable; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.nodes.calc.*; - -public class AMD64ControlFlowOpcode { - - public enum LabelOpcode implements LIROpcode { - LABEL; - - public LIRInstruction create(final Label label, final boolean align) { - return new AMD64LIRInstruction(this, LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - if (align) { - masm.align(tasm.target.wordSize); - } - masm.bind(label); - } - - @Override - public String operationString() { - return label.toString(); - } - }; - } - } - - - public enum ReturnOpcode implements StandardOpcode.ReturnOpcode { - RETURN; - - public LIRInstruction create(CiValue input) { - CiValue[] inputs = new CiValue[] {input}; - - return new AMD64LIRInstruction(this, LIRInstruction.NO_OPERANDS, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.ret(0); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); - } - throw Util.shouldNotReachHere(); - } - }; - } - } - - - public enum JumpOpcode implements LIROpcode { - JUMP; - - public LIRInstruction create(LabelRef label, LIRDebugInfo info) { - return new LIRBranch(this, null, false, label, info) { - @Override - public void emitCode(TargetMethodAssembler tasm) { - AMD64MacroAssembler masm = (AMD64MacroAssembler) tasm.asm; - masm.jmp(this.destination.label()); - } - - @Override - public String operationString() { - return "[" + destination + "]"; - } - }; - } - } - - - public enum BranchOpcode implements LIROpcode { - BRANCH; - - public LIRInstruction create(Condition cond, LabelRef label, LIRDebugInfo info) { - return new LIRBranch(this, cond, false, label, info) { - @Override - public void emitCode(TargetMethodAssembler tasm) { - AMD64MacroAssembler masm = (AMD64MacroAssembler) tasm.asm; - masm.jcc(intCond(cond), destination.label()); - } - - @Override - public String operationString() { - return cond.operator + " [" + destination + "]"; - } - }; - } - } - - - public enum FloatBranchOpcode implements LIROpcode { - FLOAT_BRANCH; - - public LIRInstruction create(Condition cond, boolean unorderedIsTrue, LabelRef label, LIRDebugInfo info) { - return new LIRBranch(this, cond, unorderedIsTrue, label, info) { - @Override - public void emitCode(TargetMethodAssembler tasm) { - floatJcc((AMD64MacroAssembler) tasm.asm, cond, unorderedIsTrue, destination.label()); - } - - @Override - public String operationString() { - return cond.operator + " [" + destination + "]" + (unorderedIsTrue ? " unorderedIsTrue" : " unorderedIsFalse"); - } - }; - } - } - - - public enum TableSwitchOpcode implements LIROpcode { - TABLE_SWITCH; - - public LIRInstruction create(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch) { - CiValue[] alives = new CiValue[] {index}; - CiValue[] temps = new CiValue[] {scratch}; - - return new AMD64LIRInstruction(this, LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, alives, temps) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(alive(0)), asLongReg(temp(0))); - } - - @Override - public String operationString() { - StringBuilder buf = new StringBuilder(super.operationString()); - buf.append("\ndefault: [").append(defaultTarget).append(']'); - int key = lowKey; - for (LabelRef l : targets) { - buf.append("\ncase ").append(key).append(": [").append(l).append(']'); - key++; - } - return buf.toString(); - } - }; - } - } - - - public enum CondMoveOpcode implements LIROpcode { - CMOVE; - - public LIRInstruction create(Variable result, final Condition condition, Variable trueValue, CiValue falseValue) { - CiValue[] inputs = new CiValue[] {falseValue}; - CiValue[] alives = new CiValue[] {trueValue}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, null, inputs, alives, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - cmove(tasm, masm, output(0), false, condition, false, alive(0), input(0)); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - return super.flagsFor(mode, index); - } - - @Override - public String operationString() { - return condition.toString() + " " + super.operationString(); - } - }; - } - } - - - public enum FloatCondMoveOpcode implements LIROpcode { - FLOAT_CMOVE; - - public LIRInstruction create(Variable result, final Condition condition, final boolean unorderedIsTrue, Variable trueValue, Variable falseValue) { - CiValue[] alives = new CiValue[] {trueValue, falseValue}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, null, LIRInstruction.NO_OPERANDS, alives, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - cmove(tasm, masm, output(0), true, condition, unorderedIsTrue, alive(0), alive(1)); - } - - @Override - public String operationString() { - return condition.toString() + " unordered=" + unorderedIsTrue + " " + super.operationString(); - } - }; - } - } - - - private static void tableswitch(TargetMethodAssembler tasm, AMD64MacroAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, CiRegister value, CiRegister scratch) { - Buffer buf = masm.codeBuffer; - // Compare index against jump table bounds - int highKey = lowKey + targets.length - 1; - if (lowKey != 0) { - // subtract the low value from the switch value - masm.subl(value, lowKey); - masm.cmpl(value, highKey - lowKey); - } else { - masm.cmpl(value, highKey); - } - - // Jump to default target if index is not within the jump table - masm.jcc(ConditionFlag.above, defaultTarget.label()); - - // Set scratch to address of jump table - int leaPos = buf.position(); - masm.leaq(scratch, new CiAddress(tasm.target.wordKind, AMD64.rip.asValue(), 0)); - int afterLea = buf.position(); - - // Load jump table entry into scratch and jump to it - masm.movslq(value, new CiAddress(CiKind.Int, scratch.asValue(), value.asValue(), Scale.Times4, 0)); - masm.addq(scratch, value); - masm.jmp(scratch); - - // Inserting padding so that jump table address is 4-byte aligned - if ((buf.position() & 0x3) != 0) { - masm.nop(4 - (buf.position() & 0x3)); - } - - // Patch LEA instruction above now that we know the position of the jump table - int jumpTablePos = buf.position(); - buf.setPosition(leaPos); - masm.leaq(scratch, new CiAddress(tasm.target.wordKind, AMD64.rip.asValue(), jumpTablePos - afterLea)); - buf.setPosition(jumpTablePos); - - // Emit jump table entries - for (LabelRef target : targets) { - Label label = target.label(); - int offsetToJumpTableBase = buf.position() - jumpTablePos; - if (label.isBound()) { - int imm32 = label.position() - jumpTablePos; - buf.emitInt(imm32); - } else { - label.addPatchAt(buf.position()); - - buf.emitByte(0); // psuedo-opcode for jump table entry - buf.emitShort(offsetToJumpTableBase); - buf.emitByte(0); // padding to make jump table entry 4 bytes wide - } - } - - JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4); - tasm.targetMethod.addAnnotation(jt); - } - - private static void floatJcc(AMD64MacroAssembler masm, Condition condition, boolean unorderedIsTrue, Label label) { - ConditionFlag cond = floatCond(condition); - Label endLabel = new Label(); - if (unorderedIsTrue && !trueOnUnordered(cond)) { - masm.jcc(ConditionFlag.parity, label); - } else if (!unorderedIsTrue && trueOnUnordered(cond)) { - masm.jcc(ConditionFlag.parity, endLabel); - } - masm.jcc(cond, label); - masm.bind(endLabel); - } - - private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, boolean isFloat, Condition condition, boolean unorderedIsTrue, CiValue trueValue, CiValue falseValue) { - ConditionFlag cond = isFloat ? floatCond(condition) : intCond(condition); - // check that we don't overwrite an input operand before it is used. - assert !result.equals(trueValue); - - AMD64MoveOpcode.move(tasm, masm, result, falseValue); - cmove(tasm, masm, result, cond, trueValue); - - if (isFloat) { - if (unorderedIsTrue && !trueOnUnordered(cond)) { - cmove(tasm, masm, result, ConditionFlag.parity, trueValue); - } else if (!unorderedIsTrue && trueOnUnordered(cond)) { - cmove(tasm, masm, result, ConditionFlag.parity, falseValue); - } - } - } - - private static void cmove(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, ConditionFlag cond, CiValue other) { - if (isRegister(other)) { - assert asRegister(other) != asRegister(result) : "other already overwritten by previous move"; - switch (other.kind) { - case Int: masm.cmovl(cond, asRegister(result), asRegister(other)); break; - case Long: masm.cmovq(cond, asRegister(result), asRegister(other)); break; - default: throw Util.shouldNotReachHere(); - } - } else { - switch (other.kind) { - case Int: masm.cmovl(cond, asRegister(result), tasm.asAddress(other)); break; - case Long: masm.cmovq(cond, asRegister(result), tasm.asAddress(other)); break; - default: throw Util.shouldNotReachHere(); - } - } - } - - private static ConditionFlag intCond(Condition cond) { - switch (cond) { - case EQ: return ConditionFlag.equal; - case NE: return ConditionFlag.notEqual; - case LT: return ConditionFlag.less; - case LE: return ConditionFlag.lessEqual; - case GE: return ConditionFlag.greaterEqual; - case GT: return ConditionFlag.greater; - case BE: return ConditionFlag.belowEqual; - case AE: return ConditionFlag.aboveEqual; - case AT: return ConditionFlag.above; - case BT: return ConditionFlag.below; - case OF: return ConditionFlag.overflow; - case NOF: return ConditionFlag.noOverflow; - default: throw Util.shouldNotReachHere(); - } - } - - private static ConditionFlag floatCond(Condition cond) { - switch (cond) { - case EQ: return ConditionFlag.equal; - case NE: return ConditionFlag.notEqual; - case BT: return ConditionFlag.below; - case BE: return ConditionFlag.belowEqual; - case AE: return ConditionFlag.aboveEqual; - case AT: return ConditionFlag.above; - default: throw Util.shouldNotReachHere(); - } - } - - private static boolean trueOnUnordered(ConditionFlag condition) { - switch(condition) { - case aboveEqual: - case notEqual: - case above: - case less: - case overflow: - return false; - case equal: - case belowEqual: - case below: - case greaterEqual: - case noOverflow: - return true; - default: - throw Util.shouldNotReachHere(); - } - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ConvertOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ConvertOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.*; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.asm.target.amd64.AMD64Assembler.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public enum AMD64ConvertOpcode implements LIROpcode { - I2L, L2I, I2B, I2C, I2S, - F2D, D2F, - I2F, I2D, F2I, D2I, - L2F, L2D, F2L, D2L, - MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L; - - public LIRInstruction create(CiValue result, CiValue x) { - CiValue[] inputs = new CiValue[] {x}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - emit(tasm, masm, output(0), input(0)); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - return super.flagsFor(mode, index); - } - }; - } - - private void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue x) { - switch (this) { - case L2I: - AMD64MoveOpcode.move(tasm, masm, result, x); - masm.andl(asIntReg(result), 0xFFFFFFFF); - break; - case I2B: - AMD64MoveOpcode.move(tasm, masm, result, x); - masm.signExtendByte(asIntReg(result)); - break; - case I2C: - AMD64MoveOpcode.move(tasm, masm, result, x); - masm.andl(asIntReg(result), 0xFFFF); - break; - case I2S: - AMD64MoveOpcode.move(tasm, masm, result, x); - masm.signExtendShort(asIntReg(result)); - break; - case I2L: masm.movslq(asLongReg(result), asIntReg(x)); break; - case F2D: masm.cvtss2sd(asDoubleReg(result), asFloatReg(x)); break; - case D2F: masm.cvtsd2ss(asFloatReg(result), asDoubleReg(x)); break; - case I2F: masm.cvtsi2ssl(asFloatReg(result), asIntReg(x)); break; - case I2D: masm.cvtsi2sdl(asDoubleReg(result), asIntReg(x)); break; - case L2F: masm.cvtsi2ssq(asFloatReg(result), asLongReg(x)); break; - case L2D: masm.cvtsi2sdq(asDoubleReg(result), asLongReg(x)); break; - case F2I: - masm.cvttss2sil(asIntReg(result), asFloatReg(x)); - emitFixup(tasm, masm, result, x); - break; - case D2I: - masm.cvttsd2sil(asIntReg(result), asDoubleReg(x)); - emitFixup(tasm, masm, result, x); - break; - case F2L: - masm.cvttss2siq(asLongReg(result), asFloatReg(x)); - emitFixup(tasm, masm, result, x); - break; - case D2L: - masm.cvttsd2siq(asLongReg(result), asDoubleReg(x)); - emitFixup(tasm, masm, result, x); - break; - case MOV_I2F: masm.movdl(asFloatReg(result), asIntReg(x)); break; - case MOV_L2D: masm.movdq(asDoubleReg(result), asLongReg(x)); break; - case MOV_F2I: masm.movdl(asIntReg(result), asFloatReg(x)); break; - case MOV_D2L: masm.movdq(asLongReg(result), asDoubleReg(x)); break; - default: throw Util.shouldNotReachHere(); - } - } - - private static void emitFixup(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue x) { - FixupSlowPath slowPath = new FixupSlowPath(result, x); - tasm.slowPaths.add(slowPath); - switch (result.kind) { - case Int: masm.cmpl(asIntReg(result), Integer.MIN_VALUE); break; - case Long: masm.cmpq(asLongReg(result), tasm.asLongConstRef(CiConstant.forLong(java.lang.Long.MIN_VALUE))); break; - default: throw Util.shouldNotReachHere(); - } - masm.jcc(ConditionFlag.equal, slowPath.start); - masm.bind(slowPath.continuation); - } - - private static class FixupSlowPath extends AMD64SlowPath { - public final Label start = new Label(); - public final Label continuation = new Label(); - private final CiValue result; - private final CiValue x; - - public FixupSlowPath(CiValue result, CiValue x) { - this.result = result; - this.x = x; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.bind(start); - switch (x.kind) { - case Float: masm.ucomiss(asFloatReg(x), tasm.asFloatConstRef(CiConstant.FLOAT_0)); break; - case Double: masm.ucomisd(asDoubleReg(x), tasm.asDoubleConstRef(CiConstant.DOUBLE_0)); break; - default: throw Util.shouldNotReachHere(); - } - Label nan = new Label(); - masm.jcc(ConditionFlag.parity, nan); - masm.jcc(ConditionFlag.below, continuation); - - // input is > 0 -> return maxInt - // result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff - switch (result.kind) { - case Int: masm.decrementl(asIntReg(result), 1); break; - case Long: masm.decrementq(asLongReg(result), 1); break; - default: throw Util.shouldNotReachHere(); - } - masm.jmp(continuation); - - // input is NaN -> return 0 - masm.bind(nan); - masm.xorptr(asRegister(result), asRegister(result)); - masm.jmp(continuation); - } - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64DeoptimizationStub.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64DeoptimizationStub.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64DeoptimizationStub.java Thu Jan 26 12:23:00 2012 +0100 @@ -57,9 +57,9 @@ if (GraalOptions.CreateDeoptInfo && deoptInfo != null) { masm.nop(); keepAlive.add(deoptInfo.toString()); - AMD64MoveOpcode.move(tasm, masm, scratch.asValue(), CiConstant.forObject(deoptInfo)); + AMD64Move.move(tasm, masm, scratch.asValue(), CiConstant.forObject(deoptInfo)); // TODO Why use scratch register here? Is it an implicit calling convention that the runtime function reads this register? - AMD64CallOpcode.directCall(tasm, masm, CiRuntimeCall.SetDeoptInfo, info); + AMD64Call.directCall(tasm, masm, CiRuntimeCall.SetDeoptInfo, info); } int code; switch(action) { @@ -83,7 +83,7 @@ } masm.movq(scratch, code); // TODO Why use scratch register here? Is it an implicit calling convention that the runtime function reads this register? - AMD64CallOpcode.directCall(tasm, masm, CiRuntimeCall.Deoptimize, info); - AMD64CallOpcode.shouldNotReachHere(tasm, masm); + AMD64Call.directCall(tasm, masm, CiRuntimeCall.Deoptimize, info); + AMD64Call.shouldNotReachHere(tasm, masm); } } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64DivOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64DivOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import com.oracle.max.asm.*; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public enum AMD64DivOpcode implements LIROpcode { - IDIV, IREM, IUDIV, IUREM, - LDIV, LREM, LUDIV, LUREM; - - public LIRInstruction create(CiValue result, LIRDebugInfo info, CiValue x, CiValue y) { - CiValue[] inputs = new CiValue[] {x}; - CiValue[] alives = new CiValue[] {y}; - CiValue[] temps = new CiValue[] {asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.kind) : AMD64.rax.asValue(result.kind)}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, info, inputs, alives, temps) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - emit(tasm, masm, output(0), info, input(0), alive(0)); - } - }; - } - - protected void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, LIRDebugInfo info, CiValue x, CiValue y) { - // left input in rax, right input in any register but rax and rdx, result quotient in rax, result remainder in rdx - assert asRegister(x) == AMD64.rax; - assert differentRegisters(y, AMD64.rax.asValue(), AMD64.rdx.asValue()); - assert (name().endsWith("DIV") && asRegister(result) == AMD64.rax) || (name().endsWith("REM") && asRegister(result) == AMD64.rdx); - - int exceptionOffset; - switch (this) { - case IDIV: - case IREM: - masm.cdql(); - exceptionOffset = masm.codeBuffer.position(); - masm.idivl(asRegister(y)); - break; - - case LDIV: - case LREM: - Label continuation = new Label(); - if (this == LDIV) { - // check for special case of Long.MIN_VALUE / -1 - Label normalCase = new Label(); - masm.movq(AMD64.rdx, java.lang.Long.MIN_VALUE); - masm.cmpq(AMD64.rax, AMD64.rdx); - masm.jcc(ConditionFlag.notEqual, normalCase); - masm.cmpl(asRegister(y), -1); - masm.jcc(ConditionFlag.equal, continuation); - masm.bind(normalCase); - } - - masm.cdqq(); - exceptionOffset = masm.codeBuffer.position(); - masm.idivq(asRegister(y)); - masm.bind(continuation); - break; - - case IUDIV: - case IUREM: - // Must zero the high 64-bit word (in RDX) of the dividend - masm.xorq(AMD64.rdx, AMD64.rdx); - exceptionOffset = masm.codeBuffer.position(); - masm.divl(asRegister(y)); - break; - - case LUDIV: - case LUREM: - // Must zero the high 64-bit word (in RDX) of the dividend - masm.xorq(AMD64.rdx, AMD64.rdx); - exceptionOffset = masm.codeBuffer.position(); - masm.divq(asRegister(y)); - break; - - default: - throw Util.shouldNotReachHere(); - } - tasm.recordImplicitException(exceptionOffset, info); - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Thu Jan 26 12:23:00 2012 +0100 @@ -23,26 +23,33 @@ package com.oracle.max.graal.compiler.target.amd64; +import com.oracle.max.graal.compiler.target.amd64.AMD64Call.*; import static com.oracle.max.cri.ci.CiValueUtil.*; -import static com.oracle.max.graal.compiler.target.amd64.AMD64ArithmeticOpcode.*; -import static com.oracle.max.graal.compiler.target.amd64.AMD64CompareOpcode.*; +import static com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.*; +import static com.oracle.max.graal.compiler.target.amd64.AMD64Compare.*; import static com.oracle.max.graal.compiler.target.amd64.AMD64CompareToIntOpcode.*; -import static com.oracle.max.graal.compiler.target.amd64.AMD64ConvertOpcode.*; -import static com.oracle.max.graal.compiler.target.amd64.AMD64DivOpcode.*; -import static com.oracle.max.graal.compiler.target.amd64.AMD64LogicFloatOpcode.*; -import static com.oracle.max.graal.compiler.target.amd64.AMD64MulOpcode.*; -import static com.oracle.max.graal.compiler.target.amd64.AMD64Op1Opcode.*; -import static com.oracle.max.graal.compiler.target.amd64.AMD64ShiftOpcode.*; -import static com.oracle.max.graal.compiler.target.amd64.AMD64StandardOpcode.*; +import static com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.*; + +import java.util.*; import com.oracle.max.asm.*; import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiTargetMethod.*; import com.oracle.max.cri.ri.*; import com.oracle.max.cri.xir.*; +import com.oracle.max.cri.xir.CiXirAssembler.*; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.DivOp; +import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op1Reg; +import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op1Stack; +import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op2RegCommutative; +import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op2Stack; +import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.ShiftOp; +import com.oracle.max.graal.compiler.target.amd64.AMD64Compare.CompareOp; +import com.oracle.max.graal.compiler.target.amd64.AMD64Move.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction; @@ -62,20 +69,23 @@ private static final CiRegisterValue RDX_L = AMD64.rdx.asValue(CiKind.Long); private static final CiRegisterValue RCX_I = AMD64.rcx.asValue(CiKind.Int); - static { - StandardOpcode.SPILL_MOVE = AMD64MoveOpcode.SpillMoveOpcode.SPILL_MOVE; - StandardOpcode.NULL_CHECK = AMD64StandardOpcode.NULL_CHECK; - StandardOpcode.DIRECT_CALL = AMD64CallOpcode.DIRECT_CALL; - StandardOpcode.INDIRECT_CALL = AMD64CallOpcode.INDIRECT_CALL; - StandardOpcode.LABEL = AMD64StandardOpcode.LABEL; - StandardOpcode.JUMP = AMD64StandardOpcode.JUMP; - StandardOpcode.RETURN = AMD64StandardOpcode.RETURN; - StandardOpcode.XIR = AMD64XirOpcode.XIR; + public static class AMD64SpillMoveFactory implements LIR.SpillMoveFactory { + @Override + public LIRInstruction createMove(CiValue result, CiValue input) { + return new SpillMoveOp(result, input); + } + + @Override + public LIRInstruction createExchange(CiValue input1, CiValue input2) { + // TODO implement XCHG operation for LIR + return null; + } } public AMD64LIRGenerator(GraalContext context, Graph graph, RiRuntime runtime, CiTarget target, FrameMap frameMap, RiResolvedMethod method, LIR lir, RiXirGenerator xir) { super(context, graph, runtime, target, frameMap, method, lir, xir); lir.methodEndMarker = new AMD64MethodEndStub(); + lir.spillMoveFactory = new AMD64SpillMoveFactory(); } @Override @@ -144,43 +154,47 @@ @Override public Variable emitMove(CiValue input) { Variable result = newVariable(input.kind); - append(MOVE.create(result, input)); + emitMove(input, result); return result; } @Override public void emitMove(CiValue src, CiValue dst) { - append(MOVE.create(dst, src)); + if (isRegister(src) || isStackSlot(dst)) { + append(new MoveFromRegOp(dst, src)); + } else { + append(new MoveToRegOp(dst, src)); + } } @Override public Variable emitLoad(CiValue loadAddress, boolean canTrap) { Variable result = newVariable(loadAddress.kind); - append(LOAD.create(result, loadAddress, canTrap ? state() : null)); + append(new LoadOp(result, loadAddress, canTrap ? state() : null)); return result; } @Override public void emitStore(CiValue storeAddress, CiValue inputVal, boolean canTrap) { CiValue input = loadForStore(inputVal, storeAddress.kind); - append(STORE.create(storeAddress, input, canTrap ? state() : null)); + append(new StoreOp(storeAddress, input, canTrap ? state() : null)); } @Override public Variable emitLea(CiValue address) { Variable result = newVariable(target().wordKind); - append(LEA.create(result, address)); + append(new LeaOp(result, address)); return result; } @Override public void emitLabel(Label label, boolean align) { - append(LABEL.create(label, align)); + append(new LabelOp(label, align)); } @Override public void emitJump(LabelRef label, LIRDebugInfo info) { - append(JUMP.create(label, info)); + append(new JumpOp(label, info)); } @Override @@ -190,9 +204,9 @@ case Boolean: case Int: case Long: - case Object: append(BRANCH.create(cond, label, info)); break; + case Object: append(new BranchOp(cond, label, info)); break; case Float: - case Double: append(FLOAT_BRANCH.create(cond, unorderedIsTrue, label, info)); break; + case Double: append(new FloatBranchOp(cond, unorderedIsTrue, label, info)); break; default: throw Util.shouldNotReachHere("" + left.kind); } } @@ -206,9 +220,9 @@ case Boolean: case Int: case Long: - case Object: append(CMOVE.create(result, cond, load(trueValue), loadNonConst(falseValue))); break; + case Object: append(new CondMoveOp(result, cond, load(trueValue), loadNonConst(falseValue))); break; case Float: - case Double: append(FLOAT_CMOVE.create(result, cond, unorderedIsTrue, load(trueValue), load(falseValue))); break; + case Double: append(new FloatCondMoveOp(result, cond, unorderedIsTrue, load(trueValue), load(falseValue))); break; } return result; @@ -219,11 +233,11 @@ CiValue right = loadNonConst(b); switch (left.kind) { case Jsr: - case Int: append(ICMP.create(left, right)); break; - case Long: append(LCMP.create(left, right)); break; - case Object: append(ACMP.create(left, right)); break; - case Float: append(FCMP.create(left, right)); break; - case Double: append(DCMP.create(left, right)); break; + case Int: append(new CompareOp(ICMP, left, right)); break; + case Long: append(new CompareOp(LCMP, left, right)); break; + case Object: append(new CompareOp(ACMP, left, right)); break; + case Float: append(new CompareOp(FCMP, left, right)); break; + case Double: append(new CompareOp(DCMP, left, right)); break; default: throw Util.shouldNotReachHere(); } } @@ -232,10 +246,10 @@ public Variable emitNegate(CiValue input) { Variable result = newVariable(input.kind); switch (input.kind) { - case Int: append(INEG.create(result, input)); break; - case Long: append(LNEG.create(result, input)); break; - case Float: append(FXOR.create(result, input, CiConstant.forFloat(Float.intBitsToFloat(0x80000000)))); break; - case Double: append(DXOR.create(result, input, CiConstant.forDouble(Double.longBitsToDouble(0x8000000000000000L)))); break; + case Int: append(new Op1Stack(INEG, result, input)); break; + case Long: append(new Op1Stack(LNEG, result, input)); break; + case Float: append(new Op2RegCommutative(FXOR, result, input, CiConstant.forFloat(Float.intBitsToFloat(0x80000000)))); break; + case Double: append(new Op2RegCommutative(DXOR, result, input, CiConstant.forDouble(Double.longBitsToDouble(0x8000000000000000L)))); break; default: throw Util.shouldNotReachHere(); } return result; @@ -245,10 +259,10 @@ public Variable emitAdd(CiValue a, CiValue b) { Variable result = newVariable(a.kind); switch(a.kind) { - case Int: append(IADD.create(result, a, loadNonConst(b))); break; - case Long: append(LADD.create(result, a, loadNonConst(b))); break; - case Float: append(FADD.create(result, a, loadNonConst(b))); break; - case Double: append(DADD.create(result, a, loadNonConst(b))); break; + case Int: append(new Op2Stack(IADD, result, a, loadNonConst(b))); break; + case Long: append(new Op2Stack(LADD, result, a, loadNonConst(b))); break; + case Float: append(new Op2Stack(FADD, result, a, loadNonConst(b))); break; + case Double: append(new Op2Stack(DADD, result, a, loadNonConst(b))); break; default: throw Util.shouldNotReachHere(); } return result; @@ -258,10 +272,10 @@ public Variable emitSub(CiValue a, CiValue b) { Variable result = newVariable(a.kind); switch(a.kind) { - case Int: append(ISUB.create(result, a, loadNonConst(b))); break; - case Long: append(LSUB.create(result, a, loadNonConst(b))); break; - case Float: append(FSUB.create(result, a, loadNonConst(b))); break; - case Double: append(DSUB.create(result, a, loadNonConst(b))); break; + case Int: append(new Op2Stack(ISUB, result, a, loadNonConst(b))); break; + case Long: append(new Op2Stack(LSUB, result, a, loadNonConst(b))); break; + case Float: append(new Op2Stack(FSUB, result, a, loadNonConst(b))); break; + case Double: append(new Op2Stack(DSUB, result, a, loadNonConst(b))); break; default: throw Util.shouldNotReachHere(); } return result; @@ -271,10 +285,10 @@ public Variable emitMul(CiValue a, CiValue b) { Variable result = newVariable(a.kind); switch(a.kind) { - case Int: append(IMUL.create(result, a, loadNonConst(b))); break; - case Long: append(LMUL.create(result, a, loadNonConst(b))); break; - case Float: append(FMUL.create(result, a, loadNonConst(b))); break; - case Double: append(DMUL.create(result, a, loadNonConst(b))); break; + case Int: append(new Op2RegCommutative(IMUL, result, a, loadNonConst(b))); break; + case Long: append(new Op2RegCommutative(LMUL, result, a, loadNonConst(b))); break; + case Float: append(new Op2Stack(FMUL, result, a, loadNonConst(b))); break; + case Double: append(new Op2Stack(DMUL, result, a, loadNonConst(b))); break; default: throw Util.shouldNotReachHere(); } return result; @@ -284,21 +298,21 @@ public Variable emitDiv(CiValue a, CiValue b) { switch(a.kind) { case Int: - append(MOVE.create(RAX_I, a)); - append(IDIV.create(RAX_I, state(), RAX_I, load(b))); + emitMove(a, RAX_I); + append(new DivOp(IDIV, RAX_I, RAX_I, load(b), state())); return emitMove(RAX_I); case Long: - append(MOVE.create(RAX_L, a)); - append(LDIV.create(RAX_L, state(), RAX_L, load(b))); + emitMove(a, RAX_L); + append(new DivOp(LDIV, RAX_L, RAX_L, load(b), state())); return emitMove(RAX_L); case Float: { Variable result = newVariable(a.kind); - append(FDIV.create(result, a, loadNonConst(b))); + append(new Op2Stack(FDIV, result, a, loadNonConst(b))); return result; } case Double: { Variable result = newVariable(a.kind); - append(DDIV.create(result, a, loadNonConst(b))); + append(new Op2Stack(DDIV, result, a, loadNonConst(b))); return result; } default: @@ -310,12 +324,12 @@ public Variable emitRem(CiValue a, CiValue b) { switch(a.kind) { case Int: - append(MOVE.create(RAX_I, a)); - append(IREM.create(RDX_I, state(), RAX_I, load(b))); + emitMove(a, RAX_I); + append(new DivOp(IREM, RDX_I, RAX_I, load(b), state())); return emitMove(RDX_I); case Long: - append(MOVE.create(RAX_L, a)); - append(LREM.create(RDX_L, state(), RAX_L, load(b))); + emitMove(a, RAX_L); + append(new DivOp(LREM, RDX_L, RAX_L, load(b), state())); return emitMove(RDX_L); case Float: return emitCallToRuntime(CiRuntimeCall.ArithmeticFrem, false, a, b); @@ -330,12 +344,12 @@ public Variable emitUDiv(CiValue a, CiValue b) { switch(a.kind) { case Int: - append(MOVE.create(RAX_I, load(a))); - append(IUDIV.create(RAX_I, state(), RAX_I, load(b))); + emitMove(a, RAX_I); + append(new DivOp(IUDIV, RAX_I, RAX_I, load(b), state())); return emitMove(RAX_I); case Long: - append(MOVE.create(RAX_L, load(a))); - append(LUDIV.create(RAX_L, state(), RAX_L, load(b))); + emitMove(a, RAX_L); + append(new DivOp(LUDIV, RAX_L, RAX_L, load(b), state())); return emitMove(RAX_L); default: throw Util.shouldNotReachHere(); @@ -346,12 +360,12 @@ public Variable emitURem(CiValue a, CiValue b) { switch(a.kind) { case Int: - append(MOVE.create(RAX_I, load(a))); - append(IUREM.create(RDX_I, state(), RAX_I, load(b))); + emitMove(a, RAX_I); + append(new DivOp(IUREM, RDX_I, RAX_I, load(b), state())); return emitMove(RDX_I); case Long: - append(MOVE.create(RAX_L, load(a))); - append(LUREM.create(RDX_L, state(), RAX_L, load(b))); + emitMove(a, RAX_L); + append(new DivOp(LUREM, RDX_L, RAX_L, load(b), state())); return emitMove(RDX_L); default: throw Util.shouldNotReachHere(); @@ -363,8 +377,8 @@ public Variable emitAnd(CiValue a, CiValue b) { Variable result = newVariable(a.kind); switch(a.kind) { - case Int: append(IAND.create(result, a, loadNonConst(b))); break; - case Long: append(LAND.create(result, a, loadNonConst(b))); break; + case Int: append(new Op2Stack(IAND, result, a, loadNonConst(b))); break; + case Long: append(new Op2Stack(LAND, result, a, loadNonConst(b))); break; default: throw Util.shouldNotReachHere(); } return result; @@ -374,8 +388,8 @@ public Variable emitOr(CiValue a, CiValue b) { Variable result = newVariable(a.kind); switch(a.kind) { - case Int: append(IOR.create(result, a, loadNonConst(b))); break; - case Long: append(LOR.create(result, a, loadNonConst(b))); break; + case Int: append(new Op2Stack(IOR, result, a, loadNonConst(b))); break; + case Long: append(new Op2Stack(LOR, result, a, loadNonConst(b))); break; default: throw Util.shouldNotReachHere(); } return result; @@ -385,8 +399,8 @@ public Variable emitXor(CiValue a, CiValue b) { Variable result = newVariable(a.kind); switch(a.kind) { - case Int: append(IXOR.create(result, a, loadNonConst(b))); break; - case Long: append(LXOR.create(result, a, loadNonConst(b))); break; + case Int: append(new Op2Stack(IXOR, result, a, loadNonConst(b))); break; + case Long: append(new Op2Stack(LXOR, result, a, loadNonConst(b))); break; default: throw Util.shouldNotReachHere(); } return result; @@ -397,8 +411,8 @@ public Variable emitShl(CiValue a, CiValue b) { Variable result = newVariable(a.kind); switch (a.kind) { - case Int: append(ISHL.create(result, a, loadShiftCount(b))); break; - case Long: append(LSHL.create(result, a, loadShiftCount(b))); break; + case Int: append(new ShiftOp(ISHL, result, a, loadShiftCount(b))); break; + case Long: append(new ShiftOp(LSHL, result, a, loadShiftCount(b))); break; default: Util.shouldNotReachHere(); } return result; @@ -408,8 +422,8 @@ public Variable emitShr(CiValue a, CiValue b) { Variable result = newVariable(a.kind); switch (a.kind) { - case Int: append(ISHR.create(result, a, loadShiftCount(b))); break; - case Long: append(LSHR.create(result, a, loadShiftCount(b))); break; + case Int: append(new ShiftOp(ISHR, result, a, loadShiftCount(b))); break; + case Long: append(new ShiftOp(LSHR, result, a, loadShiftCount(b))); break; default: Util.shouldNotReachHere(); } return result; @@ -419,8 +433,8 @@ public Variable emitUShr(CiValue a, CiValue b) { Variable result = newVariable(a.kind); switch (a.kind) { - case Int: append(IUSHR.create(result, a, loadShiftCount(b))); break; - case Long: append(LUSHR.create(result, a, loadShiftCount(b))); break; + case Int: append(new ShiftOp(IUSHR, result, a, loadShiftCount(b))); break; + case Long: append(new ShiftOp(LUSHR, result, a, loadShiftCount(b))); break; default: Util.shouldNotReachHere(); } return result; @@ -431,7 +445,7 @@ return value; } // Non-constant shift count must be in RCX - append(MOVE.create(RCX_I, value)); + emitMove(value, RCX_I); return RCX_I; } @@ -441,25 +455,25 @@ Variable input = load(inputVal); Variable result = newVariable(opcode.to); switch (opcode) { - case I2L: append(I2L.create(result, input)); break; - case L2I: append(L2I.create(result, input)); break; - case I2B: append(I2B.create(result, input)); break; - case I2C: append(I2C.create(result, input)); break; - case I2S: append(I2S.create(result, input)); break; - case F2D: append(F2D.create(result, input)); break; - case D2F: append(D2F.create(result, input)); break; - case I2F: append(I2F.create(result, input)); break; - case I2D: append(I2D.create(result, input)); break; - case F2I: append(F2I.create(result, input)); break; - case D2I: append(D2I.create(result, input)); break; - case L2F: append(L2F.create(result, input)); break; - case L2D: append(L2D.create(result, input)); break; - case F2L: append(F2L.create(result, input)); break; - case D2L: append(D2L.create(result, input)); break; - case MOV_I2F: append(MOV_I2F.create(result, input)); break; - case MOV_L2D: append(MOV_L2D.create(result, input)); break; - case MOV_F2I: append(MOV_F2I.create(result, input)); break; - case MOV_D2L: append(MOV_D2L.create(result, input)); break; + case I2L: append(new Op1Reg(I2L, result, input)); break; + case L2I: append(new Op1Stack(L2I, result, input)); break; + case I2B: append(new Op1Stack(I2B, result, input)); break; + case I2C: append(new Op1Stack(I2C, result, input)); break; + case I2S: append(new Op1Stack(I2S, result, input)); break; + case F2D: append(new Op1Reg(F2D, result, input)); break; + case D2F: append(new Op1Reg(D2F, result, input)); break; + case I2F: append(new Op1Reg(I2F, result, input)); break; + case I2D: append(new Op1Reg(I2D, result, input)); break; + case F2I: append(new Op1Reg(F2I, result, input)); break; + case D2I: append(new Op1Reg(D2I, result, input)); break; + case L2F: append(new Op1Reg(L2F, result, input)); break; + case L2D: append(new Op1Reg(L2D, result, input)); break; + case F2L: append(new Op1Reg(F2L, result, input)); break; + case D2L: append(new Op1Reg(D2L, result, input)); break; + case MOV_I2F: append(new Op1Reg(MOV_I2F, result, input)); break; + case MOV_L2D: append(new Op1Reg(MOV_L2D, result, input)); break; + case MOV_F2I: append(new Op1Reg(MOV_F2I, result, input)); break; + case MOV_D2L: append(new Op1Reg(MOV_D2L, result, input)); break; default: throw Util.shouldNotReachHere(); } return result; @@ -471,9 +485,9 @@ LIRDebugInfo info = state(); LabelRef stubEntry = createDeoptStub(action, info, deoptInfo); if (cond != null) { - append(BRANCH.create(cond, stubEntry, info)); + append(new BranchOp(cond, stubEntry, info)); } else { - append(JUMP.create(stubEntry, info)); + append(new JumpOp(stubEntry, info)); } } @@ -481,15 +495,36 @@ public void emitMembar(int barriers) { int necessaryBarriers = target.arch.requiredBarriers(barriers); if (target.isMP && necessaryBarriers != 0) { - append(MEMBAR.create(necessaryBarriers)); + append(new MembarOp(necessaryBarriers)); + } + } + + @Override + protected void emitCall(Object targetMethod, CiValue result, List arguments, CiValue targetAddress, LIRDebugInfo info, Map marks) { + if (isConstant(targetAddress)) { + assert asConstant(targetAddress).isDefaultValue() : "destination address should be zero"; + append(new DirectCallOp(targetMethod, result, arguments.toArray(new CiValue[arguments.size()]), info, marks)); + } else { + append(new IndirectCallOp(targetMethod, result, arguments.toArray(new CiValue[arguments.size()]), targetAddress, info, marks)); } } @Override + protected void emitReturn(CiValue input) { + append(new ReturnOp(input)); + } + + @Override + protected void emitXir(XirSnippet snippet, CiValue[] operands, CiValue outputOperand, CiValue[] inputs, CiValue[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex, + LIRDebugInfo info, LIRDebugInfo infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) { + append(new AMD64XirOp(snippet, operands, outputOperand, inputs, temps, inputOperandIndices, tempOperandIndices, outputOperandIndex, info, infoAfter, trueSuccessor, falseSuccessor)); + } + + @Override protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, CiValue index) { // Making a copy of the switch value is necessary because jump table destroys the input value Variable tmp = emitMove(index); - append(TABLE_SWITCH.create(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind))); + append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind))); } @Override @@ -500,6 +535,14 @@ return LabelRef.forLabel(stub.label); } + @Override + protected void emitNullCheckGuard(NullCheckNode node) { + assert !node.expectedNull; + Variable value = load(operand(node.object())); + LIRDebugInfo info = state(); + append(new NullCheckOp(value, info)); + } + // TODO The CompareAndSwapNode in its current form needs to be lowered to several Nodes before code generation to separate three parts: // * The write barriers (and possibly read barriers) when accessing an object field // * The distinction of returning a boolean value (semantic similar to a BooleanNode to be used as a condition?) or the old value being read @@ -526,14 +569,14 @@ } CiRegisterValue rax = AMD64.rax.asValue(kind); - append(MOVE.create(rax, expected)); - append(CAS.create(rax, address, rax, newValue)); + emitMove(expected, rax); + append(new CompareAndSwapOp(rax, address, rax, newValue)); Variable result = newVariable(node.kind()); if (node.directResult()) { - append(MOVE.create(result, rax)); + emitMove(rax, result); } else { - append(CMOVE.create(result, Condition.EQ, load(CiConstant.TRUE), CiConstant.FALSE)); + append(new CondMoveOp(result, Condition.EQ, load(CiConstant.TRUE), CiConstant.FALSE)); } setResult(node, result); diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRInstruction.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRInstruction.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRInstruction.java Thu Jan 26 12:23:00 2012 +0100 @@ -32,7 +32,7 @@ */ public abstract class AMD64LIRInstruction extends LIRInstruction { - public AMD64LIRInstruction(LIROpcode opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { + public AMD64LIRInstruction(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { super(opcode, outputs, info, inputs, alives, temps); } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LogicFloatOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LogicFloatOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public enum AMD64LogicFloatOpcode implements LIROpcode { - FAND, FOR, FXOR, - DAND, DOR, DXOR; - - public LIRInstruction create(CiValue result, CiValue x, CiValue y) { - assert (name().startsWith("F") && result.kind == CiKind.Float && x.kind == CiKind.Float && y.kind == CiKind.Float) - || (name().startsWith("D") && result.kind == CiKind.Double && x.kind == CiKind.Double && y.kind == CiKind.Double); - - CiValue[] inputs = new CiValue[] {x}; - CiValue[] alives = new CiValue[] {y}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, null, inputs, alives, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - emit(tasm, masm, output(0), input(0), alive(0)); - } - - @Override - public EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Alive && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - return super.flagsFor(mode, index); - } - }; - } - - protected void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue x, CiValue y) { - assert sameRegister(x, y) || differentRegisters(result, y); - AMD64MoveOpcode.move(tasm, masm, result, x); - - CiRegister dst = asRegister(result); - if (isRegister(y)) { - CiRegister rreg = asRegister(y); - switch (this) { - case FAND: masm.andps(dst, rreg); break; - case FOR: masm.orps(dst, rreg); break; - case FXOR: masm.xorps(dst, rreg); break; - case DAND: masm.andpd(dst, rreg); break; - case DOR: masm.orpd(dst, rreg); break; - case DXOR: masm.xorpd(dst, rreg); break; - default: throw Util.shouldNotReachHere(); - } - } else { - switch (this) { - case FAND: masm.andps(dst, tasm.asFloatConstRef(y, 16)); break; - case FOR: masm.orps(dst, tasm.asFloatConstRef(y, 16)); break; - case FXOR: masm.xorps(dst, tasm.asFloatConstRef(y, 16)); break; - case DAND: masm.andpd(dst, tasm.asDoubleConstRef(y, 16)); break; - case DOR: masm.orpd(dst, tasm.asDoubleConstRef(y, 16)); break; - case DXOR: masm.xorpd(dst, tasm.asDoubleConstRef(y, 16)); break; - default: throw Util.shouldNotReachHere(); - } - } - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Move.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Move.java Thu Jan 26 12:23:00 2012 +0100 @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.target.amd64; + +import static com.oracle.max.cri.ci.CiValueUtil.*; +import static java.lang.Double.*; +import static java.lang.Float.*; + +import java.util.*; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.compiler.asm.*; +import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.lir.StandardOp.MoveOp; +import com.oracle.max.graal.compiler.util.*; + +public class AMD64Move { + + public static class SpillMoveOp extends AMD64LIRInstruction implements MoveOp { + public SpillMoveOp(CiValue result, CiValue input) { + super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + move(tasm, masm, getResult(), getInput()); + } + + @Override + public CiValue getInput() { + return input(0); + } + @Override + public CiValue getResult() { + return output(0); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + } + throw Util.shouldNotReachHere(); + } + } + + + public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp { + public MoveToRegOp(CiValue result, CiValue input) { + super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + move(tasm, masm, getResult(), getInput()); + } + + @Override + public CiValue getInput() { + return input(0); + } + @Override + public CiValue getResult() { + return output(0); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + throw Util.shouldNotReachHere(); + } + } + + + public static class MoveFromRegOp extends AMD64LIRInstruction implements MoveOp { + public MoveFromRegOp(CiValue result, CiValue input) { + super("MOVE", new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + move(tasm, masm, getResult(), getInput()); + } + + @Override + public CiValue getInput() { + return input(0); + } + @Override + public CiValue getResult() { + return output(0); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.RegisterHint); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + } + throw Util.shouldNotReachHere(); + } + } + + + public static class LoadOp extends AMD64LIRInstruction { + public LoadOp(CiValue result, CiValue address, LIRDebugInfo info) { + super("LOAD", new CiValue[] {result}, info, new CiValue[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + load(tasm, masm, output(0), (CiAddress) input(0), info); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Address); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register); + } + throw Util.shouldNotReachHere(); + } + } + + + public static class StoreOp extends AMD64LIRInstruction { + public StoreOp(CiValue address, CiValue input, LIRDebugInfo info) { + super("STORE", LIRInstruction.NO_OPERANDS, info, new CiValue[] {address, input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + store(tasm, masm, (CiAddress) input(0), input(1), info); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Address); + } else if (mode == OperandMode.Input && index == 1) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); + } + throw Util.shouldNotReachHere(); + } + } + + + public static class LeaOp extends AMD64LIRInstruction { + public LeaOp(CiValue result, CiValue address) { + super("LEA", new CiValue[] {result}, null, new CiValue[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + masm.leaq(asLongReg(output(0)), tasm.asAddress(input(0))); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Address, OperandFlag.Stack, OperandFlag.Uninitialized); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register); + } + throw Util.shouldNotReachHere(); + } + } + + + public static class MembarOp extends AMD64LIRInstruction { + private final int barriers; + + public MembarOp(final int barriers) { + super("MEMBAR", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + this.barriers = barriers; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + masm.membar(barriers); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + throw Util.shouldNotReachHere(); + } + } + + + public static class NullCheckOp extends AMD64LIRInstruction { + public NullCheckOp(Variable input, LIRDebugInfo info) { + super("NULL_CHECK", LIRInstruction.NO_OPERANDS, info, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + tasm.recordImplicitException(masm.codeBuffer.position(), info); + masm.nullCheck(asRegister(input(0))); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register); + } + throw Util.shouldNotReachHere(); + } + } + + + public static class CompareAndSwapOp extends AMD64LIRInstruction { + public CompareAndSwapOp(CiValue result, CiAddress address, CiValue cmpValue, CiValue newValue) { + super("CAS", new CiValue[] {result}, null, new CiValue[] {address, cmpValue, newValue}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + compareAndSwap(tasm, masm, output(0), asAddress(input(0)), input(1), input(2)); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Address); + } else if (mode == OperandMode.Input && index == 1) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Input && index == 2) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register); + } + throw Util.shouldNotReachHere(); + } + } + + + protected static void move(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) { + if (isRegister(input)) { + if (isRegister(result)) { + reg2reg(masm, result, input); + } else if (isStackSlot(result)) { + reg2stack(tasm, masm, result, input); + } else { + throw Util.shouldNotReachHere(); + } + } else if (isStackSlot(input)) { + if (isRegister(result)) { + stack2reg(tasm, masm, result, input); + } else { + throw Util.shouldNotReachHere(); + } + } else if (isConstant(input)) { + if (isRegister(result)) { + const2reg(tasm, masm, result, (CiConstant) input); + } else if (isStackSlot(result)) { + const2stack(tasm, masm, result, (CiConstant) input); + } else { + throw Util.shouldNotReachHere(); + } + } else { + throw Util.shouldNotReachHere(); + } + } + + private static void reg2reg(AMD64MacroAssembler masm, CiValue result, CiValue input) { + if (input.equals(result)) { + return; + } + switch (result.kind) { + case Jsr: + case Int: masm.movl(asRegister(result), asRegister(input)); break; + case Long: masm.movq(asRegister(result), asRegister(input)); break; + case Float: masm.movflt(asFloatReg(result), asFloatReg(input)); break; + case Double: masm.movdbl(asDoubleReg(result), asDoubleReg(input)); break; + case Object: masm.movq(asRegister(result), asRegister(input)); break; + default: throw Util.shouldNotReachHere("kind=" + result.kind); + } + } + + private static void reg2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) { + switch (result.kind) { + case Jsr: + case Int: masm.movl(tasm.asAddress(result), asRegister(input)); break; + case Long: masm.movq(tasm.asAddress(result), asRegister(input)); break; + case Float: masm.movflt(tasm.asAddress(result), asFloatReg(input)); break; + case Double: masm.movsd(tasm.asAddress(result), asDoubleReg(input)); break; + case Object: masm.movq(tasm.asAddress(result), asRegister(input)); break; + default: throw Util.shouldNotReachHere(); + } + } + + private static void stack2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) { + switch (result.kind) { + case Jsr: + case Int: masm.movl(asRegister(result), tasm.asAddress(input)); break; + case Long: masm.movq(asRegister(result), tasm.asAddress(input)); break; + case Float: masm.movflt(asFloatReg(result), tasm.asAddress(input)); break; + case Double: masm.movdbl(asDoubleReg(result), tasm.asAddress(input)); break; + case Object: masm.movq(asRegister(result), tasm.asAddress(input)); break; + default: throw Util.shouldNotReachHere(); + } + } + + private static void const2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiConstant c) { + switch (result.kind) { + case Jsr: + case Int: + // Do not optimize with an XOR as this instruction may be between + // a CMP and a Jcc in which case the XOR will modify the condition + // flags and interfere with the Jcc. + masm.movl(asRegister(result), tasm.asIntConst(c)); + break; + case Long: + // Do not optimize with an XOR as this instruction may be between + // a CMP and a Jcc in which case the XOR will modify the condition + // flags and interfere with the Jcc. + masm.movq(asRegister(result), c.asLong()); + break; + case Float: + // This is *not* the same as 'constant == 0.0f' in the case where constant is -0.0f + if (Float.floatToRawIntBits(c.asFloat()) == Float.floatToRawIntBits(0.0f)) { + masm.xorps(asFloatReg(result), asFloatReg(result)); + } else { + masm.movflt(asFloatReg(result), tasm.asFloatConstRef(c)); + } + break; + case Double: + // This is *not* the same as 'constant == 0.0d' in the case where constant is -0.0d + if (Double.doubleToRawLongBits(c.asDouble()) == Double.doubleToRawLongBits(0.0d)) { + masm.xorpd(asDoubleReg(result), asDoubleReg(result)); + } else { + masm.movdbl(asDoubleReg(result), tasm.asDoubleConstRef(c)); + } + break; + case Object: + // Do not optimize with an XOR as this instruction may be between + // a CMP and a Jcc in which case the XOR will modify the condition + // flags and interfere with the Jcc. + if (c.isNull()) { + masm.movq(asRegister(result), 0x0L); + } else if (tasm.target.inlineObjects) { + tasm.recordDataReferenceInCode(c, 0); + masm.movq(asRegister(result), 0xDEADDEADDEADDEADL); + } else { + masm.movq(asRegister(result), tasm.recordDataReferenceInCode(c, 0)); + } + break; + default: + throw Util.shouldNotReachHere(); + } + } + + private static void const2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiConstant c) { + switch (result.kind) { + case Jsr: + case Int: masm.movl(tasm.asAddress(result), c.asInt()); break; + case Long: masm.movlong(tasm.asAddress(result), c.asLong()); break; + case Float: masm.movl(tasm.asAddress(result), floatToRawIntBits(c.asFloat())); break; + case Double: masm.movlong(tasm.asAddress(result), doubleToRawLongBits(c.asDouble())); break; + case Object: + if (c.isNull()) { + masm.movlong(tasm.asAddress(result), 0L); + } else { + throw Util.shouldNotReachHere("Non-null object constants must be in register"); + } + break; + default: + throw Util.shouldNotReachHere(); + } + } + + + protected static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiAddress loadAddr, LIRDebugInfo info) { + if (info != null) { + tasm.recordImplicitException(masm.codeBuffer.position(), info); + } + switch (loadAddr.kind) { + case Boolean: + case Byte: masm.movsxb(asRegister(result), loadAddr); break; + case Char: masm.movzxl(asRegister(result), loadAddr); break; + case Short: masm.movswl(asRegister(result), loadAddr); break; + case Int: masm.movslq(asRegister(result), loadAddr); break; + case Long: masm.movq(asRegister(result), loadAddr); break; + case Float: masm.movflt(asFloatReg(result), loadAddr); break; + case Double: masm.movdbl(asDoubleReg(result), loadAddr); break; + case Object: masm.movq(asRegister(result), loadAddr); break; + default: throw Util.shouldNotReachHere(); + } + } + + protected static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiAddress storeAddr, CiValue input, LIRDebugInfo info) { + if (info != null) { + tasm.recordImplicitException(masm.codeBuffer.position(), info); + } + + if (isRegister(input)) { + switch (storeAddr.kind) { + case Boolean: + case Byte: masm.movb(storeAddr, asRegister(input)); break; + case Char: + case Short: masm.movw(storeAddr, asRegister(input)); break; + case Int: masm.movl(storeAddr, asRegister(input)); break; + case Long: masm.movq(storeAddr, asRegister(input)); break; + case Float: masm.movflt(storeAddr, asFloatReg(input)); break; + case Double: masm.movsd(storeAddr, asDoubleReg(input)); break; + case Object: masm.movq(storeAddr, asRegister(input)); break; + default: throw Util.shouldNotReachHere(); + } + } else if (isConstant(input)) { + CiConstant c = (CiConstant) input; + switch (storeAddr.kind) { + case Boolean: + case Byte: masm.movb(storeAddr, c.asInt() & 0xFF); break; + case Char: + case Short: masm.movw(storeAddr, c.asInt() & 0xFFFF); break; + case Jsr: + case Int: masm.movl(storeAddr, c.asInt()); break; + case Long: + if (Util.isInt(c.asLong())) { + masm.movslq(storeAddr, (int) c.asLong()); + } else { + throw Util.shouldNotReachHere("Cannot store 64-bit constants to memory"); + } + break; + case Float: masm.movl(storeAddr, floatToRawIntBits(c.asFloat())); break; + case Double: throw Util.shouldNotReachHere("Cannot store 64-bit constants to memory"); + case Object: + if (c.isNull()) { + masm.movptr(storeAddr, 0); + } else { + throw Util.shouldNotReachHere("Cannot store 64-bit constants to memory"); + } + break; + default: + throw Util.shouldNotReachHere(); + } + + } else { + throw Util.shouldNotReachHere(); + } + } + + protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiAddress address, CiValue cmpValue, CiValue newValue) { + assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax; + + if (tasm.target.isMP) { + masm.lock(); + } + switch (cmpValue.kind) { + case Int: masm.cmpxchgl(asRegister(newValue), address); break; + case Long: + case Object: masm.cmpxchgq(asRegister(newValue), address); break; + default: throw Util.shouldNotReachHere(); + } + } +} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MoveOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MoveOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,511 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - -import static com.oracle.max.graal.alloc.util.ValueUtil.*; -import static java.lang.Double.*; -import static java.lang.Float.*; - -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public class AMD64MoveOpcode { - - public enum MoveOpcode implements LIROpcode { - MOVE; - - public LIRInstruction create(CiValue result, CiValue input) { - assert result.kind == result.kind.stackKind() && result.kind != CiKind.Illegal; - CiValue[] inputs = new CiValue[] {input}; - CiValue[] outputs = new CiValue[] {result}; - - if (isRegister(input) || isStackSlot(result)) { - return new AMD64MoveFromRegInstruction(this, outputs, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } else { - return new AMD64MoveToRegInstruction(this, outputs, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - } - } - - public enum SpillMoveOpcode implements StandardOpcode.MoveOpcode { - SPILL_MOVE; - - @Override - public MoveInstruction create(CiValue result, CiValue input) { - assert result.kind == result.kind.stackKind() && result.kind != CiKind.Illegal; - CiValue[] inputs = new CiValue[] {input}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64SpillMoveInstruction(this, outputs, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); - } - } - - protected static class AMD64SpillMoveInstruction extends MoveInstruction { - public AMD64SpillMoveInstruction(LIROpcode opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { - super(opcode, outputs, info, inputs, alives, temps); - } - - @Override - public void emitCode(TargetMethodAssembler tasm) { - move(tasm, (AMD64MacroAssembler) tasm.asm, getDest(), getSource()); - } - - @Override - public CiValue getSource() { - return input(0); - } - @Override - public CiValue getDest() { - return output(0); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - } - throw Util.shouldNotReachHere(); - } - - } - - protected static class AMD64MoveToRegInstruction extends MoveInstruction { - public AMD64MoveToRegInstruction(LIROpcode opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { - super(opcode, outputs, info, inputs, alives, temps); - } - - @Override - public void emitCode(TargetMethodAssembler tasm) { - move(tasm, (AMD64MacroAssembler) tasm.asm, getDest(), getSource()); - } - - @Override - public CiValue getSource() { - return input(0); - } - @Override - public CiValue getDest() { - return output(0); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - throw Util.shouldNotReachHere(); - } - } - - protected static class AMD64MoveFromRegInstruction extends MoveInstruction { - public AMD64MoveFromRegInstruction(LIROpcode opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { - super(opcode, outputs, info, inputs, alives, temps); - } - - @Override - public void emitCode(TargetMethodAssembler tasm) { - move(tasm, (AMD64MacroAssembler) tasm.asm, getDest(), getSource()); - } - - @Override - public CiValue getSource() { - return input(0); - } - @Override - public CiValue getDest() { - return output(0); - } - - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.RegisterHint); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - } - throw Util.shouldNotReachHere(); - } - } - - public enum LoadOpcode implements LIROpcode { - LOAD; - - public LIRInstruction create(CiValue result, CiValue address, LIRDebugInfo info) { - CiValue[] inputs = new CiValue[] {address}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, info, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - load(tasm, masm, output(0), (CiAddress) input(0), info); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Address); - } - return super.flagsFor(mode, index); - } - }; - } - } - - - public enum StoreOpcode implements LIROpcode { - STORE; - - public LIRInstruction create(CiValue address, CiValue input, LIRDebugInfo info) { - CiValue[] inputs = new CiValue[] {address, input}; - - return new AMD64LIRInstruction(this, LIRInstruction.NO_OPERANDS, info, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - store(tasm, masm, (CiAddress) input(0), input(1), info); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Address); - } else if (mode == OperandMode.Input && index == 1) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); - } - return super.flagsFor(mode, index); - } - }; - } - } - - - public enum LeaOpcode implements LIROpcode { - LEA; - - public LIRInstruction create(CiValue result, CiValue address) { - CiValue[] inputs = new CiValue[] {address}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.leaq(asLongReg(output(0)), tasm.asAddress(input(0))); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Address, OperandFlag.Stack, OperandFlag.Uninitialized); - } - return super.flagsFor(mode, index); - } - }; - } - } - - - public enum MembarOpcode implements LIROpcode { - MEMBAR; - - public LIRInstruction create(final int barriers) { - return new AMD64LIRInstruction(this, LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.membar(barriers); - } - }; - } - } - - - public enum NullCheckOpcode implements StandardOpcode.NullCheckOpcode { - NULL_CHECK; - - @Override - public LIRInstruction create(Variable input, LIRDebugInfo info) { - CiValue[] inputs = new CiValue[] {input}; - - return new AMD64LIRInstruction(this, LIRInstruction.NO_OPERANDS, info, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - tasm.recordImplicitException(masm.codeBuffer.position(), info); - masm.nullCheck(asRegister(input(0))); - } - }; - } - } - - - public enum CompareAndSwapOpcode implements LIROpcode { - CAS; - - public LIRInstruction create(CiValue result, CiAddress address, CiValue cmpValue, CiValue newValue) { - CiValue[] inputs = new CiValue[] {address, cmpValue, newValue}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - compareAndSwap(tasm, masm, output(0), asAddress(input(0)), input(1), input(2)); - } - - @Override - protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Address); - } - return super.flagsFor(mode, index); - } - }; - } - } - - protected static void move(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) { - if (isRegister(input)) { - if (isRegister(result)) { - reg2reg(masm, result, input); - } else if (isStackSlot(result)) { - reg2stack(tasm, masm, result, input); - } else { - throw Util.shouldNotReachHere(); - } - } else if (isStackSlot(input)) { - if (isRegister(result)) { - stack2reg(tasm, masm, result, input); - } else { - throw Util.shouldNotReachHere(); - } - } else if (isConstant(input)) { - if (isRegister(result)) { - const2reg(tasm, masm, result, (CiConstant) input); - } else if (isStackSlot(result)) { - const2stack(tasm, masm, result, (CiConstant) input); - } else { - throw Util.shouldNotReachHere(); - } - } else { - throw Util.shouldNotReachHere(); - } - } - - private static void reg2reg(AMD64MacroAssembler masm, CiValue result, CiValue input) { - if (input.equals(result)) { - return; - } - switch (result.kind) { - case Jsr: - case Int: masm.movl(asRegister(result), asRegister(input)); break; - case Long: masm.movq(asRegister(result), asRegister(input)); break; - case Float: masm.movflt(asFloatReg(result), asFloatReg(input)); break; - case Double: masm.movdbl(asDoubleReg(result), asDoubleReg(input)); break; - case Object: masm.movq(asRegister(result), asRegister(input)); break; - default: throw Util.shouldNotReachHere("kind=" + result.kind); - } - } - - private static void reg2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) { - switch (result.kind) { - case Jsr: - case Int: masm.movl(tasm.asAddress(result), asRegister(input)); break; - case Long: masm.movq(tasm.asAddress(result), asRegister(input)); break; - case Float: masm.movflt(tasm.asAddress(result), asFloatReg(input)); break; - case Double: masm.movsd(tasm.asAddress(result), asDoubleReg(input)); break; - case Object: masm.movq(tasm.asAddress(result), asRegister(input)); break; - default: throw Util.shouldNotReachHere(); - } - } - - private static void stack2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) { - switch (result.kind) { - case Jsr: - case Int: masm.movl(asRegister(result), tasm.asAddress(input)); break; - case Long: masm.movq(asRegister(result), tasm.asAddress(input)); break; - case Float: masm.movflt(asFloatReg(result), tasm.asAddress(input)); break; - case Double: masm.movdbl(asDoubleReg(result), tasm.asAddress(input)); break; - case Object: masm.movq(asRegister(result), tasm.asAddress(input)); break; - default: throw Util.shouldNotReachHere(); - } - } - - private static void const2reg(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiConstant c) { - switch (result.kind) { - case Jsr: - case Int: - // Do not optimize with an XOR as this instruction may be between - // a CMP and a Jcc in which case the XOR will modify the condition - // flags and interfere with the Jcc. - masm.movl(asRegister(result), tasm.asIntConst(c)); - break; - case Long: - // Do not optimize with an XOR as this instruction may be between - // a CMP and a Jcc in which case the XOR will modify the condition - // flags and interfere with the Jcc. - masm.movq(asRegister(result), c.asLong()); - break; - case Float: - // This is *not* the same as 'constant == 0.0f' in the case where constant is -0.0f - if (Float.floatToRawIntBits(c.asFloat()) == Float.floatToRawIntBits(0.0f)) { - masm.xorps(asFloatReg(result), asFloatReg(result)); - } else { - masm.movflt(asFloatReg(result), tasm.asFloatConstRef(c)); - } - break; - case Double: - // This is *not* the same as 'constant == 0.0d' in the case where constant is -0.0d - if (Double.doubleToRawLongBits(c.asDouble()) == Double.doubleToRawLongBits(0.0d)) { - masm.xorpd(asDoubleReg(result), asDoubleReg(result)); - } else { - masm.movdbl(asDoubleReg(result), tasm.asDoubleConstRef(c)); - } - break; - case Object: - // Do not optimize with an XOR as this instruction may be between - // a CMP and a Jcc in which case the XOR will modify the condition - // flags and interfere with the Jcc. - if (c.isNull()) { - masm.movq(asRegister(result), 0x0L); - } else if (tasm.target.inlineObjects) { - tasm.recordDataReferenceInCode(c, 0); - masm.movq(asRegister(result), 0xDEADDEADDEADDEADL); - } else { - masm.movq(asRegister(result), tasm.recordDataReferenceInCode(c, 0)); - } - break; - default: - throw Util.shouldNotReachHere(); - } - } - - private static void const2stack(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiConstant c) { - switch (result.kind) { - case Jsr: - case Int: masm.movl(tasm.asAddress(result), c.asInt()); break; - case Long: masm.movlong(tasm.asAddress(result), c.asLong()); break; - case Float: masm.movl(tasm.asAddress(result), floatToRawIntBits(c.asFloat())); break; - case Double: masm.movlong(tasm.asAddress(result), doubleToRawLongBits(c.asDouble())); break; - case Object: - if (c.isNull()) { - masm.movlong(tasm.asAddress(result), 0L); - } else { - throw Util.shouldNotReachHere("Non-null object constants must be in register"); - } - break; - default: - throw Util.shouldNotReachHere(); - } - } - - - protected static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiAddress loadAddr, LIRDebugInfo info) { - if (info != null) { - tasm.recordImplicitException(masm.codeBuffer.position(), info); - } - switch (loadAddr.kind) { - case Boolean: - case Byte: masm.movsxb(asRegister(result), loadAddr); break; - case Char: masm.movzxl(asRegister(result), loadAddr); break; - case Short: masm.movswl(asRegister(result), loadAddr); break; - case Int: masm.movslq(asRegister(result), loadAddr); break; - case Long: masm.movq(asRegister(result), loadAddr); break; - case Float: masm.movflt(asFloatReg(result), loadAddr); break; - case Double: masm.movdbl(asDoubleReg(result), loadAddr); break; - case Object: masm.movq(asRegister(result), loadAddr); break; - default: throw Util.shouldNotReachHere(); - } - } - - protected static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiAddress storeAddr, CiValue input, LIRDebugInfo info) { - if (info != null) { - tasm.recordImplicitException(masm.codeBuffer.position(), info); - } - - if (isRegister(input)) { - switch (storeAddr.kind) { - case Boolean: - case Byte: masm.movb(storeAddr, asRegister(input)); break; - case Char: - case Short: masm.movw(storeAddr, asRegister(input)); break; - case Int: masm.movl(storeAddr, asRegister(input)); break; - case Long: masm.movq(storeAddr, asRegister(input)); break; - case Float: masm.movflt(storeAddr, asFloatReg(input)); break; - case Double: masm.movsd(storeAddr, asDoubleReg(input)); break; - case Object: masm.movq(storeAddr, asRegister(input)); break; - default: throw Util.shouldNotReachHere(); - } - } else if (isConstant(input)) { - CiConstant c = (CiConstant) input; - switch (storeAddr.kind) { - case Boolean: - case Byte: masm.movb(storeAddr, c.asInt() & 0xFF); break; - case Char: - case Short: masm.movw(storeAddr, c.asInt() & 0xFFFF); break; - case Jsr: - case Int: masm.movl(storeAddr, c.asInt()); break; - case Long: - if (Util.isInt(c.asLong())) { - masm.movslq(storeAddr, (int) c.asLong()); - } else { - throw Util.shouldNotReachHere("Cannot store 64-bit constants to memory"); - } - break; - case Float: masm.movl(storeAddr, floatToRawIntBits(c.asFloat())); break; - case Double: throw Util.shouldNotReachHere("Cannot store 64-bit constants to memory"); - case Object: - if (c.isNull()) { - masm.movptr(storeAddr, 0); - } else { - throw Util.shouldNotReachHere("Cannot store 64-bit constants to memory"); - } - break; - default: - throw Util.shouldNotReachHere(); - } - - } else { - throw Util.shouldNotReachHere(); - } - } - - protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiAddress address, CiValue cmpValue, CiValue newValue) { - assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax; - - if (tasm.target.isMP) { - masm.lock(); - } - switch (cmpValue.kind) { - case Int: masm.cmpxchgl(asRegister(newValue), address); break; - case Long: - case Object: masm.cmpxchgq(asRegister(newValue), address); break; - default: throw Util.shouldNotReachHere(); - } - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MulOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MulOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public enum AMD64MulOpcode implements LIROpcode { - IMUL, LMUL; - - public LIRInstruction create(CiValue result, CiValue x, CiValue y) { - CiValue[] inputs = new CiValue[] {x}; - CiValue[] alives = new CiValue[] {y}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, null, inputs, alives, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - emit(tasm, masm, output(0), input(0), alive(0)); - } - - @Override - public EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Alive && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - return super.flagsFor(mode, index); - } - }; - } - - protected void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue x, CiValue y) { - assert sameRegister(x, y) || differentRegisters(result, y); - AMD64MoveOpcode.move(tasm, masm, result, x); - - CiRegister dst = asRegister(result); - if (isRegister(y)) { - switch (this) { - case IMUL: masm.imull(dst, asRegister(y)); break; - case LMUL: masm.imulq(dst, asRegister(y)); break; - default: throw Util.shouldNotReachHere(); - } - } else { - switch (this) { - case IMUL: masm.imull(dst, dst, tasm.asIntConst(y)); break; - case LMUL: masm.imulq(dst, dst, tasm.asIntConst(y)); break; - default: throw Util.shouldNotReachHere(); - } - } - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Op1Opcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Op1Opcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public enum AMD64Op1Opcode implements LIROpcode { - INEG, LNEG; - - public LIRInstruction create(CiValue result, CiValue x) { - CiValue[] inputs = new CiValue[] {x}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - emit(tasm, masm, output(0), input(0)); - } - - @Override - public EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - return super.flagsFor(mode, index); - } - }; - } - - private void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue x) { - AMD64MoveOpcode.move(tasm, masm, result, x); - switch (this) { - case INEG: masm.negl(asIntReg(result)); break; - case LNEG: masm.negq(asLongReg(result)); break; - default: throw Util.shouldNotReachHere(); - } - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ShiftOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ShiftOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public enum AMD64ShiftOpcode implements LIROpcode { - ISHL, ISHR, IUSHR, - LSHL, LSHR, LUSHR; - - public LIRInstruction create(CiValue result, CiValue x, CiValue y) { - CiValue[] inputs = new CiValue[] {x}; - CiValue[] alives = new CiValue[] {y}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, null, inputs, alives, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - emit(tasm, masm, output(0), input(0), alive(0)); - } - - @Override - public EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); - } else if (mode == OperandMode.Alive && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); - } else if (mode == OperandMode.Output && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); - } - return super.flagsFor(mode, index); - } - }; - } - - protected void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue x, CiValue y) { - assert sameRegister(x, y) || differentRegisters(result, y); - AMD64MoveOpcode.move(tasm, masm, result, x); - - CiRegister dst = asRegister(result); - if (isRegister(y)) { - assert asRegister(y) == AMD64.rcx; - switch (this) { - case ISHL: masm.shll(dst); break; - case ISHR: masm.sarl(dst); break; - case IUSHR: masm.shrl(dst); break; - case LSHL: masm.shlq(dst); break; - case LSHR: masm.sarq(dst); break; - case LUSHR: masm.shrq(dst); break; - default: throw Util.shouldNotReachHere(); - } - } else if (isConstant(y)) { - switch (this) { - case ISHL: masm.shll(dst, tasm.asIntConst(y) & 31); break; - case ISHR: masm.sarl(dst, tasm.asIntConst(y) & 31); break; - case IUSHR: masm.shrl(dst, tasm.asIntConst(y) & 31); break; - case LSHL: masm.shlq(dst, tasm.asIntConst(y) & 63); break; - case LSHR: masm.sarq(dst, tasm.asIntConst(y) & 63); break; - case LUSHR: masm.shrq(dst, tasm.asIntConst(y) & 63); break; - default: throw Util.shouldNotReachHere(); - } - } else { - throw Util.shouldNotReachHere(); - } - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64StandardOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64StandardOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - - -/** - * A collection of AMD64 specific opcodes that is convenient for a static import. - * Since every defined opcode is in its own enum, accessing them without this class is - * more verbose. - */ -public class AMD64StandardOpcode { - public static final AMD64MoveOpcode.MoveOpcode MOVE = AMD64MoveOpcode.MoveOpcode.MOVE; - public static final AMD64MoveOpcode.LoadOpcode LOAD = AMD64MoveOpcode.LoadOpcode.LOAD; - public static final AMD64MoveOpcode.StoreOpcode STORE = AMD64MoveOpcode.StoreOpcode.STORE; - public static final AMD64MoveOpcode.LeaOpcode LEA = AMD64MoveOpcode.LeaOpcode.LEA; - public static final AMD64MoveOpcode.MembarOpcode MEMBAR = AMD64MoveOpcode.MembarOpcode.MEMBAR; - public static final AMD64MoveOpcode.NullCheckOpcode NULL_CHECK = AMD64MoveOpcode.NullCheckOpcode.NULL_CHECK; - public static final AMD64MoveOpcode.CompareAndSwapOpcode CAS = AMD64MoveOpcode.CompareAndSwapOpcode.CAS; - - public static final AMD64ControlFlowOpcode.LabelOpcode LABEL = AMD64ControlFlowOpcode.LabelOpcode.LABEL; - public static final AMD64ControlFlowOpcode.ReturnOpcode RETURN = AMD64ControlFlowOpcode.ReturnOpcode.RETURN; - public static final AMD64ControlFlowOpcode.JumpOpcode JUMP = AMD64ControlFlowOpcode.JumpOpcode.JUMP; - public static final AMD64ControlFlowOpcode.BranchOpcode BRANCH = AMD64ControlFlowOpcode.BranchOpcode.BRANCH; - public static final AMD64ControlFlowOpcode.FloatBranchOpcode FLOAT_BRANCH = AMD64ControlFlowOpcode.FloatBranchOpcode.FLOAT_BRANCH; - public static final AMD64ControlFlowOpcode.TableSwitchOpcode TABLE_SWITCH = AMD64ControlFlowOpcode.TableSwitchOpcode.TABLE_SWITCH; - public static final AMD64ControlFlowOpcode.CondMoveOpcode CMOVE = AMD64ControlFlowOpcode.CondMoveOpcode.CMOVE; - public static final AMD64ControlFlowOpcode.FloatCondMoveOpcode FLOAT_CMOVE = AMD64ControlFlowOpcode.FloatCondMoveOpcode.FLOAT_CMOVE; -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64XirOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64XirOp.java Thu Jan 26 12:23:00 2012 +0100 @@ -0,0 +1,561 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.target.amd64; + +import static com.oracle.max.cri.ci.CiCallingConvention.Type.*; +import static com.oracle.max.cri.ci.CiValue.*; +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiTargetMethod.Mark; +import com.oracle.max.cri.xir.*; +import com.oracle.max.cri.xir.CiXirAssembler.RuntimeCallInformation; +import com.oracle.max.cri.xir.CiXirAssembler.XirInstruction; +import com.oracle.max.cri.xir.CiXirAssembler.XirLabel; +import com.oracle.max.cri.xir.CiXirAssembler.XirMark; +import com.oracle.max.criutils.*; +import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.asm.*; +import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.util.*; + +public class AMD64XirOp extends LIRXirInstruction { + public AMD64XirOp(XirSnippet snippet, CiValue[] operands, CiValue outputOperand, CiValue[] inputs, CiValue[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex, + LIRDebugInfo info, LIRDebugInfo infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) { + super("XIR", snippet, operands, outputOperand, inputs, temps, inputOperandIndices, tempOperandIndices, outputOperandIndex, info, infoAfter, trueSuccessor, falseSuccessor); + } + + @Override + public void emitCode(TargetMethodAssembler tasm) { + AMD64MacroAssembler masm = (AMD64MacroAssembler) tasm.asm; + + Label endLabel = null; + Label[] labels = new Label[snippet.template.labels.length]; + for (int i = 0; i < labels.length; i++) { + labels[i] = new Label(); + if (snippet.template.labels[i].name == XirLabel.TrueSuccessor) { + if (trueSuccessor == null) { + assert endLabel == null; + endLabel = new Label(); + labels[i] = endLabel; + } else { + labels[i] = trueSuccessor.label(); + } + } else if (snippet.template.labels[i].name == XirLabel.FalseSuccessor) { + if (falseSuccessor == null) { + assert endLabel == null; + endLabel = new Label(); + labels[i] = endLabel; + } else { + labels[i] = falseSuccessor.label(); + } + } + } + emitXirInstructions(tasm, masm, snippet.template.fastPath, labels, getOperands(), snippet.marks); + if (endLabel != null) { + masm.bind(endLabel); + } + + if (snippet.template.slowPath != null) { + tasm.slowPaths.add(new SlowPath(labels)); + } + } + + private class SlowPath extends AMD64SlowPath { + public final Label[] labels; + + public SlowPath(Label[] labels) { + this.labels = labels; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + int start = -1; + if (GraalOptions.TraceAssembler) { + TTY.println("Emitting slow path for XIR instruction " + snippet.template.name); + start = masm.codeBuffer.position(); + } + emitXirInstructions(tasm, masm, snippet.template.slowPath, labels, getOperands(), snippet.marks); + masm.nop(); + if (GraalOptions.TraceAssembler) { + TTY.println("From " + start + " to " + masm.codeBuffer.position()); + } + } + } + + + protected void emitXirInstructions(TargetMethodAssembler tasm, AMD64MacroAssembler masm, XirInstruction[] instructions, Label[] labels, CiValue[] operands, Map marks) { + for (XirInstruction inst : instructions) { + switch (inst.op) { + case Add: + emitXirViaLir(tasm, masm, AMD64Arithmetic.IADD, AMD64Arithmetic.LADD, AMD64Arithmetic.FADD, AMD64Arithmetic.DADD, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); + break; + + case Sub: + emitXirViaLir(tasm, masm, AMD64Arithmetic.ISUB, AMD64Arithmetic.LSUB, AMD64Arithmetic.FSUB, AMD64Arithmetic.DSUB, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); + break; + + case Div: + emitXirViaLir(tasm, masm, AMD64Arithmetic.IDIV, AMD64Arithmetic.LDIV, AMD64Arithmetic.FDIV, AMD64Arithmetic.DDIV, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); + break; + + case Mul: + emitXirViaLir(tasm, masm, AMD64Arithmetic.IMUL, AMD64Arithmetic.LMUL, AMD64Arithmetic.FMUL, AMD64Arithmetic.DMUL, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); + break; + + case Mod: + emitXirViaLir(tasm, masm, AMD64Arithmetic.IREM, AMD64Arithmetic.LREM, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); + break; + + case Shl: + emitXirViaLir(tasm, masm, AMD64Arithmetic.ISHL, AMD64Arithmetic.LSHL, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); + break; + + case Sar: + emitXirViaLir(tasm, masm, AMD64Arithmetic.ISHR, AMD64Arithmetic.LSHR, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); + break; + + case Shr: + emitXirViaLir(tasm, masm, AMD64Arithmetic.IUSHR, AMD64Arithmetic.LUSHR, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); + break; + + case And: + emitXirViaLir(tasm, masm, AMD64Arithmetic.IAND, AMD64Arithmetic.LAND, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); + break; + + case Or: + emitXirViaLir(tasm, masm, AMD64Arithmetic.IOR, AMD64Arithmetic.LOR, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); + break; + + case Xor: + emitXirViaLir(tasm, masm, AMD64Arithmetic.IXOR, AMD64Arithmetic.LXOR, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); + break; + + case Mov: { + CiValue result = operands[inst.result.index]; + CiValue source = operands[inst.x().index]; + AMD64Move.move(tasm, masm, result, source); + break; + } + + case PointerLoad: { + CiValue result = operands[inst.result.index]; + CiValue pointer = operands[inst.x().index]; + CiRegisterValue register = assureInRegister(tasm, masm, pointer); + + AMD64Move.load(tasm, masm, result, new CiAddress(inst.kind, register), (Boolean) inst.extra ? info : null); + break; + } + + case PointerStore: { + CiValue value = assureNot64BitConstant(tasm, masm, operands[inst.y().index]); + CiValue pointer = operands[inst.x().index]; + assert isRegister(pointer); + + AMD64Move.store(tasm, masm, new CiAddress(inst.kind, pointer), value, (Boolean) inst.extra ? info : null); + break; + } + + case PointerLoadDisp: { + CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra; + boolean canTrap = addressInformation.canTrap; + + CiAddress.Scale scale = addressInformation.scale; + int displacement = addressInformation.disp; + + CiValue result = operands[inst.result.index]; + CiValue pointer = operands[inst.x().index]; + CiValue index = operands[inst.y().index]; + + pointer = assureInRegister(tasm, masm, pointer); + assert isRegister(pointer); + + CiAddress src; + if (isConstant(index)) { + assert index.kind == CiKind.Int; + CiConstant constantIndex = (CiConstant) index; + src = new CiAddress(inst.kind, pointer, constantIndex.asInt() * scale.value + displacement); + } else { + src = new CiAddress(inst.kind, pointer, index, scale, displacement); + } + + AMD64Move.load(tasm, masm, result, src, canTrap ? info : null); + break; + } + + case LoadEffectiveAddress: { + CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra; + + CiAddress.Scale scale = addressInformation.scale; + int displacement = addressInformation.disp; + + CiValue result = operands[inst.result.index]; + CiValue pointer = operands[inst.x().index]; + CiValue index = operands[inst.y().index]; + + pointer = assureInRegister(tasm, masm, pointer); + assert isRegister(pointer); + CiAddress src = new CiAddress(CiKind.Illegal, pointer, index, scale, displacement); + masm.leaq(asRegister(result), src); + break; + } + + case PointerStoreDisp: { + CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra; + boolean canTrap = addressInformation.canTrap; + + CiAddress.Scale scale = addressInformation.scale; + int displacement = addressInformation.disp; + + CiValue value = assureNot64BitConstant(tasm, masm, operands[inst.z().index]); + CiValue pointer = operands[inst.x().index]; + CiValue index = operands[inst.y().index]; + + pointer = assureInRegister(tasm, masm, pointer); + assert isRegister(pointer); + + CiAddress dst; + if (isConstant(index)) { + assert index.kind == CiKind.Int; + CiConstant constantIndex = (CiConstant) index; + dst = new CiAddress(inst.kind, pointer, IllegalValue, scale, constantIndex.asInt() * scale.value + displacement); + } else { + dst = new CiAddress(inst.kind, pointer, index, scale, displacement); + } + + AMD64Move.store(tasm, masm, dst, value, canTrap ? info : null); + break; + } + + case RepeatMoveBytes: + assert asRegister(operands[inst.x().index]).equals(AMD64.rsi) : "wrong input x: " + operands[inst.x().index]; + assert asRegister(operands[inst.y().index]).equals(AMD64.rdi) : "wrong input y: " + operands[inst.y().index]; + assert asRegister(operands[inst.z().index]).equals(AMD64.rcx) : "wrong input z: " + operands[inst.z().index]; + masm.repeatMoveBytes(); + break; + + case RepeatMoveWords: + assert asRegister(operands[inst.x().index]).equals(AMD64.rsi) : "wrong input x: " + operands[inst.x().index]; + assert asRegister(operands[inst.y().index]).equals(AMD64.rdi) : "wrong input y: " + operands[inst.y().index]; + assert asRegister(operands[inst.z().index]).equals(AMD64.rcx) : "wrong input z: " + operands[inst.z().index]; + masm.repeatMoveWords(); + break; + + case PointerCAS: + assert asRegister(operands[inst.x().index]).equals(AMD64.rax) : "wrong input x: " + operands[inst.x().index]; + + CiValue exchangedVal = operands[inst.y().index]; + CiValue exchangedAddress = operands[inst.x().index]; + CiRegisterValue pointerRegister = assureInRegister(tasm, masm, exchangedAddress); + CiAddress addr = new CiAddress(tasm.target.wordKind, pointerRegister); + + if ((Boolean) inst.extra && info != null) { + tasm.recordImplicitException(masm.codeBuffer.position(), info); + } + masm.cmpxchgq(asRegister(exchangedVal), addr); + + break; + + case CallRuntime: { + CiKind[] signature = new CiKind[inst.arguments.length]; + for (int i = 0; i < signature.length; i++) { + signature[i] = inst.arguments[i].kind; + } + + CiCallingConvention cc = tasm.frameMap.registerConfig.getCallingConvention(RuntimeCall, signature, tasm.target, false); + for (int i = 0; i < inst.arguments.length; i++) { + CiValue argumentLocation = cc.locations[i]; + CiValue argumentSourceLocation = operands[inst.arguments[i].index]; + if (argumentLocation != argumentSourceLocation) { + AMD64Move.move(tasm, masm, argumentLocation, argumentSourceLocation); + } + } + + RuntimeCallInformation runtimeCallInformation = (RuntimeCallInformation) inst.extra; + AMD64Call.directCall(tasm, masm, runtimeCallInformation.target, (runtimeCallInformation.useInfoAfter) ? infoAfter : info); + + if (inst.result != null && inst.result.kind != CiKind.Illegal && inst.result.kind != CiKind.Void) { + CiRegister returnRegister = tasm.frameMap.registerConfig.getReturnRegister(inst.result.kind); + CiValue resultLocation = returnRegister.asValue(inst.result.kind.stackKind()); + AMD64Move.move(tasm, masm, operands[inst.result.index], resultLocation); + } + break; + } + case Jmp: { + if (inst.extra instanceof XirLabel) { + Label label = labels[((XirLabel) inst.extra).index]; + masm.jmp(label); + } else { + AMD64Call.directJmp(tasm, masm, inst.extra); + } + break; + } + case DecAndJumpNotZero: { + Label label = labels[((XirLabel) inst.extra).index]; + CiValue value = operands[inst.x().index]; + if (value.kind == CiKind.Long) { + masm.decq(asRegister(value)); + } else { + assert value.kind == CiKind.Int; + masm.decl(asRegister(value)); + } + masm.jcc(ConditionFlag.notZero, label); + break; + } + case Jeq: { + Label label = labels[((XirLabel) inst.extra).index]; + emitXirCompare(tasm, masm, inst, ConditionFlag.equal, operands, label); + break; + } + case Jneq: { + Label label = labels[((XirLabel) inst.extra).index]; + emitXirCompare(tasm, masm, inst, ConditionFlag.notEqual, operands, label); + break; + } + + case Jgt: { + Label label = labels[((XirLabel) inst.extra).index]; + emitXirCompare(tasm, masm, inst, ConditionFlag.greater, operands, label); + break; + } + + case Jgteq: { + Label label = labels[((XirLabel) inst.extra).index]; + emitXirCompare(tasm, masm, inst, ConditionFlag.greaterEqual, operands, label); + break; + } + + case Jugteq: { + Label label = labels[((XirLabel) inst.extra).index]; + emitXirCompare(tasm, masm, inst, ConditionFlag.aboveEqual, operands, label); + break; + } + + case Jlt: { + Label label = labels[((XirLabel) inst.extra).index]; + emitXirCompare(tasm, masm, inst, ConditionFlag.less, operands, label); + break; + } + + case Jlteq: { + Label label = labels[((XirLabel) inst.extra).index]; + emitXirCompare(tasm, masm, inst, ConditionFlag.lessEqual, operands, label); + break; + } + + case Jbset: { + Label label = labels[((XirLabel) inst.extra).index]; + CiValue pointer = operands[inst.x().index]; + CiValue offset = operands[inst.y().index]; + CiValue bit = operands[inst.z().index]; + assert isConstant(offset) && isConstant(bit); + CiConstant constantOffset = (CiConstant) offset; + CiConstant constantBit = (CiConstant) bit; + CiAddress src = new CiAddress(inst.kind, pointer, constantOffset.asInt()); + masm.btli(src, constantBit.asInt()); + masm.jcc(ConditionFlag.aboveEqual, label); + break; + } + + case Bind: { + XirLabel l = (XirLabel) inst.extra; + Label label = labels[l.index]; + masm.bind(label); + break; + } + case Safepoint: { + assert info != null : "Must have debug info in order to create a safepoint."; + tasm.recordSafepoint(masm.codeBuffer.position(), info); + break; + } + case NullCheck: { + tasm.recordImplicitException(masm.codeBuffer.position(), info); + CiValue pointer = operands[inst.x().index]; + masm.nullCheck(asRegister(pointer)); + break; + } + case Align: { + masm.align((Integer) inst.extra); + break; + } + case StackOverflowCheck: { + int frameSize = tasm.frameMap.frameSize(); + int lastFramePage = frameSize / tasm.target.pageSize; + // emit multiple stack bangs for methods with frames larger than a page + for (int i = 0; i <= lastFramePage; i++) { + int offset = (i + GraalOptions.StackShadowPages) * tasm.target.pageSize; + // Deduct 'frameSize' to handle frames larger than the shadow + bangStackWithOffset(tasm, masm, offset - frameSize); + } + break; + } + case PushFrame: { + int frameSize = tasm.frameMap.frameSize(); + masm.decrementq(AMD64.rsp, frameSize); // does not emit code for frameSize == 0 + if (GraalOptions.ZapStackOnMethodEntry) { + final int intSize = 4; + for (int i = 0; i < frameSize / intSize; ++i) { + masm.movl(new CiAddress(CiKind.Int, AMD64.rsp.asValue(), i * intSize), 0xC1C1C1C1); + } + } + CiCalleeSaveLayout csl = tasm.frameMap.registerConfig.getCalleeSaveLayout(); + if (csl != null && csl.size != 0) { + int frameToCSA = tasm.frameMap.offsetToCalleeSaveArea(); + assert frameToCSA >= 0; + masm.save(csl, frameToCSA); + } + break; + } + case PopFrame: { + int frameSize = tasm.frameMap.frameSize(); + + CiCalleeSaveLayout csl = tasm.frameMap.registerConfig.getCalleeSaveLayout(); + if (csl != null && csl.size != 0) { + tasm.targetMethod.setRegisterRestoreEpilogueOffset(masm.codeBuffer.position()); + // saved all registers, restore all registers + int frameToCSA = tasm.frameMap.offsetToCalleeSaveArea(); + masm.restore(csl, frameToCSA); + } + + masm.incrementq(AMD64.rsp, frameSize); + break; + } + case Push: { + CiRegisterValue value = assureInRegister(tasm, masm, operands[inst.x().index]); + masm.push(asRegister(value)); + break; + } + case Pop: { + CiValue result = operands[inst.result.index]; + if (isRegister(result)) { + masm.pop(asRegister(result)); + } else { + CiRegister rscratch = tasm.frameMap.registerConfig.getScratchRegister(); + masm.pop(rscratch); + AMD64Move.move(tasm, masm, result, rscratch.asValue()); + } + break; + } + case Mark: { + XirMark xmark = (XirMark) inst.extra; + Mark[] references = new Mark[xmark.references.length]; + for (int i = 0; i < references.length; i++) { + references[i] = marks.get(xmark.references[i]); + assert references[i] != null; + } + Mark mark = tasm.recordMark(xmark.id, references); + marks.put(xmark, mark); + break; + } + case Nop: { + for (int i = 0; i < (Integer) inst.extra; i++) { + masm.nop(); + } + break; + } + case RawBytes: { + for (byte b : (byte[]) inst.extra) { + masm.codeBuffer.emitByte(b & 0xff); + } + break; + } + case ShouldNotReachHere: { + AMD64Call.shouldNotReachHere(tasm, masm); + break; + } + default: + throw Util.shouldNotReachHere("Unknown XIR operation " + inst.op); + } + } + } + + private static void emitXirViaLir(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic intOp, AMD64Arithmetic longOp, AMD64Arithmetic floatOp, + AMD64Arithmetic doubleOp, CiValue left, CiValue right, CiValue result) { + AMD64Arithmetic code; + switch (result.kind) { + case Int: code = intOp; break; + case Long: code = longOp; break; + case Float: code = floatOp; break; + case Double: code = doubleOp; break; + default: throw Util.shouldNotReachHere(); + } + assert left == result; + if (isRegister(right) && right.kind != result.kind) { + // XIR is not strongly typed, so we can have a type mismatch that we have to fix here. + AMD64Arithmetic.emit(tasm, masm, code, result, asRegister(right).asValue(result.kind), null); + } else { + AMD64Arithmetic.emit(tasm, masm, code, result, right, null); + } + } + + private static void emitXirCompare(TargetMethodAssembler tasm, AMD64MacroAssembler masm, XirInstruction inst, ConditionFlag cflag, CiValue[] ops, Label label) { + CiValue x = ops[inst.x().index]; + CiValue y = ops[inst.y().index]; + AMD64Compare code; + switch (x.kind) { + case Int: code = AMD64Compare.ICMP; break; + case Long: code = AMD64Compare.LCMP; break; + case Object: code = AMD64Compare.ACMP; break; + case Float: code = AMD64Compare.FCMP; break; + case Double: code = AMD64Compare.DCMP; break; + default: throw Util.shouldNotReachHere(); + } + AMD64Compare.emit(tasm, masm, code, x, y); + masm.jcc(cflag, label); + } + + /** + * @param offset the offset RSP at which to bang. Note that this offset is relative to RSP after RSP has been + * adjusted to allocated the frame for the method. It denotes an offset "down" the stack. + * For very large frames, this means that the offset may actually be negative (i.e. denoting + * a slot "up" the stack above RSP). + */ + private static void bangStackWithOffset(TargetMethodAssembler tasm, AMD64MacroAssembler masm, int offset) { + masm.movq(new CiAddress(tasm.target.wordKind, AMD64.RSP, -offset), AMD64.rax); + } + + private static CiValue assureNot64BitConstant(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue value) { + if (isConstant(value) && (value.kind == CiKind.Long || value.kind == CiKind.Object)) { + CiRegisterValue register = tasm.frameMap.registerConfig.getScratchRegister().asValue(value.kind); + AMD64Move.move(tasm, masm, register, value); + return register; + } + return value; + } + + private static CiRegisterValue assureInRegister(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue pointer) { + if (isConstant(pointer)) { + CiRegisterValue register = tasm.frameMap.registerConfig.getScratchRegister().asValue(pointer.kind); + AMD64Move.move(tasm, masm, register, pointer); + return register; + } + + assert isRegister(pointer) : "should be register, but is: " + pointer; + return (CiRegisterValue) pointer; + } +} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64XirOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64XirOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,577 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.compiler.target.amd64; - -import static com.oracle.max.cri.ci.CiCallingConvention.Type.*; -import static com.oracle.max.cri.ci.CiValue.*; -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import java.util.*; - -import com.oracle.max.asm.*; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiTargetMethod.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.cri.xir.*; -import com.oracle.max.cri.xir.CiXirAssembler.*; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.util.*; - -public enum AMD64XirOpcode implements StandardOpcode.XirOpcode { - XIR; - - public LIRInstruction create(XirSnippet snippet, CiValue[] operands, CiValue outputOperand, CiValue[] inputs, CiValue[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex, - LIRDebugInfo info, LIRDebugInfo infoAfter, RiMethod method) { - return new LIRXirInstruction(this, snippet, operands, outputOperand, inputs, temps, inputOperandIndices, tempOperandIndices, outputOperandIndex, info, infoAfter, method) { - @Override - public void emitCode(TargetMethodAssembler tasm) { - emit(tasm, (AMD64MacroAssembler) tasm.asm, this); - } - }; - } - - private static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, LIRXirInstruction op) { - XirSnippet snippet = op.snippet; - Label endLabel = null; - Label[] labels = new Label[snippet.template.labels.length]; - for (int i = 0; i < labels.length; i++) { - labels[i] = new Label(); - if (snippet.template.labels[i].name == XirLabel.TrueSuccessor) { - if (op.trueSuccessor() == null) { - assert endLabel == null; - endLabel = new Label(); - labels[i] = endLabel; - } else { - labels[i] = op.trueSuccessor().label(); - } - } else if (snippet.template.labels[i].name == XirLabel.FalseSuccessor) { - if (op.falseSuccessor() == null) { - assert endLabel == null; - endLabel = new Label(); - labels[i] = endLabel; - } else { - labels[i] = op.falseSuccessor().label(); - } - } - } - emitXirInstructions(tasm, masm, op, snippet.template.fastPath, labels, op.getOperands(), snippet.marks); - if (endLabel != null) { - masm.bind(endLabel); - } - - if (snippet.template.slowPath != null) { - tasm.slowPaths.add(new SlowPath(op, labels, snippet.marks)); - } - } - - private static class SlowPath extends AMD64SlowPath { - public final LIRXirInstruction instruction; - public final Label[] labels; - public final Map marks; - - public SlowPath(LIRXirInstruction instruction, Label[] labels, Map marks) { - this.instruction = instruction; - this.labels = labels; - this.marks = marks; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - emitSlowPath(tasm, masm, this); - } - } - - - private static void emitSlowPath(TargetMethodAssembler tasm, AMD64MacroAssembler masm, SlowPath sp) { - int start = -1; - if (GraalOptions.TraceAssembler) { - TTY.println("Emitting slow path for XIR instruction " + sp.instruction.snippet.template.name); - start = masm.codeBuffer.position(); - } - emitXirInstructions(tasm, masm, sp.instruction, sp.instruction.snippet.template.slowPath, sp.labels, sp.instruction.getOperands(), sp.marks); - masm.nop(); - if (GraalOptions.TraceAssembler) { - TTY.println("From " + start + " to " + masm.codeBuffer.position()); - } - } - - protected static void emitXirInstructions(TargetMethodAssembler tasm, AMD64MacroAssembler masm, LIRXirInstruction xir, XirInstruction[] instructions, Label[] labels, CiValue[] operands, Map marks) { - LIRDebugInfo info = xir == null ? null : xir.info; - LIRDebugInfo infoAfter = xir == null ? null : xir.infoAfter; - - for (XirInstruction inst : instructions) { - switch (inst.op) { - case Add: - emitXirViaLir(tasm, masm, AMD64ArithmeticOpcode.IADD, AMD64ArithmeticOpcode.LADD, AMD64ArithmeticOpcode.FADD, AMD64ArithmeticOpcode.DADD, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); - break; - - case Sub: - emitXirViaLir(tasm, masm, AMD64ArithmeticOpcode.ISUB, AMD64ArithmeticOpcode.LSUB, AMD64ArithmeticOpcode.FSUB, AMD64ArithmeticOpcode.DSUB, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); - break; - - case Div: - emitXirViaLir(tasm, masm, AMD64DivOpcode.IDIV, AMD64DivOpcode.LDIV, AMD64ArithmeticOpcode.FDIV, AMD64ArithmeticOpcode.DDIV, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); - break; - - case Mul: - emitXirViaLir(tasm, masm, AMD64MulOpcode.IMUL, AMD64MulOpcode.LMUL, AMD64ArithmeticOpcode.FMUL, AMD64ArithmeticOpcode.DMUL, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); - break; - - case Mod: - emitXirViaLir(tasm, masm, AMD64DivOpcode.IREM, AMD64DivOpcode.LREM, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); - break; - - case Shl: - emitXirViaLir(tasm, masm, AMD64ShiftOpcode.ISHL, AMD64ShiftOpcode.LSHL, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); - break; - - case Sar: - emitXirViaLir(tasm, masm, AMD64ShiftOpcode.ISHR, AMD64ShiftOpcode.LSHR, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); - break; - - case Shr: - emitXirViaLir(tasm, masm, AMD64ShiftOpcode.IUSHR, AMD64ShiftOpcode.LUSHR, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); - break; - - case And: - emitXirViaLir(tasm, masm, AMD64ArithmeticOpcode.IAND, AMD64ArithmeticOpcode.LAND, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); - break; - - case Or: - emitXirViaLir(tasm, masm, AMD64ArithmeticOpcode.IOR, AMD64ArithmeticOpcode.LOR, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); - break; - - case Xor: - emitXirViaLir(tasm, masm, AMD64ArithmeticOpcode.IXOR, AMD64ArithmeticOpcode.LXOR, null, null, operands[inst.x().index], operands[inst.y().index], operands[inst.result.index]); - break; - - case Mov: { - CiValue result = operands[inst.result.index]; - CiValue source = operands[inst.x().index]; - AMD64MoveOpcode.move(tasm, masm, result, source); - break; - } - - case PointerLoad: { - CiValue result = operands[inst.result.index]; - CiValue pointer = operands[inst.x().index]; - CiRegisterValue register = assureInRegister(tasm, masm, pointer); - - AMD64MoveOpcode.load(tasm, masm, result, new CiAddress(inst.kind, register), (Boolean) inst.extra ? info : null); - break; - } - - case PointerStore: { - CiValue value = assureNot64BitConstant(tasm, masm, operands[inst.y().index]); - CiValue pointer = operands[inst.x().index]; - assert isRegister(pointer); - - AMD64MoveOpcode.store(tasm, masm, new CiAddress(inst.kind, pointer), value, (Boolean) inst.extra ? info : null); - break; - } - - case PointerLoadDisp: { - CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra; - boolean canTrap = addressInformation.canTrap; - - CiAddress.Scale scale = addressInformation.scale; - int displacement = addressInformation.disp; - - CiValue result = operands[inst.result.index]; - CiValue pointer = operands[inst.x().index]; - CiValue index = operands[inst.y().index]; - - pointer = assureInRegister(tasm, masm, pointer); - assert isRegister(pointer); - - CiAddress src; - if (isConstant(index)) { - assert index.kind == CiKind.Int; - CiConstant constantIndex = (CiConstant) index; - src = new CiAddress(inst.kind, pointer, constantIndex.asInt() * scale.value + displacement); - } else { - src = new CiAddress(inst.kind, pointer, index, scale, displacement); - } - - AMD64MoveOpcode.load(tasm, masm, result, src, canTrap ? info : null); - break; - } - - case LoadEffectiveAddress: { - CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra; - - CiAddress.Scale scale = addressInformation.scale; - int displacement = addressInformation.disp; - - CiValue result = operands[inst.result.index]; - CiValue pointer = operands[inst.x().index]; - CiValue index = operands[inst.y().index]; - - pointer = assureInRegister(tasm, masm, pointer); - assert isRegister(pointer); - CiAddress src = new CiAddress(CiKind.Illegal, pointer, index, scale, displacement); - masm.leaq(asRegister(result), src); - break; - } - - case PointerStoreDisp: { - CiXirAssembler.AddressAccessInformation addressInformation = (CiXirAssembler.AddressAccessInformation) inst.extra; - boolean canTrap = addressInformation.canTrap; - - CiAddress.Scale scale = addressInformation.scale; - int displacement = addressInformation.disp; - - CiValue value = assureNot64BitConstant(tasm, masm, operands[inst.z().index]); - CiValue pointer = operands[inst.x().index]; - CiValue index = operands[inst.y().index]; - - pointer = assureInRegister(tasm, masm, pointer); - assert isRegister(pointer); - - CiAddress dst; - if (isConstant(index)) { - assert index.kind == CiKind.Int; - CiConstant constantIndex = (CiConstant) index; - dst = new CiAddress(inst.kind, pointer, IllegalValue, scale, constantIndex.asInt() * scale.value + displacement); - } else { - dst = new CiAddress(inst.kind, pointer, index, scale, displacement); - } - - AMD64MoveOpcode.store(tasm, masm, dst, value, canTrap ? info : null); - break; - } - - case RepeatMoveBytes: - assert asRegister(operands[inst.x().index]).equals(AMD64.rsi) : "wrong input x: " + operands[inst.x().index]; - assert asRegister(operands[inst.y().index]).equals(AMD64.rdi) : "wrong input y: " + operands[inst.y().index]; - assert asRegister(operands[inst.z().index]).equals(AMD64.rcx) : "wrong input z: " + operands[inst.z().index]; - masm.repeatMoveBytes(); - break; - - case RepeatMoveWords: - assert asRegister(operands[inst.x().index]).equals(AMD64.rsi) : "wrong input x: " + operands[inst.x().index]; - assert asRegister(operands[inst.y().index]).equals(AMD64.rdi) : "wrong input y: " + operands[inst.y().index]; - assert asRegister(operands[inst.z().index]).equals(AMD64.rcx) : "wrong input z: " + operands[inst.z().index]; - masm.repeatMoveWords(); - break; - - case PointerCAS: - assert asRegister(operands[inst.x().index]).equals(AMD64.rax) : "wrong input x: " + operands[inst.x().index]; - - CiValue exchangedVal = operands[inst.y().index]; - CiValue exchangedAddress = operands[inst.x().index]; - CiRegisterValue pointerRegister = assureInRegister(tasm, masm, exchangedAddress); - CiAddress addr = new CiAddress(tasm.target.wordKind, pointerRegister); - - if ((Boolean) inst.extra && info != null) { - tasm.recordImplicitException(masm.codeBuffer.position(), info); - } - masm.cmpxchgq(asRegister(exchangedVal), addr); - - break; - - case CallRuntime: { - CiKind[] signature = new CiKind[inst.arguments.length]; - for (int i = 0; i < signature.length; i++) { - signature[i] = inst.arguments[i].kind; - } - - CiCallingConvention cc = tasm.frameMap.registerConfig.getCallingConvention(RuntimeCall, signature, tasm.target, false); - for (int i = 0; i < inst.arguments.length; i++) { - CiValue argumentLocation = cc.locations[i]; - CiValue argumentSourceLocation = operands[inst.arguments[i].index]; - if (argumentLocation != argumentSourceLocation) { - AMD64MoveOpcode.move(tasm, masm, argumentLocation, argumentSourceLocation); - } - } - - RuntimeCallInformation runtimeCallInformation = (RuntimeCallInformation) inst.extra; - AMD64CallOpcode.directCall(tasm, masm, runtimeCallInformation.target, (runtimeCallInformation.useInfoAfter) ? infoAfter : info); - - if (inst.result != null && inst.result.kind != CiKind.Illegal && inst.result.kind != CiKind.Void) { - CiRegister returnRegister = tasm.frameMap.registerConfig.getReturnRegister(inst.result.kind); - CiValue resultLocation = returnRegister.asValue(inst.result.kind.stackKind()); - AMD64MoveOpcode.move(tasm, masm, operands[inst.result.index], resultLocation); - } - break; - } - case Jmp: { - if (inst.extra instanceof XirLabel) { - Label label = labels[((XirLabel) inst.extra).index]; - masm.jmp(label); - } else { - AMD64CallOpcode.directJmp(tasm, masm, inst.extra); - } - break; - } - case DecAndJumpNotZero: { - Label label = labels[((XirLabel) inst.extra).index]; - CiValue value = operands[inst.x().index]; - if (value.kind == CiKind.Long) { - masm.decq(asRegister(value)); - } else { - assert value.kind == CiKind.Int; - masm.decl(asRegister(value)); - } - masm.jcc(ConditionFlag.notZero, label); - break; - } - case Jeq: { - Label label = labels[((XirLabel) inst.extra).index]; - emitXirCompare(tasm, masm, inst, ConditionFlag.equal, operands, label); - break; - } - case Jneq: { - Label label = labels[((XirLabel) inst.extra).index]; - emitXirCompare(tasm, masm, inst, ConditionFlag.notEqual, operands, label); - break; - } - - case Jgt: { - Label label = labels[((XirLabel) inst.extra).index]; - emitXirCompare(tasm, masm, inst, ConditionFlag.greater, operands, label); - break; - } - - case Jgteq: { - Label label = labels[((XirLabel) inst.extra).index]; - emitXirCompare(tasm, masm, inst, ConditionFlag.greaterEqual, operands, label); - break; - } - - case Jugteq: { - Label label = labels[((XirLabel) inst.extra).index]; - emitXirCompare(tasm, masm, inst, ConditionFlag.aboveEqual, operands, label); - break; - } - - case Jlt: { - Label label = labels[((XirLabel) inst.extra).index]; - emitXirCompare(tasm, masm, inst, ConditionFlag.less, operands, label); - break; - } - - case Jlteq: { - Label label = labels[((XirLabel) inst.extra).index]; - emitXirCompare(tasm, masm, inst, ConditionFlag.lessEqual, operands, label); - break; - } - - case Jbset: { - Label label = labels[((XirLabel) inst.extra).index]; - CiValue pointer = operands[inst.x().index]; - CiValue offset = operands[inst.y().index]; - CiValue bit = operands[inst.z().index]; - assert isConstant(offset) && isConstant(bit); - CiConstant constantOffset = (CiConstant) offset; - CiConstant constantBit = (CiConstant) bit; - CiAddress src = new CiAddress(inst.kind, pointer, constantOffset.asInt()); - masm.btli(src, constantBit.asInt()); - masm.jcc(ConditionFlag.aboveEqual, label); - break; - } - - case Bind: { - XirLabel l = (XirLabel) inst.extra; - Label label = labels[l.index]; - masm.bind(label); - break; - } - case Safepoint: { - assert info != null : "Must have debug info in order to create a safepoint."; - tasm.recordSafepoint(masm.codeBuffer.position(), info); - break; - } - case NullCheck: { - tasm.recordImplicitException(masm.codeBuffer.position(), info); - CiValue pointer = operands[inst.x().index]; - masm.nullCheck(asRegister(pointer)); - break; - } - case Align: { - masm.align((Integer) inst.extra); - break; - } - case StackOverflowCheck: { - int frameSize = tasm.frameMap.frameSize(); - int lastFramePage = frameSize / tasm.target.pageSize; - // emit multiple stack bangs for methods with frames larger than a page - for (int i = 0; i <= lastFramePage; i++) { - int offset = (i + GraalOptions.StackShadowPages) * tasm.target.pageSize; - // Deduct 'frameSize' to handle frames larger than the shadow - bangStackWithOffset(tasm, masm, offset - frameSize); - } - break; - } - case PushFrame: { - int frameSize = tasm.frameMap.frameSize(); - masm.decrementq(AMD64.rsp, frameSize); // does not emit code for frameSize == 0 - if (GraalOptions.ZapStackOnMethodEntry) { - final int intSize = 4; - for (int i = 0; i < frameSize / intSize; ++i) { - masm.movl(new CiAddress(CiKind.Int, AMD64.rsp.asValue(), i * intSize), 0xC1C1C1C1); - } - } - CiCalleeSaveLayout csl = tasm.frameMap.registerConfig.getCalleeSaveLayout(); - if (csl != null && csl.size != 0) { - int frameToCSA = tasm.frameMap.offsetToCalleeSaveArea(); - assert frameToCSA >= 0; - masm.save(csl, frameToCSA); - } - break; - } - case PopFrame: { - int frameSize = tasm.frameMap.frameSize(); - - CiCalleeSaveLayout csl = tasm.frameMap.registerConfig.getCalleeSaveLayout(); - if (csl != null && csl.size != 0) { - tasm.targetMethod.setRegisterRestoreEpilogueOffset(masm.codeBuffer.position()); - // saved all registers, restore all registers - int frameToCSA = tasm.frameMap.offsetToCalleeSaveArea(); - masm.restore(csl, frameToCSA); - } - - masm.incrementq(AMD64.rsp, frameSize); - break; - } - case Push: { - CiRegisterValue value = assureInRegister(tasm, masm, operands[inst.x().index]); - masm.push(asRegister(value)); - break; - } - case Pop: { - CiValue result = operands[inst.result.index]; - if (isRegister(result)) { - masm.pop(asRegister(result)); - } else { - CiRegister rscratch = tasm.frameMap.registerConfig.getScratchRegister(); - masm.pop(rscratch); - AMD64MoveOpcode.move(tasm, masm, result, rscratch.asValue()); - } - break; - } - case Mark: { - XirMark xmark = (XirMark) inst.extra; - Mark[] references = new Mark[xmark.references.length]; - for (int i = 0; i < references.length; i++) { - references[i] = marks.get(xmark.references[i]); - assert references[i] != null; - } - Mark mark = tasm.recordMark(xmark.id, references); - marks.put(xmark, mark); - break; - } - case Nop: { - for (int i = 0; i < (Integer) inst.extra; i++) { - masm.nop(); - } - break; - } - case RawBytes: { - for (byte b : (byte[]) inst.extra) { - masm.codeBuffer.emitByte(b & 0xff); - } - break; - } - case ShouldNotReachHere: { - AMD64CallOpcode.shouldNotReachHere(tasm, masm); - break; - } - default: - throw Util.shouldNotReachHere("Unknown XIR operation " + inst.op); - } - } - } - - private static void emitXirViaLir(TargetMethodAssembler tasm, AMD64MacroAssembler masm, LIROpcode intOp, LIROpcode longOp, LIROpcode floatOp, LIROpcode doubleOp, CiValue left, CiValue right, CiValue result) { - LIROpcode code; - switch (result.kind) { - case Int: code = intOp; break; - case Long: code = longOp; break; - case Float: code = floatOp; break; - case Double: code = doubleOp; break; - default: throw Util.shouldNotReachHere(); - } - - if (code instanceof AMD64ArithmeticOpcode) { - ((AMD64ArithmeticOpcode) code).emit(tasm, masm, result, left, right); - } else if (code instanceof AMD64MulOpcode) { - ((AMD64MulOpcode) code).emit(tasm, masm, result, left, right); - } else if (code instanceof AMD64DivOpcode) { - ((AMD64DivOpcode) code).emit(tasm, masm, result, null, left, right); - } else if (code instanceof AMD64ShiftOpcode) { - ((AMD64ShiftOpcode) code).emit(tasm, masm, result, left, right); - } - } - - private static void emitXirCompare(TargetMethodAssembler tasm, AMD64MacroAssembler masm, XirInstruction inst, ConditionFlag cflag, CiValue[] ops, Label label) { - CiValue x = ops[inst.x().index]; - CiValue y = ops[inst.y().index]; - AMD64CompareOpcode code; - switch (x.kind) { - case Int: code = AMD64CompareOpcode.ICMP; break; - case Long: code = AMD64CompareOpcode.LCMP; break; - case Object: code = AMD64CompareOpcode.ACMP; break; - case Float: code = AMD64CompareOpcode.FCMP; break; - case Double: code = AMD64CompareOpcode.DCMP; break; - default: throw Util.shouldNotReachHere(); - } - code.emit(tasm, masm, x, y); - masm.jcc(cflag, label); - } - - /** - * @param offset the offset RSP at which to bang. Note that this offset is relative to RSP after RSP has been - * adjusted to allocated the frame for the method. It denotes an offset "down" the stack. - * For very large frames, this means that the offset may actually be negative (i.e. denoting - * a slot "up" the stack above RSP). - */ - private static void bangStackWithOffset(TargetMethodAssembler tasm, AMD64MacroAssembler masm, int offset) { - masm.movq(new CiAddress(tasm.target.wordKind, AMD64.RSP, -offset), AMD64.rax); - } - - private static CiValue assureNot64BitConstant(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue value) { - if (isConstant(value) && (value.kind == CiKind.Long || value.kind == CiKind.Object)) { - CiRegisterValue register = tasm.frameMap.registerConfig.getScratchRegister().asValue(value.kind); - AMD64MoveOpcode.move(tasm, masm, register, value); - return register; - } - return value; - } - - private static CiRegisterValue assureInRegister(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue pointer) { - if (isConstant(pointer)) { - CiRegisterValue register = tasm.frameMap.registerConfig.getScratchRegister().asValue(pointer.kind); - AMD64MoveOpcode.move(tasm, masm, register, pointer); - return register; - } - - assert isRegister(pointer) : "should be register, but is: " + pointer; - return (CiRegisterValue) pointer; - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotTargetMethod.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotTargetMethod.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotTargetMethod.java Thu Jan 26 12:23:00 2012 +0100 @@ -35,7 +35,7 @@ public final class HotSpotTargetMethod extends CompilerObject { /** - * + * */ private static final long serialVersionUID = 7807321392203253218L; public final CiTargetMethod targetMethod; @@ -45,7 +45,7 @@ public final Site[] sites; public final ExceptionHandler[] exceptionHandlers; - private HotSpotTargetMethod(Compiler compiler, HotSpotMethodResolved method, CiTargetMethod targetMethod) { + public HotSpotTargetMethod(Compiler compiler, HotSpotMethodResolved method, CiTargetMethod targetMethod) { super(compiler); this.method = method; this.targetMethod = targetMethod; @@ -100,10 +100,6 @@ return result; } - public static HotSpotCompiledMethod installMethod(Compiler compiler, HotSpotMethodResolved method, CiTargetMethod targetMethod, boolean installCode) { - return compiler.getVMEntries().installMethod(new HotSpotTargetMethod(compiler, method, targetMethod), installCode); - } - public static Object installStub(Compiler compiler, CiTargetMethod targetMethod, String name) { return compiler.getVMEntries().installStub(new HotSpotTargetMethod(compiler, targetMethod, name)); } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java Thu Jan 26 12:23:00 2012 +0100 @@ -32,7 +32,6 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.phases.*; import com.oracle.max.graal.compiler.phases.PhasePlan.PhasePosition; -import com.oracle.max.graal.hotspot.*; import com.oracle.max.graal.hotspot.Compiler; import com.oracle.max.graal.hotspot.ri.*; import com.oracle.max.graal.hotspot.server.*; @@ -182,7 +181,7 @@ GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime()); plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); CiTargetMethod result = compiler.getCompiler().compileMethod(method, -1, plan); - HotSpotTargetMethod.installMethod(compiler, method, result, true); + compiler.getRuntime().installMethod(method, result); } catch (CiBailout bailout) { if (GraalOptions.ExitVMOnBailout) { bailout.printStackTrace(TTY.cachedOut); diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/nodes/TailcallNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/nodes/TailcallNode.java Thu Jan 26 12:23:00 2012 +0100 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.hotspot.nodes; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.hotspot.*; +import com.oracle.max.graal.hotspot.target.amd64.*; +import com.oracle.max.graal.nodes.*; +import com.oracle.max.graal.nodes.spi.*; +import com.oracle.max.graal.nodes.type.*; + +/** + * Performs a tail call to the specified target compiled method, with the parameter taken from the supplied FrameState. + */ +public class TailcallNode extends FixedWithNextNode implements LIRLowerable { + + @Input private final FrameState frameState; + @Input private final ValueNode target; + + /** + * Creates a TailcallNode. + * @param target points to the start of an nmethod + * @param frameState the parameters will be taken from this FrameState + */ + public TailcallNode(ValueNode target, FrameState frameState) { + super(StampFactory.illegal()); + this.target = target; + this.frameState = frameState; + } + + @Override + public void generate(LIRGeneratorTool generator) { + LIRGenerator gen = (LIRGenerator) generator; + HotSpotVMConfig config = CompilerImpl.getInstance().getConfig(); + RiResolvedMethod method = frameState.method(); + boolean isStatic = Modifier.isStatic(method.accessFlags()); + + CiKind[] signature = CiUtil.signatureToKinds(method.signature(), isStatic ? null : method.holder().kind(true)); + CiCallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CiCallingConvention.Type.JavaCall, signature, gen.target(), false); + gen.frameMap().callsMethod(cc, CiCallingConvention.Type.JavaCall); + List parameters = new ArrayList<>(); + for (int i = 0; i < cc.locations.length; i++) { + parameters.add(frameState.localAt(i)); + } + List argList = gen.visitInvokeArguments(cc, parameters, null); + + CiValue entry = gen.emitLoad(new CiAddress(CiKind.Long, gen.operand(target), config.nmethodEntryOffset), false); + + gen.append(new AMD64TailcallOp(argList, entry, cc.locations)); + } +} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java Thu Jan 26 12:23:00 2012 +0100 @@ -57,6 +57,7 @@ private RiResolvedType holder; private byte[] code; private boolean canBeInlined; + private CiGenericCallback callback; private HotSpotMethodResolvedImpl() { super(null); @@ -306,10 +307,16 @@ @Override public boolean canBeInlined() { - return canBeInlined; + return canBeInlined && callback == null; + } + public void neverInline() { + this.canBeInlined = false; } - public void setCanBeInlined(boolean canBeInlined) { - this.canBeInlined = canBeInlined; + public CiGenericCallback callback() { + return callback; + } + public void setCallback(CiGenericCallback callback) { + this.callback = callback; } } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java Thu Jan 26 12:23:00 2012 +0100 @@ -34,12 +34,15 @@ import com.oracle.max.cri.ri.RiType.Representation; import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.phases.*; import com.oracle.max.graal.cri.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.hotspot.*; import com.oracle.max.graal.hotspot.Compiler; import com.oracle.max.graal.hotspot.nodes.*; +import com.oracle.max.graal.java.*; import com.oracle.max.graal.nodes.*; +import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction; import com.oracle.max.graal.nodes.calc.*; import com.oracle.max.graal.nodes.extended.*; import com.oracle.max.graal.nodes.java.*; @@ -399,18 +402,82 @@ return (RiResolvedMethod) compiler.getVMEntries().getRiMethod(reflectionMethod); } - public void installMethod(RiMethod method, CiTargetMethod code) { - HotSpotTargetMethod.installMethod(CompilerImpl.getInstance(), (HotSpotMethodResolved) method, code, true); + @Override + public void installMethod(RiResolvedMethod method, CiTargetMethod code) { + synchronized (method) { + if (((HotSpotMethodResolvedImpl) method).callback() == null) { + compiler.getVMEntries().installMethod(new HotSpotTargetMethod(compiler, (HotSpotMethodResolved) method, code), true); + } else { + // callback stub is installed. + } + } } @Override public RiCompiledMethod addMethod(RiResolvedMethod method, CiTargetMethod code) { - Compiler compilerInstance = CompilerImpl.getInstance(); - return HotSpotTargetMethod.installMethod(compilerInstance, (HotSpotMethodResolved) method, code, false); + return compiler.getVMEntries().installMethod(new HotSpotTargetMethod(compiler, (HotSpotMethodResolved) method, code), false); + } + + public void installMethodCallback(RiResolvedMethod method, CiGenericCallback callback) { + synchronized (method) { + ((HotSpotMethodResolvedImpl) method).setCallback(callback); + CiTargetMethod callbackStub = createCallbackStub(method, callback); + compiler.getVMEntries().installMethod(new HotSpotTargetMethod(compiler, (HotSpotMethodResolved) method, callbackStub), true); + } } @Override public RiRegisterConfig getGlobalStubRegisterConfig() { return globalStubRegConfig; } + + private CiTargetMethod createCallbackStub(RiResolvedMethod method, CiGenericCallback callback) { + StructuredGraph graph = new StructuredGraph(); + FrameStateBuilder frameState = new FrameStateBuilder(method, method.maxLocals(), method.maxStackSize(), graph); + ValueNode local0 = frameState.loadLocal(0); + + FrameState initialFrameState = frameState.create(0); + graph.start().setStateAfter(initialFrameState); + + ConstantNode callbackNode = ConstantNode.forObject(callback, this, graph); + + RuntimeCallNode runtimeCall = graph.add(new RuntimeCallNode(CiRuntimeCall.GenericCallback, new ValueNode[] {callbackNode, local0})); + runtimeCall.setStateAfter(initialFrameState.duplicateModified(0, false, CiKind.Void, runtimeCall)); + + @SuppressWarnings("unused") + HotSpotCompiledMethod hotSpotCompiledMethod = new HotSpotCompiledMethod(null); // initialize class... + RiResolvedType compiledMethodClass = getType(HotSpotCompiledMethod.class); + RiResolvedField nmethodField = null; + for (RiResolvedField field : compiledMethodClass.declaredFields()) { + if (field.name().equals("nmethod")) { + nmethodField = field; + break; + } + } + assert nmethodField != null; + LoadFieldNode loadField = graph.add(new LoadFieldNode(runtimeCall, nmethodField)); + + CompareNode compare = graph.unique(new CompareNode(loadField, Condition.EQ, ConstantNode.forLong(0, graph))); + + IfNode ifNull = graph.add(new IfNode(compare, 0.01)); + + BeginNode beginInvalidated = graph.add(new BeginNode()); + DeoptimizeNode deoptInvalidated = graph.add(new DeoptimizeNode(DeoptAction.None)); + + BeginNode beginTailcall = graph.add(new BeginNode()); + TailcallNode tailcall = graph.add(new TailcallNode(loadField, initialFrameState)); + DeoptimizeNode deoptEnd = graph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile)); + + graph.start().setNext(runtimeCall); + runtimeCall.setNext(loadField); + loadField.setNext(ifNull); + ifNull.setTrueSuccessor(beginInvalidated); + ifNull.setFalseSuccessor(beginTailcall); + beginInvalidated.setNext(deoptInvalidated); + beginTailcall.setNext(tailcall); + tailcall.setNext(deoptEnd); + + CiTargetMethod result = compiler.getCompiler().compileMethod(method, graph, -1, PhasePlan.DEFAULT); + return result; + } } diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java Thu Jan 26 12:23:00 2012 +0100 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.hotspot.target.amd64; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.compiler.asm.*; +import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.target.amd64.*; +import com.oracle.max.graal.compiler.util.*; + +/** + * Performs a hard-coded tail call to the specified target, which normally should be an RiCompiledCode instance. + */ +public class AMD64TailcallOp extends AMD64LIRInstruction { + public AMD64TailcallOp(List parameters, CiValue target, CiValue[] callingConvention) { + super("TAILCALL", LIRInstruction.NO_OPERANDS, null, toArray(parameters, target), LIRInstruction.NO_OPERANDS, callingConvention.clone()); + assert inputs.length == temps.length + 1; + } + + private static CiValue[] toArray(List parameters, CiValue target) { + CiValue[] result = new CiValue[parameters.size() + 1]; + parameters.toArray(result); + result[parameters.size()] = target; + return result; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + // move all parameters to the correct positions, according to the calling convention + // TODO: These moves should not be part of the TAILCALL opcode, but emitted as separate MOVE instructions before. + for (int i = 0; i < inputs.length - 1; i++) { + assert inputs[i].kind == CiKind.Object || inputs[i].kind == CiKind.Int || inputs[i].kind == CiKind.Long : "only Object, int and long supported for now"; + assert isRegister(temps[i]) : "too many parameters"; + if (isRegister(inputs[i])) { + if (inputs[i] != temps[i]) { + masm.movq(asRegister(temps[i]), asRegister(inputs[i])); + } + } else { + masm.movq(asRegister(temps[i]), tasm.asAddress(inputs[i])); + } + } + // destroy the current frame (now the return address is the top of stack) + masm.leave(); + + // jump to the target method + masm.jmp(asRegister(inputs[inputs.length - 1])); + masm.ensureUniquePC(); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Stack); + } else if (mode == OperandMode.Temp && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + } + throw Util.shouldNotReachHere(); + } +} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/nodes/MathIntrinsicNode.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/nodes/MathIntrinsicNode.java Thu Jan 26 12:22:36 2012 +0100 +++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/nodes/MathIntrinsicNode.java Thu Jan 26 12:23:00 2012 +0100 @@ -22,8 +22,11 @@ */ package com.oracle.max.graal.snippets.nodes; +import static com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.*; + import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op2RegCommutative; import com.oracle.max.graal.compiler.target.amd64.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.nodes.*; @@ -61,13 +64,13 @@ Variable input = gen.load(gen.operand(x())); Variable result = gen.newVariable(kind()); switch (operation()) { - case ABS: gen.append(AMD64LogicFloatOpcode.DAND.create(result, input, CiConstant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)))); break; - case SQRT: gen.append(AMD64MathIntrinsicOpcode.SQRT.create(result, input)); break; - case LOG: gen.append(AMD64MathIntrinsicOpcode.LOG.create(result, input)); break; - case LOG10: gen.append(AMD64MathIntrinsicOpcode.LOG10.create(result, input)); break; - case SIN: gen.append(AMD64MathIntrinsicOpcode.SIN.create(result, input)); break; - case COS: gen.append(AMD64MathIntrinsicOpcode.COS.create(result, input)); break; - case TAN: gen.append(AMD64MathIntrinsicOpcode.TAN.create(result, input)); break; + case ABS: gen.append(new Op2RegCommutative(DAND, result, input, CiConstant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)))); break; + case SQRT: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.SQRT, result, input)); break; + case LOG: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.LOG, result, input)); break; + case LOG10: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.LOG10, result, input)); break; + case SIN: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.SIN, result, input)); break; + case COS: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.COS, result, input)); break; + case TAN: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.TAN, result, input)); break; default: throw Util.shouldNotReachHere(); } gen.setResult(this, result); diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java Thu Jan 26 12:23:00 2012 +0100 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.snippets.target.amd64; + +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.util.*; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.compiler.asm.*; +import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.target.amd64.*; +import com.oracle.max.graal.compiler.util.*; + +public class AMD64MathIntrinsicOp extends AMD64LIRInstruction { + public enum Opcode { + SQRT, + SIN, COS, TAN, + LOG, LOG10; + } + + public AMD64MathIntrinsicOp(Opcode opcode, CiValue result, CiValue input) { + super(opcode, new CiValue[] {result}, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + Opcode opcode = (Opcode) code; + CiValue result = output(0); + CiValue input = input(0); + + switch (opcode) { + case SQRT: masm.sqrtsd(asDoubleReg(result), asDoubleReg(input)); break; + case LOG: masm.flog(asDoubleReg(result), asDoubleReg(input), false); break; + case LOG10: masm.flog(asDoubleReg(result), asDoubleReg(input), true); break; + case SIN: masm.fsin(asDoubleReg(result), asDoubleReg(input)); break; + case COS: masm.fcos(asDoubleReg(result), asDoubleReg(input)); break; + case TAN: masm.ftan(asDoubleReg(result), asDoubleReg(input)); break; + default: throw Util.shouldNotReachHere(); + } + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register); + } + throw Util.shouldNotReachHere(); + } +} diff -r 4aacce9c9cb9 -r d13bfce7b3dd graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/target/amd64/AMD64MathIntrinsicOpcode.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/target/amd64/AMD64MathIntrinsicOpcode.java Thu Jan 26 12:22:36 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.snippets.target.amd64; - -import static com.oracle.max.cri.ci.CiValueUtil.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.asm.*; -import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.target.amd64.*; -import com.oracle.max.graal.compiler.util.*; - -public enum AMD64MathIntrinsicOpcode implements LIROpcode { - SQRT, - SIN, COS, TAN, - LOG, LOG10; - - public LIRInstruction create(Variable result, Variable input) { - CiValue[] inputs = new CiValue[] {input}; - CiValue[] outputs = new CiValue[] {result}; - - return new AMD64LIRInstruction(this, outputs, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - emit(tasm, masm, asDoubleReg(output(0)), asDoubleReg(input(0))); - } - }; - } - - /** - * @param tasm - */ - private void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiRegister result, CiRegister input) { - switch (this) { - case SQRT: masm.sqrtsd(result, input); break; - case LOG: masm.flog(result, input, false); break; - case LOG10: masm.flog(result, input, true); break; - case SIN: masm.fsin(result, input); break; - case COS: masm.fcos(result, input); break; - case TAN: masm.ftan(result, input); break; - default: throw Util.shouldNotReachHere(); - } - } -} diff -r 4aacce9c9cb9 -r d13bfce7b3dd mx/commands.py --- a/mx/commands.py Thu Jan 26 12:22:36 2012 +0100 +++ b/mx/commands.py Thu Jan 26 12:23:00 2012 +0100 @@ -369,6 +369,7 @@ """run the GraalVM""" build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product' + mx.expand_project_in_args(args) if mx.java().debug: args = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000'] + args exe = join(_jdk(build), 'bin', mx.exe_suffix('java')) @@ -508,7 +509,7 @@ total.stop() def bench(args): - """run benchmarks and parse their ouput for results + """run benchmarks and parse their output for results Results are JSON formated : {group : {benchmark : score}}.""" resultFile = None diff -r 4aacce9c9cb9 -r d13bfce7b3dd src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/callgraph.filter --- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/callgraph.filter Thu Jan 26 12:22:36 2012 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/callgraph.filter Thu Jan 26 12:23:00 2012 +0100 @@ -1,3 +1,4 @@ colorize("name", ".*", yellow); colorize("name", ".*", pink); -colorize("leaf", "1", red); +colorize("leaf", "1", lightGray); +colorize("cutoff", "1", red); diff -r 4aacce9c9cb9 -r d13bfce7b3dd src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Thu Jan 26 12:22:36 2012 +0100 +++ b/src/share/vm/code/nmethod.cpp Thu Jan 26 12:23:00 2012 +0100 @@ -1235,6 +1235,14 @@ } _method = NULL; // Clear the method of this dead nmethod } + +#ifdef GRAAL + if (_graal_compiled_method != NULL) { + HotSpotCompiledMethod::set_nmethod(_graal_compiled_method, 0); + _graal_compiled_method = NULL; + } +#endif + // Make the class unloaded - i.e., change state and notify sweeper assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); if (is_in_use()) { diff -r 4aacce9c9cb9 -r d13bfce7b3dd src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Thu Jan 26 12:22:36 2012 +0100 +++ b/src/share/vm/compiler/compileBroker.cpp Thu Jan 26 12:23:00 2012 +0100 @@ -1120,12 +1120,14 @@ blocking);*/ } +#ifdef GRAAL if (!JavaThread::current()->is_compiling()) { method->set_queued_for_compilation(); GraalCompiler::instance()->compile_method(method, osr_bci, blocking); } else { // Recursive compile request => ignore. } +#endif /*if (blocking) { wait_for_completion(task); diff -r 4aacce9c9cb9 -r d13bfce7b3dd src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Thu Jan 26 12:22:36 2012 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Thu Jan 26 12:23:00 2012 +0100 @@ -275,10 +275,10 @@ int stack_slots = _total_frame_size / HeapWordSize; // conversion to words methodHandle method = getMethodFromHotSpotMethod(HotSpotTargetMethod::method(JNIHandles::resolve(target_method_obj))); - { - nm = GraalEnv::register_method(method, -1, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, - &_implicit_exception_table, GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, true, false, install_code); - } + + nm = GraalEnv::register_method(method, -1, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, + &_implicit_exception_table, GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, true, false, install_code); + method->clear_queued_for_compilation(); } diff -r 4aacce9c9cb9 -r d13bfce7b3dd src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Thu Jan 26 12:22:36 2012 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Thu Jan 26 12:23:00 2012 +0100 @@ -68,6 +68,7 @@ int_field(HotSpotMethodResolved, maxLocals) \ int_field(HotSpotMethodResolved, maxStackSize) \ boolean_field(HotSpotMethodResolved, canBeInlined) \ + oop_field(HotSpotMethodResolved, callback, "Lcom/oracle/max/cri/ci/CiGenericCallback;") \ end_class \ start_class(HotSpotType) \ oop_field(HotSpotType, name, "Ljava/lang/String;") \ diff -r 4aacce9c9cb9 -r d13bfce7b3dd src/share/vm/memory/heap.cpp --- a/src/share/vm/memory/heap.cpp Thu Jan 26 12:22:36 2012 +0100 +++ b/src/share/vm/memory/heap.cpp Thu Jan 26 12:23:00 2012 +0100 @@ -127,7 +127,7 @@ assert(_number_of_reserved_segments >= _number_of_committed_segments, "just checking"); // reserve space for _segmap - if (!_segmap.initialize(align_to_page_size(_number_of_reserved_segments), align_to_page_size(_number_of_committed_segments))) { + if (!_segmap.initialize(align_to_allocation_size(_number_of_reserved_segments), align_to_allocation_size(_number_of_committed_segments))) { return false; } assert(_segmap.committed_size() >= (size_t) _number_of_committed_segments, "could not commit enough space for segment map"); diff -r 4aacce9c9cb9 -r d13bfce7b3dd src/share/vm/runtime/java.cpp --- a/src/share/vm/runtime/java.cpp Thu Jan 26 12:22:36 2012 +0100 +++ b/src/share/vm/runtime/java.cpp Thu Jan 26 12:23:00 2012 +0100 @@ -425,9 +425,11 @@ #define BEFORE_EXIT_DONE 2 static jint volatile _before_exit_status = BEFORE_EXIT_NOT_RUN; +#ifdef GRAAL if (UseGraal) { GraalCompiler::instance()->exit(); } +#endif // Note: don't use a Mutex to guard the entire before_exit(), as // JVMTI post_thread_end_event and post_vm_death_event will run native code.