org.eclipse.objectteams.otredyn.bytecode.asm.StackBalanceAnalyzer.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.objectteams.otredyn.bytecode.asm.StackBalanceAnalyzer.java

Source

/**********************************************************************
 * This file is part of "Object Teams Dynamic Runtime Environment"
 * 
 * Copyright 2014 Stephan Herrmann.
 * 
 * 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
 * 
 * Please visit http://www.eclipse.org/objectteams for updates and contact.
 * 
 * Contributors:
 *      Stephan Herrmann - Initial API and implementation
 **********************************************************************/
package org.eclipse.objectteams.otredyn.bytecode.asm;

import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;

public class StackBalanceAnalyzer {

    /**
     * Answer an array of insertion points such that each element points to the start of a loading sequence
     * that produces as many bytes on the stack as are required for the corresponding type in 'args'.
     * 
     * @param location point in an instruction list at which all args are present on the stack
     * @param args types of the arguments on the top of the stack at 'location'
     * @return one instruction per element in 'args'
     */
    public static AbstractInsnNode[] findInsertionPointsBefore(AbstractInsnNode location, Type[] args) {
        AbstractInsnNode[] nodes = new AbstractInsnNode[args.length];
        AbstractInsnNode current = location;
        for (int i = args.length - 1; i >= 0; i--) {
            current = findInsertionPointBefore(current, -args[i].getSize());
            nodes[i] = current;
        }
        return nodes;
    }

    /**
     * Answer the closest point in the instruction list before 'location'
     * where the stack has 'stackDifference' more bytes than at 'location'.
     * Negative 'stackDifference' means we are looking for smaller stack.
     * 
     * @param location start searching here
     * @param stackDifference 
     * @return the last instruction before which the required stack size was present 
     */
    public static AbstractInsnNode findInsertionPointBefore(AbstractInsnNode location, int stackDifference) {
        int offset = 0;
        AbstractInsnNode current = location;
        while (offset != stackDifference) {
            current = location.getPrevious();
            if (current == null)
                return null;
            offset -= SIZE[current.getOpcode()];
        }
        return current;
    }

    // Field from org.objectweb.asm.Frame, made accessible:
    /**
     * The stack size variation corresponding to each JVM instruction. This
     * stack variation is equal to the size of the values produced by an
     * instruction, minus the size of the values consumed by this instruction.
     */
    static final int[] SIZE;

    /**
     * Computes the stack size variation corresponding to each JVM instruction.
     */
    static {
        int i;
        int[] b = new int[202];
        String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
                + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
                + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED" + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
        for (i = 0; i < b.length; ++i) {
            b[i] = s.charAt(i) - 'E';
        }
        SIZE = b;
    }

}