1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.  Oracle designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Oracle in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25/*
26 * This file is available under and governed by the GNU General Public
27 * License version 2 only, as published by the Free Software Foundation.
28 * However, the following notice accompanied the original version of this
29 * file:
30 *
31 * ASM: a very small and fast Java bytecode manipulation framework
32 * Copyright (c) 2000-2011 INRIA, France Telecom
33 * All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 *    notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 *    notice, this list of conditions and the following disclaimer in the
42 *    documentation and/or other materials provided with the distribution.
43 * 3. Neither the name of the copyright holders nor the names of its
44 *    contributors may be used to endorse or promote products derived from
45 *    this software without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
57 * THE POSSIBILITY OF SUCH DAMAGE.
58 */
59
60package jdk.internal.org.objectweb.asm.commons;
61
62import jdk.internal.org.objectweb.asm.AnnotationVisitor;
63import jdk.internal.org.objectweb.asm.Handle;
64import jdk.internal.org.objectweb.asm.Label;
65import jdk.internal.org.objectweb.asm.MethodVisitor;
66import jdk.internal.org.objectweb.asm.Opcodes;
67import jdk.internal.org.objectweb.asm.TypePath;
68
69/**
70 * A {@link LocalVariablesSorter} for type mapping.
71 *
72 * @author Eugene Kuleshov
73 */
74public class MethodRemapper extends MethodVisitor {
75
76    protected final Remapper remapper;
77
78    public MethodRemapper(final MethodVisitor mv, final Remapper remapper) {
79        this(Opcodes.ASM5, mv, remapper);
80    }
81
82    protected MethodRemapper(final int api, final MethodVisitor mv,
83            final Remapper remapper) {
84        super(api, mv);
85        this.remapper = remapper;
86    }
87
88    @Override
89    public AnnotationVisitor visitAnnotationDefault() {
90        AnnotationVisitor av = super.visitAnnotationDefault();
91        return av == null ? av : new AnnotationRemapper(av, remapper);
92    }
93
94    @Override
95    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
96        AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
97                visible);
98        return av == null ? av : new AnnotationRemapper(av, remapper);
99    }
100
101    @Override
102    public AnnotationVisitor visitTypeAnnotation(int typeRef,
103            TypePath typePath, String desc, boolean visible) {
104        AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
105                remapper.mapDesc(desc), visible);
106        return av == null ? av : new AnnotationRemapper(av, remapper);
107    }
108
109    @Override
110    public AnnotationVisitor visitParameterAnnotation(int parameter,
111            String desc, boolean visible) {
112        AnnotationVisitor av = super.visitParameterAnnotation(parameter,
113                remapper.mapDesc(desc), visible);
114        return av == null ? av : new AnnotationRemapper(av, remapper);
115    }
116
117    @Override
118    public void visitFrame(int type, int nLocal, Object[] local, int nStack,
119            Object[] stack) {
120        super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack,
121                remapEntries(nStack, stack));
122    }
123
124    private Object[] remapEntries(int n, Object[] entries) {
125        for (int i = 0; i < n; i++) {
126            if (entries[i] instanceof String) {
127                Object[] newEntries = new Object[n];
128                if (i > 0) {
129                    System.arraycopy(entries, 0, newEntries, 0, i);
130                }
131                do {
132                    Object t = entries[i];
133                    newEntries[i++] = t instanceof String ? remapper
134                            .mapType((String) t) : t;
135                } while (i < n);
136                return newEntries;
137            }
138        }
139        return entries;
140    }
141
142    @Override
143    public void visitFieldInsn(int opcode, String owner, String name,
144            String desc) {
145        super.visitFieldInsn(opcode, remapper.mapType(owner),
146                remapper.mapFieldName(owner, name, desc),
147                remapper.mapDesc(desc));
148    }
149
150    @Deprecated
151    @Override
152    public void visitMethodInsn(final int opcode, final String owner,
153            final String name, final String desc) {
154        if (api >= Opcodes.ASM5) {
155            super.visitMethodInsn(opcode, owner, name, desc);
156            return;
157        }
158        doVisitMethodInsn(opcode, owner, name, desc,
159                opcode == Opcodes.INVOKEINTERFACE);
160    }
161
162    @Override
163    public void visitMethodInsn(final int opcode, final String owner,
164            final String name, final String desc, final boolean itf) {
165        if (api < Opcodes.ASM5) {
166            super.visitMethodInsn(opcode, owner, name, desc, itf);
167            return;
168        }
169        doVisitMethodInsn(opcode, owner, name, desc, itf);
170    }
171
172    private void doVisitMethodInsn(int opcode, String owner, String name,
173            String desc, boolean itf) {
174        // Calling super.visitMethodInsn requires to call the correct version
175        // depending on this.api (otherwise infinite loops can occur). To
176        // simplify and to make it easier to automatically remove the backward
177        // compatibility code, we inline the code of the overridden method here.
178        // IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN
179        // LocalVariableSorter.
180        if (mv != null) {
181            mv.visitMethodInsn(opcode, remapper.mapType(owner),
182                    remapper.mapMethodName(owner, name, desc),
183                    remapper.mapMethodDesc(desc), itf);
184        }
185    }
186
187    @Override
188    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
189            Object... bsmArgs) {
190        for (int i = 0; i < bsmArgs.length; i++) {
191            bsmArgs[i] = remapper.mapValue(bsmArgs[i]);
192        }
193        super.visitInvokeDynamicInsn(
194                remapper.mapInvokeDynamicMethodName(name, desc),
195                remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm),
196                bsmArgs);
197    }
198
199    @Override
200    public void visitTypeInsn(int opcode, String type) {
201        super.visitTypeInsn(opcode, remapper.mapType(type));
202    }
203
204    @Override
205    public void visitLdcInsn(Object cst) {
206        super.visitLdcInsn(remapper.mapValue(cst));
207    }
208
209    @Override
210    public void visitMultiANewArrayInsn(String desc, int dims) {
211        super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims);
212    }
213
214    @Override
215    public AnnotationVisitor visitInsnAnnotation(int typeRef,
216            TypePath typePath, String desc, boolean visible) {
217        AnnotationVisitor av = super.visitInsnAnnotation(typeRef, typePath,
218                remapper.mapDesc(desc), visible);
219        return av == null ? av : new AnnotationRemapper(av, remapper);
220    }
221
222    @Override
223    public void visitTryCatchBlock(Label start, Label end, Label handler,
224            String type) {
225        super.visitTryCatchBlock(start, end, handler, type == null ? null
226                : remapper.mapType(type));
227    }
228
229    @Override
230    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
231            TypePath typePath, String desc, boolean visible) {
232        AnnotationVisitor av = super.visitTryCatchAnnotation(typeRef, typePath,
233                remapper.mapDesc(desc), visible);
234        return av == null ? av : new AnnotationRemapper(av, remapper);
235    }
236
237    @Override
238    public void visitLocalVariable(String name, String desc, String signature,
239            Label start, Label end, int index) {
240        super.visitLocalVariable(name, remapper.mapDesc(desc),
241                remapper.mapSignature(signature, true), start, end, index);
242    }
243
244    @Override
245    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
246            TypePath typePath, Label[] start, Label[] end, int[] index,
247            String desc, boolean visible) {
248        AnnotationVisitor av = super.visitLocalVariableAnnotation(typeRef,
249                typePath, start, end, index, remapper.mapDesc(desc), visible);
250        return av == null ? av : new AnnotationRemapper(av, remapper);
251    }
252}
253