1ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski/*
2ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Copyright (C) 2008 The Android Open Source Project
3ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
4ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * you may not use this file except in compliance with the License.
6ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * You may obtain a copy of the License at
7ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
8ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
10ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Unless required by applicable law or agreed to in writing, software
11ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * See the License for the specific language governing permissions and
14ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * limitations under the License.
15ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski */
16ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
17ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskipackage com.android.tools.layoutlib.create;
18ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
19ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.AnnotationVisitor;
20ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.Attribute;
21ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.Label;
22ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.MethodVisitor;
23ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.Opcodes;
24ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport org.objectweb.asm.Type;
25ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
26ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski/**
27ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * This method adapter rewrites a method by discarding the original code and generating
28ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * a stub depending on the return type. Original annotations are passed along unchanged.
29ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski */
30ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiclass StubMethodAdapter extends MethodVisitor {
31ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
32b77a349014d1fade2185a53c2a58edaa4b971dbeDeepanshu Gupta    private static final String CONSTRUCTOR = "<init>";
33b77a349014d1fade2185a53c2a58edaa4b971dbeDeepanshu Gupta    private static final String CLASS_INIT = "<clinit>";
34ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
35ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /** The parent method writer */
36ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private MethodVisitor mParentVisitor;
37ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /** The method return type. Can be null. */
38ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private Type mReturnType;
39ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /** Message to be printed by stub methods. */
40ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private String mInvokeSignature;
41ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /** Flag to output the first line number. */
42ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private boolean mOutputFirstLineNumber = true;
43ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /** Flag that is true when implementing a constructor, to accept all original
44ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *  code calling the original super constructor. */
45ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private boolean mIsInitMethod = false;
46ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
47ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private boolean mMessageGenerated;
48ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final boolean mIsStatic;
49ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final boolean mIsNative;
50ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
51ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public StubMethodAdapter(MethodVisitor mv, String methodName, Type returnType,
52ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            String invokeSignature, boolean isStatic, boolean isNative) {
53528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta        super(Main.ASM_VERSION);
54ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mParentVisitor = mv;
55ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mReturnType = returnType;
56ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mInvokeSignature = invokeSignature;
57ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mIsStatic = isStatic;
58ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mIsNative = isNative;
59ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
60ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (CONSTRUCTOR.equals(methodName) || CLASS_INIT.equals(methodName)) {
61ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mIsInitMethod = true;
62ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
63ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
64ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
65ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private void generateInvoke() {
66ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        /* Generates the code:
67ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         *  OverrideMethod.invoke("signature", mIsNative ? true : false, null or this);
68ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         */
69ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mParentVisitor.visitLdcInsn(mInvokeSignature);
70ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // push true or false
71ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mParentVisitor.visitInsn(mIsNative ? Opcodes.ICONST_1 : Opcodes.ICONST_0);
72ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // push null or this
73ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsStatic) {
74ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitInsn(Opcodes.ACONST_NULL);
75ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } else {
76ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0);
77ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
78ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
79ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int sort = mReturnType != null ? mReturnType.getSort() : Type.VOID;
80ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        switch(sort) {
81ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.VOID:
82ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
83ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "com/android/tools/layoutlib/create/OverrideMethod",
84ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "invokeV",
85528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                    "(Ljava/lang/String;ZLjava/lang/Object;)V",
86528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                    false);
87ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitInsn(Opcodes.RETURN);
88ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            break;
89ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.BOOLEAN:
90ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.CHAR:
91ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.BYTE:
92ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.SHORT:
93ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.INT:
94ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
95ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "com/android/tools/layoutlib/create/OverrideMethod",
96ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "invokeI",
97528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                    "(Ljava/lang/String;ZLjava/lang/Object;)I",
98528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                    false);
99ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            switch(sort) {
100ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            case Type.BOOLEAN:
101ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                Label l1 = new Label();
102ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mParentVisitor.visitJumpInsn(Opcodes.IFEQ, l1);
103ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mParentVisitor.visitInsn(Opcodes.ICONST_1);
104ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mParentVisitor.visitInsn(Opcodes.IRETURN);
105ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mParentVisitor.visitLabel(l1);
106fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta                mParentVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
107ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mParentVisitor.visitInsn(Opcodes.ICONST_0);
108ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                break;
109ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            case Type.CHAR:
110ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mParentVisitor.visitInsn(Opcodes.I2C);
111ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                break;
112ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            case Type.BYTE:
113ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mParentVisitor.visitInsn(Opcodes.I2B);
114ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                break;
115ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            case Type.SHORT:
116ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mParentVisitor.visitInsn(Opcodes.I2S);
117ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                break;
118ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
119ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitInsn(Opcodes.IRETURN);
120ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            break;
121ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.LONG:
122ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
123ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "com/android/tools/layoutlib/create/OverrideMethod",
124ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "invokeL",
125528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                    "(Ljava/lang/String;ZLjava/lang/Object;)J",
126528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                    false);
127ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitInsn(Opcodes.LRETURN);
128ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            break;
129ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.FLOAT:
130ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
131ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "com/android/tools/layoutlib/create/OverrideMethod",
132ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "invokeF",
133528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                    "(Ljava/lang/String;ZLjava/lang/Object;)F",
134528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                    false);
135ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitInsn(Opcodes.FRETURN);
136ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            break;
137ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.DOUBLE:
138ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
139ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "com/android/tools/layoutlib/create/OverrideMethod",
140ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "invokeD",
141528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                    "(Ljava/lang/String;ZLjava/lang/Object;)D",
142528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                    false);
143ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitInsn(Opcodes.DRETURN);
144ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            break;
145ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.ARRAY:
146ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.OBJECT:
147ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
148ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "com/android/tools/layoutlib/create/OverrideMethod",
149ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "invokeA",
150528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                    "(Ljava/lang/String;ZLjava/lang/Object;)Ljava/lang/Object;",
151528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta                    false);
152ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitTypeInsn(Opcodes.CHECKCAST, mReturnType.getInternalName());
153ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitInsn(Opcodes.ARETURN);
154ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            break;
155ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
156ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
157ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
158ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
159ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private void generatePop() {
160ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        /* Pops the stack, depending on the return type.
161ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski         */
162ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        switch(mReturnType != null ? mReturnType.getSort() : Type.VOID) {
163ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.VOID:
164ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            break;
165ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.BOOLEAN:
166ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.CHAR:
167ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.BYTE:
168ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.SHORT:
169ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.INT:
170ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.FLOAT:
171ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.ARRAY:
172ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.OBJECT:
173ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitInsn(Opcodes.POP);
174ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            break;
175ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.LONG:
176ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        case Type.DOUBLE:
177ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitInsn(Opcodes.POP2);
178ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            break;
179ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
180ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
181ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
182ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /* Pass down to visitor writer. In this implementation, either do nothing. */
183ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
184ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitCode() {
185ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mParentVisitor.visitCode();
186ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
187ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
188ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*
189ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * visitMaxs is called just before visitEnd if there was any code to rewrite.
190ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * For non-constructor, generate the messaging code and the return statement
191ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * if it hasn't been done before.
192ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
193ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
194ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitMaxs(int maxStack, int maxLocals) {
195ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (!mIsInitMethod && !mMessageGenerated) {
196ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            generateInvoke();
197ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mMessageGenerated = true;
198ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
199ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mParentVisitor.visitMaxs(maxStack, maxLocals);
200ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
201ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
202ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
203ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * End of visiting.
204ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * For non-constructor, generate the messaging code and the return statement
205ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * if it hasn't been done before.
206ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
207ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
208ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitEnd() {
209ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (!mIsInitMethod && !mMessageGenerated) {
210ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            generateInvoke();
211ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mMessageGenerated = true;
212ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitMaxs(1, 1);
213ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
214ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mParentVisitor.visitEnd();
215ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
216ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
217ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /* Writes all annotation from the original method. */
218ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
219ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
220ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return mParentVisitor.visitAnnotation(desc, visible);
221ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
222ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
223ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /* Writes all annotation default values from the original method. */
224ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
225ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public AnnotationVisitor visitAnnotationDefault() {
226ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return mParentVisitor.visitAnnotationDefault();
227ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
228ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
229ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
230ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
231ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            boolean visible) {
232ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return mParentVisitor.visitParameterAnnotation(parameter, desc, visible);
233ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
234ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
235ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /* Writes all attributes from the original method. */
236ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
237ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitAttribute(Attribute attr) {
238ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mParentVisitor.visitAttribute(attr);
239ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
240ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
241ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*
242ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Only writes the first line number present in the original code so that source
243ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * viewers can direct to the correct method, even if the content doesn't match.
244ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
245ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
246ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitLineNumber(int line, Label start) {
247ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod || mOutputFirstLineNumber) {
248ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitLineNumber(line, start);
249ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mOutputFirstLineNumber = false;
250ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
251ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
252ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
253ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
254ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * For non-constructor, rewrite existing "return" instructions to write the message.
255ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
256ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
257ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitInsn(int opcode) {
258ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
259ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            switch (opcode) {
260ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            case Opcodes.RETURN:
261ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            case Opcodes.ARETURN:
262ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            case Opcodes.DRETURN:
263ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            case Opcodes.FRETURN:
264ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            case Opcodes.IRETURN:
265ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            case Opcodes.LRETURN:
266ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // Pop the last word from the stack since invoke will generate its own return.
267ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                generatePop();
268ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                generateInvoke();
269ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mMessageGenerated = true;
270ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                //$FALL-THROUGH$
271ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            default:
272ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mParentVisitor.visitInsn(opcode);
273ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
274ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
275ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
276ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
277ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
278ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitLabel(Label label) {
279ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
280ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitLabel(label);
281ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
282ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
283ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
284ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
285ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
286ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
287ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitTryCatchBlock(start, end, handler, type);
288ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
289ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
290ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
291ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
292528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
293ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
294528ddbf71ab1cac494e9a1aa50b9c8b76ba29586Deepanshu Gupta            mParentVisitor.visitMethodInsn(opcode, owner, name, desc, itf);
295ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
296ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
297ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
298ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
299ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
300ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
301ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitFieldInsn(opcode, owner, name, desc);
302ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
303ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
304ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
305ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
306ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
307ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
308ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitFrame(type, nLocal, local, nStack, stack);
309ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
310ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
311ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
312ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
313ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitIincInsn(int var, int increment) {
314ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
315ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitIincInsn(var, increment);
316ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
317ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
318ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
319ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
320ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitIntInsn(int opcode, int operand) {
321ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
322ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitIntInsn(opcode, operand);
323ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
324ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
325ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
326ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
327ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitJumpInsn(int opcode, Label label) {
328ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
329ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitJumpInsn(opcode, label);
330ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
331ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
332ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
333ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
334ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitLdcInsn(Object cst) {
335ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
336ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitLdcInsn(cst);
337ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
338ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
339ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
340ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
341ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitLocalVariable(String name, String desc, String signature,
342ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            Label start, Label end, int index) {
343ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
344ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitLocalVariable(name, desc, signature, start, end, index);
345ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
346ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
347ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
348ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
349ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
350ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
351ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitLookupSwitchInsn(dflt, keys, labels);
352ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
353ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
354ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
355ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
356ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitMultiANewArrayInsn(String desc, int dims) {
357ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
358ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitMultiANewArrayInsn(desc, dims);
359ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
360ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
361ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
362ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
363ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
364ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
365ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitTableSwitchInsn(min, max, dflt, labels);
366ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
367ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
368ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
369ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
370ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitTypeInsn(int opcode, String type) {
371ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
372ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitTypeInsn(opcode, type);
373ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
374ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
375ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
376ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
377ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void visitVarInsn(int opcode, int var) {
378ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mIsInitMethod) {
379ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            mParentVisitor.visitVarInsn(opcode, var);
380ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
381ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
382ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
383ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski}
384