001/* 002 * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.lir.framemap; 024 025import static jdk.internal.jvmci.code.ValueUtil.*; 026 027import java.util.*; 028 029import jdk.internal.jvmci.code.*; 030import jdk.internal.jvmci.common.*; 031import com.oracle.graal.debug.*; 032import com.oracle.graal.debug.Debug.*; 033import jdk.internal.jvmci.meta.*; 034 035import com.oracle.graal.compiler.common.cfg.*; 036import com.oracle.graal.lir.*; 037import com.oracle.graal.lir.LIRInstruction.OperandFlag; 038import com.oracle.graal.lir.LIRInstruction.OperandMode; 039import com.oracle.graal.lir.gen.*; 040import com.oracle.graal.lir.stackslotalloc.*; 041 042/** 043 * A FrameMapBuilder that records allocation. 044 */ 045public class FrameMapBuilderImpl implements FrameMapBuilderTool { 046 047 private final RegisterConfig registerConfig; 048 private final CodeCacheProvider codeCache; 049 private final FrameMap frameMap; 050 private final List<VirtualStackSlot> stackSlots; 051 private final List<CallingConvention> calls; 052 private int numStackSlots; 053 054 public FrameMapBuilderImpl(FrameMap frameMap, CodeCacheProvider codeCache, RegisterConfig registerConfig) { 055 assert registerConfig != null : "No register config!"; 056 this.registerConfig = registerConfig == null ? codeCache.getRegisterConfig() : registerConfig; 057 this.codeCache = codeCache; 058 this.frameMap = frameMap; 059 this.stackSlots = new ArrayList<>(); 060 this.calls = new ArrayList<>(); 061 this.numStackSlots = 0; 062 } 063 064 public VirtualStackSlot allocateSpillSlot(LIRKind kind) { 065 SimpleVirtualStackSlot slot = new SimpleVirtualStackSlot(numStackSlots++, kind); 066 stackSlots.add(slot); 067 return slot; 068 } 069 070 public VirtualStackSlot allocateStackSlots(int slots, BitSet objects, List<VirtualStackSlot> outObjectStackSlots) { 071 if (slots == 0) { 072 return null; 073 } 074 if (outObjectStackSlots != null) { 075 throw JVMCIError.unimplemented(); 076 } 077 VirtualStackSlotRange slot = new VirtualStackSlotRange(numStackSlots++, slots, objects); 078 stackSlots.add(slot); 079 return slot; 080 } 081 082 public RegisterConfig getRegisterConfig() { 083 return registerConfig; 084 } 085 086 public CodeCacheProvider getCodeCache() { 087 return codeCache; 088 } 089 090 public FrameMap getFrameMap() { 091 return frameMap; 092 } 093 094 public int getNumberOfStackSlots() { 095 return numStackSlots; 096 } 097 098 public void callsMethod(CallingConvention cc) { 099 calls.add(cc); 100 } 101 102 public FrameMap buildFrameMap(LIRGenerationResult res, StackSlotAllocator allocator) { 103 try (Scope s = Debug.scope("StackSlotAllocation")) { 104 allocator.allocateStackSlots(this, res); 105 if (Debug.isEnabled()) { 106 verifyStackSlotAllocation(res); 107 } 108 } 109 for (CallingConvention cc : calls) { 110 frameMap.callsMethod(cc); 111 } 112 frameMap.finish(); 113 return frameMap; 114 } 115 116 private static void verifyStackSlotAllocation(LIRGenerationResult res) { 117 LIR lir = res.getLIR(); 118 InstructionValueConsumer verifySlots = (LIRInstruction op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) -> { 119 assert !isVirtualStackSlot(value) : String.format("Instruction %s contains a virtual stack slot %s", op, value); 120 }; 121 for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) { 122 lir.getLIRforBlock(block).forEach(op -> { 123 op.visitEachInput(verifySlots); 124 op.visitEachAlive(verifySlots); 125 op.visitEachState(verifySlots); 126 127 op.visitEachTemp(verifySlots); 128 op.visitEachOutput(verifySlots); 129 }); 130 } 131 } 132 133 public List<VirtualStackSlot> getStackSlots() { 134 return stackSlots; 135 } 136 137}