001/* 002 * Copyright (c) 2009, 2015, 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; 024 025import static jdk.internal.jvmci.code.ValueUtil.*; 026 027import java.util.*; 028 029import jdk.internal.jvmci.code.*; 030import jdk.internal.jvmci.meta.*; 031 032import com.oracle.graal.lir.LIRInstruction.OperandFlag; 033import com.oracle.graal.lir.LIRInstruction.OperandMode; 034import com.oracle.graal.lir.framemap.*; 035import com.oracle.graal.lir.util.*; 036 037/** 038 * This class represents garbage collection and deoptimization information attached to a LIR 039 * instruction. 040 */ 041public class LIRFrameState { 042 043 public final BytecodeFrame topFrame; 044 private final VirtualObject[] virtualObjects; 045 public final LabelRef exceptionEdge; 046 protected DebugInfo debugInfo; 047 048 private IndexedValueMap liveBasePointers; 049 050 public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge) { 051 this.topFrame = topFrame; 052 this.virtualObjects = virtualObjects; 053 this.exceptionEdge = exceptionEdge; 054 } 055 056 public boolean hasDebugInfo() { 057 return debugInfo != null; 058 } 059 060 public DebugInfo debugInfo() { 061 assert debugInfo != null : "debug info not allocated yet"; 062 return debugInfo; 063 } 064 065 /** 066 * Iterates the frame state and calls the {@link InstructionValueProcedure} for every variable. 067 * 068 * @param proc The procedure called for variables. 069 */ 070 public void forEachState(LIRInstruction inst, InstructionValueProcedure proc) { 071 for (BytecodeFrame cur = topFrame; cur != null; cur = cur.caller()) { 072 processValues(inst, cur.values, proc); 073 } 074 if (virtualObjects != null) { 075 for (VirtualObject obj : virtualObjects) { 076 processValues(inst, obj.getValues(), proc); 077 } 078 } 079 if (liveBasePointers != null) { 080 liveBasePointers.forEach(inst, OperandMode.ALIVE, STATE_FLAGS, proc); 081 } 082 } 083 084 /** 085 * Iterates the frame state and calls the {@link InstructionValueProcedure} for every variable. 086 * 087 * @param proc The procedure called for variables. 088 */ 089 public void forEachState(LIRInstruction inst, InstructionValueConsumer proc) { 090 for (BytecodeFrame cur = topFrame; cur != null; cur = cur.caller()) { 091 processValues(inst, cur.values, proc); 092 } 093 if (virtualObjects != null) { 094 for (VirtualObject obj : virtualObjects) { 095 processValues(inst, obj.getValues(), proc); 096 } 097 } 098 if (liveBasePointers != null) { 099 liveBasePointers.forEach(inst, OperandMode.ALIVE, STATE_FLAGS, proc); 100 } 101 } 102 103 /** 104 * We filter out constant and illegal values ourself before calling the procedure, so 105 * {@link OperandFlag#CONST} and {@link OperandFlag#ILLEGAL} need not be set. 106 */ 107 protected static final EnumSet<OperandFlag> STATE_FLAGS = EnumSet.of(OperandFlag.REG, OperandFlag.STACK); 108 109 protected void processValues(LIRInstruction inst, Value[] values, InstructionValueProcedure proc) { 110 for (int i = 0; i < values.length; i++) { 111 Value value = values[i]; 112 if (isIllegal(value)) { 113 continue; 114 } 115 if (value instanceof AllocatableValue) { 116 Value result = proc.doValue(inst, value, OperandMode.ALIVE, STATE_FLAGS); 117 if (!value.identityEquals(result)) { 118 values[i] = result; 119 } 120 } else if (value instanceof StackLockValue) { 121 StackLockValue monitor = (StackLockValue) value; 122 Value owner = monitor.getOwner(); 123 if (owner instanceof AllocatableValue) { 124 monitor.setOwner(proc.doValue(inst, owner, OperandMode.ALIVE, STATE_FLAGS)); 125 } 126 Value slot = monitor.getSlot(); 127 if (isVirtualStackSlot(slot)) { 128 monitor.setSlot(asStackSlotValue(proc.doValue(inst, slot, OperandMode.ALIVE, STATE_FLAGS))); 129 } 130 } else { 131 assert unprocessed(value); 132 } 133 } 134 } 135 136 protected void processValues(LIRInstruction inst, Value[] values, InstructionValueConsumer proc) { 137 for (int i = 0; i < values.length; i++) { 138 Value value = values[i]; 139 if (isIllegal(value)) { 140 continue; 141 } else if (value instanceof AllocatableValue) { 142 proc.visitValue(inst, value, OperandMode.ALIVE, STATE_FLAGS); 143 } else if (value instanceof StackLockValue) { 144 StackLockValue monitor = (StackLockValue) value; 145 Value owner = monitor.getOwner(); 146 if (owner instanceof AllocatableValue) { 147 proc.visitValue(inst, owner, OperandMode.ALIVE, STATE_FLAGS); 148 } 149 Value slot = monitor.getSlot(); 150 if (isVirtualStackSlot(slot)) { 151 proc.visitValue(inst, slot, OperandMode.ALIVE, STATE_FLAGS); 152 } 153 } else { 154 assert unprocessed(value); 155 } 156 } 157 } 158 159 private boolean unprocessed(Value value) { 160 if (isIllegal(value)) { 161 // Ignore dead local variables. 162 return true; 163 } else if (isConstant(value)) { 164 // Ignore constants, the register allocator does not need to see them. 165 return true; 166 } else if (isVirtualObject(value)) { 167 assert Arrays.asList(virtualObjects).contains(value); 168 return true; 169 } else { 170 return false; 171 } 172 } 173 174 /** 175 * Called by the register allocator to initialize the frame state. 176 * 177 * @param frameMap The frame map. 178 * @param canHaveRegisters True if there can be any register map entries. 179 */ 180 public void initDebugInfo(FrameMap frameMap, boolean canHaveRegisters) { 181 debugInfo = new DebugInfo(topFrame, virtualObjects); 182 } 183 184 public IndexedValueMap getLiveBasePointers() { 185 return liveBasePointers; 186 } 187 188 public void setLiveBasePointers(IndexedValueMap liveBasePointers) { 189 this.liveBasePointers = liveBasePointers; 190 } 191 192 @Override 193 public String toString() { 194 return debugInfo != null ? debugInfo.toString() : topFrame != null ? topFrame.toString() : "<empty>"; 195 } 196}