1 /* 2 * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 26 package org.graalvm.compiler.core.amd64; 27 28 import static org.graalvm.compiler.core.amd64.AMD64NodeLIRBuilder.Options.MitigateSpeculativeExecutionAttacks; 29 30 import org.graalvm.compiler.core.gen.NodeLIRBuilder; 31 import org.graalvm.compiler.debug.GraalError; 32 import org.graalvm.compiler.lir.LIRFrameState; 33 import org.graalvm.compiler.lir.amd64.AMD64Call; 34 import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 35 import org.graalvm.compiler.nodes.DeoptimizingNode; 36 import org.graalvm.compiler.nodes.FixedNode; 37 import org.graalvm.compiler.nodes.FixedWithNextNode; 38 import org.graalvm.compiler.nodes.IfNode; 39 import org.graalvm.compiler.nodes.IndirectCallTargetNode; 40 import org.graalvm.compiler.nodes.StructuredGraph; 41 import org.graalvm.compiler.nodes.ValueNode; 42 import org.graalvm.compiler.nodes.calc.IntegerDivRemNode; 43 import org.graalvm.compiler.nodes.calc.IntegerDivRemNode.Op; 44 import org.graalvm.compiler.nodes.cfg.Block; 45 import org.graalvm.compiler.options.Option; 46 import org.graalvm.compiler.options.OptionKey; 47 import org.graalvm.compiler.options.OptionType; 48 import org.graalvm.compiler.options.OptionValues; 49 50 import jdk.vm.ci.amd64.AMD64; 51 import jdk.vm.ci.meta.AllocatableValue; 52 import jdk.vm.ci.meta.Value; 53 54 public abstract class AMD64NodeLIRBuilder extends NodeLIRBuilder { 55 56 public static class Options { 57 // @formatter:off 58 @Option(help = "AMD64: Emit lfence instructions at the beginning of basic blocks", type = OptionType.Expert) 59 public static final OptionKey<Boolean> MitigateSpeculativeExecutionAttacks = new OptionKey<>(false); 60 // @formatter:on 61 } 62 63 public AMD64NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, AMD64NodeMatchRules nodeMatchRules) { 64 super(graph, gen, nodeMatchRules); 65 } 66 67 @Override 68 protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { 69 Value targetAddressSrc = operand(callTarget.computedAddress()); 70 AllocatableValue targetAddress = AMD64.rax.asValue(targetAddressSrc.getValueKind()); 71 gen.emitMove(targetAddress, targetAddressSrc); 72 append(new AMD64Call.IndirectCallOp(callTarget.targetMethod(), result, parameters, temps, targetAddress, callState)); 73 } 74 75 @Override 76 protected boolean peephole(ValueNode valueNode) { 77 if (valueNode instanceof IntegerDivRemNode) { 78 AMD64ArithmeticLIRGenerator arithmeticGen = (AMD64ArithmeticLIRGenerator) gen.getArithmetic(); 79 IntegerDivRemNode divRem = (IntegerDivRemNode) valueNode; 80 FixedNode node = divRem.next(); 81 while (true) { 82 if (node instanceof IfNode) { 83 IfNode ifNode = (IfNode) node; 84 double probability = ifNode.getTrueSuccessorProbability(); 85 if (probability == 1.0) { 86 node = ifNode.trueSuccessor(); 87 } else if (probability == 0.0) { 88 node = ifNode.falseSuccessor(); 89 } else { 90 break; 91 } 92 } else if (!(node instanceof FixedWithNextNode)) { 93 break; 94 } 95 96 FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) node; 97 if (fixedWithNextNode instanceof IntegerDivRemNode) { 98 IntegerDivRemNode otherDivRem = (IntegerDivRemNode) fixedWithNextNode; 99 if (divRem.getOp() != otherDivRem.getOp() && divRem.getType() == otherDivRem.getType()) { 100 if (otherDivRem.getX() == divRem.getX() && otherDivRem.getY() == divRem.getY() && !hasOperand(otherDivRem)) { 101 Value[] results; 102 switch (divRem.getType()) { 103 case SIGNED: 104 results = arithmeticGen.emitSignedDivRem(operand(divRem.getX()), operand(divRem.getY()), state((DeoptimizingNode) valueNode)); 105 break; 106 case UNSIGNED: 107 results = arithmeticGen.emitUnsignedDivRem(operand(divRem.getX()), operand(divRem.getY()), state((DeoptimizingNode) valueNode)); 108 break; 109 default: 110 throw GraalError.shouldNotReachHere(); 111 } 112 switch (divRem.getOp()) { 113 case DIV: 114 assert otherDivRem.getOp() == Op.REM; 115 setResult(divRem, results[0]); 116 setResult(otherDivRem, results[1]); 117 break; 118 case REM: 119 assert otherDivRem.getOp() == Op.DIV; 120 setResult(divRem, results[1]); 121 setResult(otherDivRem, results[0]); 122 break; 123 default: 124 throw GraalError.shouldNotReachHere(); 125 } 126 return true; 127 } 128 } 129 } 130 node = fixedWithNextNode.next(); 131 } 132 } 133 return false; 134 } 135 136 @Override 137 public AMD64LIRGenerator getLIRGeneratorTool() { 138 return (AMD64LIRGenerator) gen; 139 } 140 141 @Override 142 public void doBlockPrologue(Block block, OptionValues options) { 143 if (MitigateSpeculativeExecutionAttacks.getValue(options)) { 144 boolean hasControlSplitPredecessor = false; 145 for (Block b : block.getPredecessors()) { 146 if (b.getSuccessorCount() > 1) { 147 hasControlSplitPredecessor = true; 148 break; 149 } 150 } 151 boolean isStartBlock = block.getPredecessorCount() == 0; 152 if (hasControlSplitPredecessor || isStartBlock) { 153 getLIRGeneratorTool().emitLFence(); 154 } 155 } 156 } 157 }