/******************************************************************************* * Copyright (c) 2002,2006 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package com.ibm.wala.shrikeBT.info; import com.ibm.wala.shrikeBT.ExceptionHandler; import com.ibm.wala.shrikeBT.IInstruction; import com.ibm.wala.shrikeBT.ILoadInstruction; import com.ibm.wala.shrikeBT.IStoreInstruction; import com.ibm.wala.shrikeBT.MethodData; import com.ibm.wala.shrikeBT.Util; /** * This method annotation parcels out fresh local variables for use as temporaries by instrumentation code. It assumes that local * variables are not allocated by any other mechanism. */ public class LocalAllocator implements MethodData.Results { private final static String key = LocalAllocator.class.getName(); private int nextLocal; LocalAllocator(MethodData info) { recalculateFrom(info); } private void recalculateFrom(MethodData info) { IInstruction[] instructions = info.getInstructions(); final int[] max = { Util.getParamsWordSize(info.getSignature()) + (info.getIsStatic() ? 0 : 1) }; IInstruction.Visitor visitor = new IInstruction.Visitor() { @Override public void visitLocalLoad(ILoadInstruction instruction) { int v = instruction.getVarIndex() + Util.getWordSize(instruction.getType()); if (v > max[0]) { max[0] = v; } } @Override public void visitLocalStore(IStoreInstruction instruction) { int v = instruction.getVarIndex() + Util.getWordSize(instruction.getType()); if (v > max[0]) { max[0] = v; } } }; for (int i = 0; i < instructions.length; i++) { instructions[i].visit(visitor); } nextLocal = max[0]; } private int allocateLocals(int count) { int r = nextLocal; nextLocal += count; return r; } /** * This should not be called by clients. */ @Override public boolean notifyUpdate(MethodData info, IInstruction[] newInstructions, ExceptionHandler[][] newHandlers, int[] newInstructionMap) { return false; } /** * Allocates a new local variable of the specified type. */ public static int allocate(MethodData info, int count) throws IllegalArgumentException { if (info == null) { throw new IllegalArgumentException(); } LocalAllocator l = (LocalAllocator) info.getInfo(key); if (l == null) { l = new LocalAllocator(info); info.putInfo(key, l); } return l.allocateLocals(count); } public static int allocate(MethodData info, String type) throws IllegalArgumentException { return allocate(info, type == null ? 2 : Util.getWordSize(type)); } /** * Allocates a new local that will fit any type. */ public static int allocate(MethodData info) throws IllegalArgumentException { return allocate(info, null); } }