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 */ 23package org.graalvm.compiler.lir.framemap; 24 25import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot; 26 27import java.util.ArrayList; 28import java.util.BitSet; 29import java.util.EnumSet; 30import java.util.List; 31 32import org.graalvm.compiler.core.common.LIRKind; 33import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; 34import org.graalvm.compiler.debug.DebugContext; 35import org.graalvm.compiler.debug.GraalError; 36import org.graalvm.compiler.lir.InstructionValueConsumer; 37import org.graalvm.compiler.lir.LIR; 38import org.graalvm.compiler.lir.LIRInstruction; 39import org.graalvm.compiler.lir.LIRInstruction.OperandFlag; 40import org.graalvm.compiler.lir.LIRInstruction.OperandMode; 41import org.graalvm.compiler.lir.VirtualStackSlot; 42import org.graalvm.compiler.lir.gen.LIRGenerationResult; 43 44import jdk.vm.ci.code.CallingConvention; 45import jdk.vm.ci.code.CodeCacheProvider; 46import jdk.vm.ci.code.RegisterConfig; 47import jdk.vm.ci.meta.JavaKind; 48import jdk.vm.ci.meta.Value; 49import jdk.vm.ci.meta.ValueKind; 50 51/** 52 * A FrameMapBuilder that records allocation. 53 */ 54public 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 DebugContext debug = res.getLIR().getDebug(); 122 if (debug.areScopesEnabled()) { 123 verifyStackSlotAllocation(res); 124 } 125 for (CallingConvention cc : calls) { 126 frameMap.callsMethod(cc); 127 } 128 frameMap.finish(); 129 return frameMap; 130 } 131 132 private static void verifyStackSlotAllocation(LIRGenerationResult res) { 133 LIR lir = res.getLIR(); 134 InstructionValueConsumer verifySlots = (LIRInstruction op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) -> { 135 assert !isVirtualStackSlot(value) : String.format("Instruction %s contains a virtual stack slot %s", op, value); 136 }; 137 for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) { 138 lir.getLIRforBlock(block).forEach(op -> { 139 op.visitEachInput(verifySlots); 140 op.visitEachAlive(verifySlots); 141 op.visitEachState(verifySlots); 142 143 op.visitEachTemp(verifySlots); 144 op.visitEachOutput(verifySlots); 145 }); 146 } 147 } 148 149 @Override 150 public List<VirtualStackSlot> getStackSlots() { 151 return stackSlots; 152 } 153 154} 155