123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- package org.aspectj.apache.bcel.verifier.util;
-
- import java.io.PrintWriter;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Iterator;
-
- import org.aspectj.apache.bcel.Constants;
- import org.aspectj.apache.bcel.classfile.ConstantPool;
- import org.aspectj.apache.bcel.classfile.Utility;
- import org.aspectj.apache.bcel.generic.BranchHandle;
- import org.aspectj.apache.bcel.generic.CodeExceptionGen;
- import org.aspectj.apache.bcel.generic.FieldInstruction;
- import org.aspectj.apache.bcel.generic.IINC;
- import org.aspectj.apache.bcel.generic.Instruction;
- import org.aspectj.apache.bcel.generic.InstructionBranch;
- import org.aspectj.apache.bcel.generic.InstructionByte;
- import org.aspectj.apache.bcel.generic.InstructionCP;
- import org.aspectj.apache.bcel.generic.InstructionConstants;
- import org.aspectj.apache.bcel.generic.InstructionHandle;
- import org.aspectj.apache.bcel.generic.InstructionSelect;
- import org.aspectj.apache.bcel.generic.InvokeInstruction;
- import org.aspectj.apache.bcel.generic.MULTIANEWARRAY;
- import org.aspectj.apache.bcel.generic.MethodGen;
- import org.aspectj.apache.bcel.generic.ObjectType;
- import org.aspectj.apache.bcel.generic.RET;
- import org.aspectj.apache.bcel.generic.Type;
- import org.aspectj.apache.bcel.verifier.InstructionWalker;
-
- /* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2002 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (https://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" and
- * "Apache BCEL" must not be used to endorse or promote products
- * derived from this software without prior written permission. For
- * written permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * "Apache BCEL", nor may "Apache" appear in their name, without
- * prior written permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <https://www.apache.org/>.
- */
-
- /**
- * Factory creates il.append() statements, and sets instruction targets. A helper class for BCELifier.
- *
- * @see BCELifier
- * @version $Id: BCELFactory.java,v 1.6 2009/09/14 20:29:10 aclement Exp $
- * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
- */
- class BCELFactory extends org.aspectj.apache.bcel.verifier.EmptyInstVisitor {
- private final MethodGen _mg;
- private final PrintWriter _out;
- private final ConstantPool _cp;
-
- BCELFactory(MethodGen mg, PrintWriter out) {
- _mg = mg;
- _cp = mg.getConstantPool();
- _out = out;
- }
-
- private final HashMap<Instruction, InstructionHandle> branch_map = new HashMap<Instruction, InstructionHandle>(); // Map<Instruction,
- // InstructionHandle>
-
- public void start() {
- if (!_mg.isAbstract() && !_mg.isNative()) {
- for (InstructionHandle ih = _mg.getInstructionList().getStart(); ih != null; ih = ih.getNext()) {
- Instruction i = ih.getInstruction();
-
- if (i instanceof InstructionBranch) {
- branch_map.put(i, ih); // memorize container
- }
-
- if (ih.hasTargeters()) {
- if (i instanceof InstructionBranch) {
- _out.println(" InstructionHandle ih_" + ih.getPosition() + ";");
- } else {
- _out.print(" InstructionHandle ih_" + ih.getPosition() + " = ");
- }
- } else {
- _out.print(" ");
- }
-
- if (!visitInstruction(i)) {
- InstructionWalker.accept(i, this);
- }
- }
-
- updateBranchTargets();
- updateExceptionHandlers();
- }
- }
-
- private boolean visitInstruction(Instruction i) {
- short opcode = i.getOpcode();
-
- if (InstructionConstants.INSTRUCTIONS[opcode] != null && !i.isConstantInstruction() && !i.isReturnInstruction()) { // Handled
- // below
- _out.println("il.append(InstructionConstants." + i.getName().toUpperCase() + ");");
- return true;
- }
-
- return false;
- }
-
- public void visitLocalVariableInstruction(Instruction i) {
- short opcode = i.getOpcode();
- Type type = i.getType(_cp);
-
- if (opcode == Constants.IINC) {
- _out.println("il.append(new IINC(" + i.getIndex() + ", " + ((IINC) i).getIncrement() + "));");
- } else {
- String kind = opcode < Constants.ISTORE ? "Load" : "Store";
- _out.println("il.append(_factory.create" + kind + "(" + BCELifier.printType(type) + ", " + i.getIndex() + "));");
- }
- }
-
- @Override
- public void visitArrayInstruction(Instruction i) {
- short opcode = i.getOpcode();
- Type type = i.getType(_cp);
- String kind = opcode < Constants.IASTORE ? "Load" : "Store";
-
- _out.println("il.append(_factory.createArray" + kind + "(" + BCELifier.printType(type) + "));");
- }
-
- public void visitFieldInstruction(FieldInstruction i) {
- short opcode = i.getOpcode();
-
- String class_name = i.getClassName(_cp);
- String field_name = i.getFieldName(_cp);
- Type type = i.getFieldType(_cp);
-
- _out.println("il.append(_factory.createFieldAccess(\"" + class_name + "\", \"" + field_name + "\", "
- + BCELifier.printType(type) + ", " + "Constants." + Constants.OPCODE_NAMES[opcode].toUpperCase() + "));");
- }
-
- @Override
- public void visitInvokeInstruction(InvokeInstruction i) {
- short opcode = i.getOpcode();
- String class_name = i.getClassName(_cp);
- String method_name = i.getMethodName(_cp);
- Type type = i.getReturnType(_cp);
- Type[] arg_types = i.getArgumentTypes(_cp);
-
- _out.println("il.append(_factory.createInvoke(\"" + class_name + "\", \"" + method_name + "\", "
- + BCELifier.printType(type) + ", " + BCELifier.printArgumentTypes(arg_types) + ", " + "Constants."
- + Constants.OPCODE_NAMES[opcode].toUpperCase() + "));");
- }
-
- @Override
- public void visitAllocationInstruction(Instruction i) {
- Type type;
-
- if (i.isConstantPoolInstruction()) {
- type = ((InstructionCP) i).getType(_cp);
- } else {
- type = ((InstructionByte) i).getType();
- }
-
- short opcode = i.getOpcode();
- int dim = 1;
-
- switch (opcode) {
- case Constants.NEW:
- _out.println("il.append(_factory.createNew(\"" + ((ObjectType) type).getClassName() + "\"));");
- break;
-
- case Constants.MULTIANEWARRAY:
- dim = ((MULTIANEWARRAY) i).getDimensions();
- case Constants.ANEWARRAY:
- case Constants.NEWARRAY:
- _out.println("il.append(_factory.createNewArray(" + BCELifier.printType(type) + ", (short) " + dim + "));");
- break;
-
- default:
- throw new RuntimeException("Oops: " + opcode);
- }
- }
-
- private void createConstant(Object value) {
- String embed = value.toString();
-
- if (value instanceof String) {
- embed = '"' + Utility.convertString(value.toString()) + '"';
- } else if (value instanceof Character) {
- embed = "(char)0x" + Integer.toHexString(((Character) value).charValue());
- }
-
- _out.println("il.append(new PUSH(_cp, " + embed + "));");
- }
-
- @Override
- public void visitLDC(Instruction i) {
- createConstant(i.getValue(_cp));
- }
-
- @Override
- public void visitLDC2_W(Instruction i) {
- createConstant(i.getValue(_cp));
- }
-
- @Override
- public void visitConstantPushInstruction(Instruction i) {
- createConstant(i.getValue());
- }
-
- @Override
- public void visitINSTANCEOF(Instruction i) {
- Type type = i.getType(_cp);
-
- _out.println("il.append(new INSTANCEOF(_cp.addClass(" + BCELifier.printType(type) + ")));");
- }
-
- @Override
- public void visitCHECKCAST(Instruction i) {
- Type type = i.getType(_cp);
-
- _out.println("il.append(_factory.createCheckCast(" + BCELifier.printType(type) + "));");
- }
-
- @Override
- public void visitReturnInstruction(Instruction i) {
- Type type = i.getType(_cp);
-
- _out.println("il.append(_factory.createReturn(" + BCELifier.printType(type) + "));");
- }
-
- // Memorize BranchInstructions that need an update
- private final ArrayList<InstructionBranch> branches = new ArrayList<InstructionBranch>();
-
- @Override
- public void visitBranchInstruction(InstructionBranch bi) {
- BranchHandle bh = (BranchHandle) branch_map.get(bi);
- int pos = bh.getPosition();
- String name = bi.getName() + "_" + pos;
-
- if (bi instanceof InstructionSelect) {
- InstructionSelect s = (InstructionSelect) bi;
- branches.add(bi);
-
- StringBuffer args = new StringBuffer("new int[] { ");
- int[] matchs = s.getMatchs();
-
- for (int i = 0; i < matchs.length; i++) {
- args.append(matchs[i]);
-
- if (i < matchs.length - 1) {
- args.append(", ");
- }
- }
-
- args.append(" }");
-
- _out.print(" Select " + name + " = new " + bi.getName().toUpperCase() + "(" + args + ", new InstructionHandle[] { ");
-
- for (int i = 0; i < matchs.length; i++) {
- _out.print("null");
-
- if (i < matchs.length - 1) {
- _out.print(", ");
- }
- }
-
- _out.println(");");
- } else {
- int t_pos = bh.getTarget().getPosition();
- String target;
-
- if (pos > t_pos) {
- target = "ih_" + t_pos;
- } else {
- branches.add(bi);
- target = "null";
- }
-
- _out.println(" BranchInstruction " + name + " = _factory.createBranchInstruction(" + "Constants."
- + bi.getName().toUpperCase() + ", " + target + ");");
- }
-
- if (bh.hasTargeters()) {
- _out.println(" ih_" + pos + " = il.append(" + name + ");");
- } else {
- _out.println(" il.append(" + name + ");");
- }
- }
-
- @Override
- public void visitRET(RET i) {
- _out.println("il.append(new RET(" + i.getIndex() + ")));");
- }
-
- private void updateBranchTargets() {
- for (Iterator<InstructionBranch> i = branches.iterator(); i.hasNext();) {
- InstructionBranch bi = i.next();
- BranchHandle bh = (BranchHandle) branch_map.get(bi);
- int pos = bh.getPosition();
- String name = bi.getName() + "_" + pos;
- int t_pos = bh.getTarget().getPosition();
-
- _out.println(" " + name + ".setTarget(ih_" + t_pos + ");");
-
- if (bi instanceof InstructionSelect) {
- InstructionHandle[] ihs = ((InstructionSelect) bi).getTargets();
-
- for (int j = 0; j < ihs.length; j++) {
- t_pos = ihs[j].getPosition();
-
- _out.println(" " + name + ".setTarget(" + j + ", ih_" + t_pos + ");");
- }
- }
- }
- }
-
- private void updateExceptionHandlers() {
- CodeExceptionGen[] handlers = _mg.getExceptionHandlers();
-
- for (int i = 0; i < handlers.length; i++) {
- CodeExceptionGen h = handlers[i];
- String type = h.getCatchType() == null ? "null" : BCELifier.printType(h.getCatchType());
-
- _out.println(" method.addExceptionHandler(" + "ih_" + h.getStartPC().getPosition() + ", " + "ih_"
- + h.getEndPC().getPosition() + ", " + "ih_" + h.getHandlerPC().getPosition() + ", " + type + ");");
- }
- }
- }
|