169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.expr;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CannotCompileException;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.ClassPool;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtBehavior;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtClass;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtConstructor;
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtPrimitiveType;
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.NotFoundException;
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.AccessFlag;
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.BadBytecode;
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.Bytecode;
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.ClassFile;
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.CodeAttribute;
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.CodeIterator;
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.ConstPool;
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.ExceptionTable;
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.ExceptionsAttribute;
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.MethodInfo;
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.Opcode;
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.compiler.Javac;
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Iterator;
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.LinkedList;
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Expression.
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic abstract class Expr implements Opcode {
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    int currentPos;
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    CodeIterator iterator;
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    CtClass thisClass;
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    MethodInfo thisMethod;
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    boolean edited;
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    int maxLocals, maxStack;
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static final String javaLangObject = "java.lang.Object";
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Undocumented constructor. Do not use; internal-use only.
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected Expr(int pos, CodeIterator i, CtClass declaring, MethodInfo m) {
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        currentPos = pos;
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        iterator = i;
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        thisClass = declaring;
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        thisMethod = m;
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the class that declares the method enclosing
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * this expression.
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.7
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtClass getEnclosingClass() { return thisClass; }
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected final ConstPool getConstPool() {
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return thisMethod.getConstPool();
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected final boolean edited() {
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return edited;
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected final int locals() {
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return maxLocals;
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected final int stack() {
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return maxStack;
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns true if this method is static.
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected final boolean withinStatic() {
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return (thisMethod.getAccessFlags() & AccessFlag.STATIC) != 0;
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the constructor or method containing the expression.
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtBehavior where() {
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        MethodInfo mi = thisMethod;
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtBehavior[] cb = thisClass.getDeclaredBehaviors();
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = cb.length - 1; i >= 0; --i)
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (cb[i].getMethodInfo2() == mi)
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return cb[i];
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtConstructor init = thisClass.getClassInitializer();
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (init != null && init.getMethodInfo2() == mi)
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return init;
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /* getDeclaredBehaviors() returns a list of methods/constructors.
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Although the list is cached in a CtClass object, it might be
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * recreated for some reason.  Thus, the member name and the signature
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * must be also checked.
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = cb.length - 1; i >= 0; --i) {
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (thisMethod.getName().equals(cb[i].getMethodInfo2().getName())
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                && thisMethod.getDescriptor()
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                             .equals(cb[i].getMethodInfo2().getDescriptor())) {
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return cb[i];
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throw new RuntimeException("fatal: not found");
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the list of exceptions that the expression may throw. This list
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * includes both the exceptions that the try-catch statements including the
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * expression can catch and the exceptions that the throws declaration
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * allows the method to throw.
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtClass[] mayThrow() {
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ClassPool pool = thisClass.getClassPool();
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool cp = thisMethod.getConstPool();
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        LinkedList list = new LinkedList();
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CodeAttribute ca = thisMethod.getCodeAttribute();
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ExceptionTable et = ca.getExceptionTable();
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int pos = currentPos;
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int n = et.size();
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; ++i)
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (et.startPc(i) <= pos && pos < et.endPc(i)) {
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    int t = et.catchType(i);
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    if (t > 0)
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        try {
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            addClass(list, pool.get(cp.getClassInfo(t)));
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        }
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        catch (NotFoundException e) {
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        }
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (NullPointerException e) {
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ExceptionsAttribute ea = thisMethod.getExceptionsAttribute();
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (ea != null) {
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String[] exceptions = ea.getExceptions();
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (exceptions != null) {
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int n = exceptions.length;
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                for (int i = 0; i < n; ++i)
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    try {
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        addClass(list, pool.get(exceptions[i]));
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    }
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    catch (NotFoundException e) {
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    }
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return (CtClass[])list.toArray(new CtClass[list.size()]);
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static void addClass(LinkedList list, CtClass c) {
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Iterator it = list.iterator();
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (it.hasNext())
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (it.next() == c)
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return;
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        list.add(c);
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the index of the bytecode corresponding to the expression. It is
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the index into the byte array containing the Java bytecode that
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * implements the method.
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int indexOfBytecode() {
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return currentPos;
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the line number of the source line containing the expression.
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return -1 if this information is not available.
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getLineNumber() {
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return thisMethod.getLineNumber(currentPos);
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the source file containing the expression.
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return null if this information is not available.
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getFileName() {
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ClassFile cf = thisClass.getClassFile2();
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (cf == null)
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return null;
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return cf.getSourceFile();
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static final boolean checkResultValue(CtClass retType, String prog)
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throws CannotCompileException {
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /*
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Is $_ included in the source code?
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0);
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (!hasIt && retType != CtClass.voidType)
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException(
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    "the resulting value is not stored in "
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            + Javac.resultVarName);
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return hasIt;
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /*
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If isStaticCall is true, null is assigned to $0. So $0 must be declared
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * by calling Javac.recordParams().
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * After executing this method, the current stack depth might be less than
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * 0.
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static final void storeStack(CtClass[] params, boolean isStaticCall,
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int regno, Bytecode bytecode) {
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        storeStack0(0, params.length, params, regno + 1, bytecode);
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (isStaticCall)
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.addOpcode(ACONST_NULL);
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        bytecode.addAstore(regno);
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static void storeStack0(int i, int n, CtClass[] params, int regno,
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Bytecode bytecode) {
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (i >= n)
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass c = params[i];
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int size;
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (c instanceof CtPrimitiveType)
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                size = ((CtPrimitiveType)c).getDataSize();
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                size = 1;
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            storeStack0(i + 1, n, params, regno + size, bytecode);
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.addStore(regno, c);
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    // The implementation of replace() should call thisClass.checkModify()
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    // so that isModify() will return true.  Otherwise, thisClass.classfile
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    // might be released during compilation and the compiler might generate
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    // bytecode with a wrong copy of ConstPool.
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Replaces this expression with the bytecode derived from
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the given source text.
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param statement         a Java statement except try-catch.
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public abstract void replace(String statement) throws CannotCompileException;
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Replaces this expression with the bytecode derived from
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the given source text and <code>ExprEditor</code>.
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param statement         a Java statement except try-catch.
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param recursive         if not null, the substituted bytecode
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          is recursively processed by the given
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          <code>ExprEditor</code>.
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.1
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void replace(String statement, ExprEditor recursive)
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        replace(statement);
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (recursive != null)
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            runEditor(recursive, iterator);
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected void replace0(int pos, Bytecode bytecode, int size)
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throws BadBytecode {
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] code = bytecode.get();
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        edited = true;
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int gap = code.length - size;
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < size; ++i)
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            iterator.writeByte(NOP, pos + i);
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (gap > 0)
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            pos = iterator.insertGapAt(pos, gap, false).position;
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        iterator.write(code, pos);
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        iterator.insert(bytecode.getExceptionTable(), pos);
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        maxLocals = bytecode.getMaxLocals();
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        maxStack = bytecode.getMaxStack();
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected void runEditor(ExprEditor ed, CodeIterator oldIterator)
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CannotCompileException
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeAttribute codeAttr = oldIterator.get();
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int orgLocals = codeAttr.getMaxLocals();
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int orgStack = codeAttr.getMaxStack();
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int newLocals = locals();
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        codeAttr.setMaxStack(stack());
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        codeAttr.setMaxLocals(newLocals);
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ExprEditor.LoopContext context
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            = new ExprEditor.LoopContext(newLocals);
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int size = oldIterator.getCodeLength();
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int endPos = oldIterator.lookAhead();
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        oldIterator.move(currentPos);
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (ed.doit(thisClass, thisMethod, context, oldIterator, endPos))
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            edited = true;
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        oldIterator.move(endPos + oldIterator.getCodeLength() - size);
32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        codeAttr.setMaxLocals(orgLocals);
32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        codeAttr.setMaxStack(orgStack);
32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        maxLocals = context.maxLocals;
32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        maxStack += context.maxStack;
32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
330