1 /* 2 * Copyright (c) 2014, 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 package org.graalvm.compiler.lir.framemap; 24 25 import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot; 26 27 import java.util.ArrayList; 28 import java.util.BitSet; 29 import java.util.EnumSet; 30 import java.util.List; 31 32 import org.graalvm.compiler.core.common.LIRKind; 33 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; 34 import org.graalvm.compiler.debug.Debug; 35 import org.graalvm.compiler.debug.GraalError; 36 import org.graalvm.compiler.lir.InstructionValueConsumer; 37 import org.graalvm.compiler.lir.LIR; 38 import org.graalvm.compiler.lir.LIRInstruction; 39 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag; 40 import org.graalvm.compiler.lir.LIRInstruction.OperandMode; 41 import org.graalvm.compiler.lir.VirtualStackSlot; 42 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 43 44 import jdk.vm.ci.code.CallingConvention; 45 import jdk.vm.ci.code.CodeCacheProvider; 46 import jdk.vm.ci.code.RegisterConfig; 47 import jdk.vm.ci.meta.JavaKind; 48 import jdk.vm.ci.meta.Value; 49 import jdk.vm.ci.meta.ValueKind; 50 51 /** 52 * A FrameMapBuilder that records allocation. 53 */ 54 public class FrameMapBuilderImpl extends FrameMapBuilderTool { 55 56 private final RegisterConfig registerConfig; 57 private final CodeCacheProvider codeCache; 58 private final FrameMap frameMap; 59 private final List<VirtualStackSlot> stackSlots; 60 private final List<CallingConvention> calls; 61 private int numStackSlots; 62 63 public FrameMapBuilderImpl(FrameMap frameMap, CodeCacheProvider codeCache, RegisterConfig registerConfig) { 64 assert registerConfig != null : "No register config!"; 65 this.registerConfig = registerConfig == null ? codeCache.getRegisterConfig() : registerConfig; 66 this.codeCache = codeCache; 67 this.frameMap = frameMap; 68 this.stackSlots = new ArrayList<>(); 69 this.calls = new ArrayList<>(); 70 this.numStackSlots = 0; 71 } 72 73 @Override 74 public VirtualStackSlot allocateSpillSlot(ValueKind<?> kind) { 75 SimpleVirtualStackSlot slot = new SimpleVirtualStackSlot(numStackSlots++, kind); 76 stackSlots.add(slot); 77 return slot; 78 } 79 80 @Override 81 public VirtualStackSlot allocateStackSlots(int slots, BitSet objects, List<VirtualStackSlot> outObjectStackSlots) { 82 if (slots == 0) { 83 return null; 84 } 85 if (outObjectStackSlots != null) { 86 throw GraalError.unimplemented(); 87 } 88 VirtualStackSlotRange slot = new VirtualStackSlotRange(numStackSlots++, slots, objects, LIRKind.fromJavaKind(frameMap.getTarget().arch, JavaKind.Object)); 89 stackSlots.add(slot); 90 return slot; 91 } 92 93 @Override 94 public RegisterConfig getRegisterConfig() { 95 return registerConfig; 96 } 97 98 @Override 99 public CodeCacheProvider getCodeCache() { 100 return codeCache; 101 } 102 103 @Override 104 public FrameMap getFrameMap() { 105 return frameMap; 106 } 107 108 @Override 109 public int getNumberOfStackSlots() { 110 return numStackSlots; 111 } 112 113 @Override 114 public void callsMethod(CallingConvention cc) { 115 calls.add(cc); 116 } 117 118 @Override 119 @SuppressWarnings("try") 120 public FrameMap buildFrameMap(LIRGenerationResult res) { 121 if (Debug.isEnabled()) { 122 verifyStackSlotAllocation(res); 123 } 124 for (CallingConvention cc : calls) { 125 frameMap.callsMethod(cc); 126 } 127 frameMap.finish(); 128 return frameMap; 129 } 130 131 private static void verifyStackSlotAllocation(LIRGenerationResult res) { 132 LIR lir = res.getLIR(); 133 InstructionValueConsumer verifySlots = (LIRInstruction op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) -> { 134 assert !isVirtualStackSlot(value) : String.format("Instruction %s contains a virtual stack slot %s", op, value); 135 }; 136 for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) { 137 lir.getLIRforBlock(block).forEach(op -> { 138 op.visitEachInput(verifySlots); 139 op.visitEachAlive(verifySlots); 140 op.visitEachState(verifySlots); 141 142 op.visitEachTemp(verifySlots); 143 op.visitEachOutput(verifySlots); 144 }); 145 } 146 } 147 148 @Override 149 public List<VirtualStackSlot> getStackSlots() { 150 return stackSlots; 151 } 152 153 }