BytecodeArray.java revision 6b386bfb92ef6efe8f963270fc5a4b756fca225e
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.dx.cf.code;
18
19import com.android.dx.rop.cst.Constant;
20import com.android.dx.rop.cst.ConstantPool;
21import com.android.dx.rop.cst.CstDouble;
22import com.android.dx.rop.cst.CstFloat;
23import com.android.dx.rop.cst.CstInteger;
24import com.android.dx.rop.cst.CstKnownNull;
25import com.android.dx.rop.cst.CstLiteralBits;
26import com.android.dx.rop.cst.CstLong;
27import com.android.dx.rop.cst.CstType;
28import com.android.dx.rop.type.Type;
29import com.android.dx.util.Bits;
30import com.android.dx.util.ByteArray;
31import com.android.dx.util.Hex;
32import java.util.ArrayList;
33
34/**
35 * Bytecode array, which is part of a standard {@code Code} attribute.
36 */
37public final class BytecodeArray {
38    /** convenient no-op implementation of {@link Visitor} */
39    public static final Visitor EMPTY_VISITOR = new BaseVisitor();
40
41    /** {@code non-null;} underlying bytes */
42    private final ByteArray bytes;
43
44    /**
45     * {@code non-null;} constant pool to use when resolving constant
46     * pool indices
47     */
48    private final ConstantPool pool;
49
50    /**
51     * Constructs an instance.
52     *
53     * @param bytes {@code non-null;} underlying bytes
54     * @param pool {@code non-null;} constant pool to use when
55     * resolving constant pool indices
56     */
57    public BytecodeArray(ByteArray bytes, ConstantPool pool) {
58        if (bytes == null) {
59            throw new NullPointerException("bytes == null");
60        }
61
62        if (pool == null) {
63            throw new NullPointerException("pool == null");
64        }
65
66        this.bytes = bytes;
67        this.pool = pool;
68    }
69
70    /**
71     * Gets the underlying byte array.
72     *
73     * @return {@code non-null;} the byte array
74     */
75    public ByteArray getBytes() {
76        return bytes;
77    }
78
79    /**
80     * Gets the size of the bytecode array, per se.
81     *
82     * @return {@code >= 0;} the length of the bytecode array
83     */
84    public int size() {
85        return bytes.size();
86    }
87
88    /**
89     * Gets the total length of this structure in bytes, when included in
90     * a {@code Code} attribute. The returned value includes the
91     * array size plus four bytes for {@code code_length}.
92     *
93     * @return {@code >= 4;} the total length, in bytes
94     */
95    public int byteLength() {
96        return 4 + bytes.size();
97    }
98
99    /**
100     * Parses each instruction in the array, in order.
101     *
102     * @param visitor {@code null-ok;} visitor to call back to for
103     * each instruction
104     */
105    public void forEach(Visitor visitor) {
106        int sz = bytes.size();
107        int at = 0;
108
109        while (at < sz) {
110            /*
111             * Don't record the previous offset here, so that we get to see the
112             * raw code that initializes the array
113             */
114            at += parseInstruction(at, visitor);
115        }
116    }
117
118    /**
119     * Finds the offset to each instruction in the bytecode array. The
120     * result is a bit set with the offset of each opcode-per-se flipped on.
121     *
122     * @see Bits
123     * @return {@code non-null;} appropriately constructed bit set
124     */
125    public int[] getInstructionOffsets() {
126        int sz = bytes.size();
127        int[] result = Bits.makeBitSet(sz);
128        int at = 0;
129
130        while (at < sz) {
131            Bits.set(result, at, true);
132            int length = parseInstruction(at, null);
133            at += length;
134        }
135
136        return result;
137    }
138
139    /**
140     * Processes the given "work set" by repeatedly finding the lowest bit
141     * in the set, clearing it, and parsing and visiting the instruction at
142     * the indicated offset (that is, the bit index), repeating until the
143     * work set is empty. It is expected that the visitor will regularly
144     * set new bits in the work set during the process.
145     *
146     * @param workSet {@code non-null;} the work set to process
147     * @param visitor {@code non-null;} visitor to call back to for
148     * each instruction
149     */
150    public void processWorkSet(int[] workSet, Visitor visitor) {
151        if (visitor == null) {
152            throw new NullPointerException("visitor == null");
153        }
154
155        for (;;) {
156            int offset = Bits.findFirst(workSet, 0);
157            if (offset < 0) {
158                break;
159            }
160            Bits.clear(workSet, offset);
161            parseInstruction(offset, visitor);
162            visitor.setPreviousOffset(offset);
163        }
164    }
165
166    /**
167     * Parses the instruction at the indicated offset. Indicate the
168     * result by calling the visitor if supplied and by returning the
169     * number of bytes consumed by the instruction.
170     *
171     * <p>In order to simplify further processing, the opcodes passed
172     * to the visitor are canonicalized, altering the opcode to a more
173     * universal one and making formerly implicit arguments
174     * explicit. In particular:</p>
175     *
176     * <ul>
177     * <li>The opcodes to push literal constants of primitive types all become
178     *   {@code ldc}.
179     *   E.g., {@code fconst_0}, {@code sipush}, and
180     *   {@code lconst_0} qualify for this treatment.</li>
181     * <li>{@code aconst_null} becomes {@code ldc} of a
182     *   "known null."</li>
183     * <li>Shorthand local variable accessors become the corresponding
184     *   longhand. E.g. {@code aload_2} becomes {@code aload}.</li>
185     * <li>{@code goto_w} and {@code jsr_w} become {@code goto}
186     *   and {@code jsr} (respectively).</li>
187     * <li>{@code ldc_w} becomes {@code ldc}.</li>
188     * <li>{@code tableswitch} becomes {@code lookupswitch}.
189     * <li>Arithmetic, array, and value-returning ops are collapsed
190     *   to the {@code int} variant opcode, with the {@code type}
191     *   argument set to indicate the actual type. E.g.,
192     *   {@code fadd} becomes {@code iadd}, but
193     *   {@code type} is passed as {@code Type.FLOAT} in that
194     *   case. Similarly, {@code areturn} becomes
195     *   {@code ireturn}. (However, {@code return} remains
196     *   unchanged.</li>
197     * <li>Local variable access ops are collapsed to the {@code int}
198     *   variant opcode, with the {@code type} argument set to indicate
199     *   the actual type. E.g., {@code aload} becomes {@code iload},
200     *   but {@code type} is passed as {@code Type.OBJECT} in
201     *   that case.</li>
202     * <li>Numeric conversion ops ({@code i2l}, etc.) are left alone
203     *   to avoid too much confustion, but their {@code type} is
204     *   the pushed type. E.g., {@code i2b} gets type
205     *   {@code Type.INT}, and {@code f2d} gets type
206     *   {@code Type.DOUBLE}. Other unaltered opcodes also get
207     *   their pushed type. E.g., {@code arraylength} gets type
208     *   {@code Type.INT}.</li>
209     * </ul>
210     *
211     * @param offset {@code >= 0, < bytes.size();} offset to the start of the
212     * instruction
213     * @param visitor {@code null-ok;} visitor to call back to
214     * @return the length of the instruction, in bytes
215     */
216    public int parseInstruction(int offset, Visitor visitor) {
217        if (visitor == null) {
218            visitor = EMPTY_VISITOR;
219        }
220
221        try {
222            int opcode = bytes.getUnsignedByte(offset);
223            int info = ByteOps.opInfo(opcode);
224            int fmt = info & ByteOps.FMT_MASK;
225
226            switch (opcode) {
227                case ByteOps.NOP: {
228                    visitor.visitNoArgs(opcode, offset, 1, Type.VOID);
229                    return 1;
230                }
231                case ByteOps.ACONST_NULL: {
232                    visitor.visitConstant(ByteOps.LDC, offset, 1,
233                                          CstKnownNull.THE_ONE, 0);
234                    return 1;
235                }
236                case ByteOps.ICONST_M1: {
237                    visitor.visitConstant(ByteOps.LDC, offset, 1,
238                                          CstInteger.VALUE_M1, -1);
239                    return 1;
240                }
241                case ByteOps.ICONST_0: {
242                    visitor.visitConstant(ByteOps.LDC, offset, 1,
243                                          CstInteger.VALUE_0, 0);
244                    return 1;
245                }
246                case ByteOps.ICONST_1: {
247                    visitor.visitConstant(ByteOps.LDC, offset, 1,
248                                          CstInteger.VALUE_1, 1);
249                    return 1;
250                }
251                case ByteOps.ICONST_2: {
252                    visitor.visitConstant(ByteOps.LDC, offset, 1,
253                                          CstInteger.VALUE_2, 2);
254                    return 1;
255                }
256                case ByteOps.ICONST_3: {
257                    visitor.visitConstant(ByteOps.LDC, offset, 1,
258                                          CstInteger.VALUE_3, 3);
259                    return 1;
260                }
261                case ByteOps.ICONST_4: {
262                    visitor.visitConstant(ByteOps.LDC, offset, 1,
263                                          CstInteger.VALUE_4, 4);
264                    return 1;
265                }
266                case ByteOps.ICONST_5:  {
267                    visitor.visitConstant(ByteOps.LDC, offset, 1,
268                                          CstInteger.VALUE_5, 5);
269                    return 1;
270                }
271                case ByteOps.LCONST_0: {
272                    visitor.visitConstant(ByteOps.LDC, offset, 1,
273                                          CstLong.VALUE_0, 0);
274                    return 1;
275                }
276                case ByteOps.LCONST_1: {
277                    visitor.visitConstant(ByteOps.LDC, offset, 1,
278                                          CstLong.VALUE_1, 0);
279                    return 1;
280                }
281                case ByteOps.FCONST_0: {
282                    visitor.visitConstant(ByteOps.LDC, offset, 1,
283                                          CstFloat.VALUE_0, 0);
284                    return 1;
285                }
286                case ByteOps.FCONST_1: {
287                    visitor.visitConstant(ByteOps.LDC, offset, 1,
288                                          CstFloat.VALUE_1, 0);
289                    return 1;
290                }
291                case ByteOps.FCONST_2:  {
292                    visitor.visitConstant(ByteOps.LDC, offset, 1,
293                                          CstFloat.VALUE_2, 0);
294                    return 1;
295                }
296                case ByteOps.DCONST_0: {
297                    visitor.visitConstant(ByteOps.LDC, offset, 1,
298                                          CstDouble.VALUE_0, 0);
299                    return 1;
300                }
301                case ByteOps.DCONST_1: {
302                    visitor.visitConstant(ByteOps.LDC, offset, 1,
303                                          CstDouble.VALUE_1, 0);
304                    return 1;
305                }
306                case ByteOps.BIPUSH: {
307                    int value = bytes.getByte(offset + 1);
308                    visitor.visitConstant(ByteOps.LDC, offset, 2,
309                                          CstInteger.make(value), value);
310                    return 2;
311                }
312                case ByteOps.SIPUSH: {
313                    int value = bytes.getShort(offset + 1);
314                    visitor.visitConstant(ByteOps.LDC, offset, 3,
315                                          CstInteger.make(value), value);
316                    return 3;
317                }
318                case ByteOps.LDC: {
319                    int idx = bytes.getUnsignedByte(offset + 1);
320                    Constant cst = pool.get(idx);
321                    int value = (cst instanceof CstInteger) ?
322                        ((CstInteger) cst).getValue() : 0;
323                    visitor.visitConstant(ByteOps.LDC, offset, 2, cst, value);
324                    return 2;
325                }
326                case ByteOps.LDC_W: {
327                    int idx = bytes.getUnsignedShort(offset + 1);
328                    Constant cst = pool.get(idx);
329                    int value = (cst instanceof CstInteger) ?
330                        ((CstInteger) cst).getValue() : 0;
331                    visitor.visitConstant(ByteOps.LDC, offset, 3, cst, value);
332                    return 3;
333                }
334                case ByteOps.LDC2_W: {
335                    int idx = bytes.getUnsignedShort(offset + 1);
336                    Constant cst = pool.get(idx);
337                    visitor.visitConstant(ByteOps.LDC2_W, offset, 3, cst, 0);
338                    return 3;
339                }
340                case ByteOps.ILOAD: {
341                    int idx = bytes.getUnsignedByte(offset + 1);
342                    visitor.visitLocal(ByteOps.ILOAD, offset, 2, idx,
343                                       Type.INT, 0);
344                    return 2;
345                }
346                case ByteOps.LLOAD: {
347                    int idx = bytes.getUnsignedByte(offset + 1);
348                    visitor.visitLocal(ByteOps.ILOAD, offset, 2, idx,
349                                       Type.LONG, 0);
350                    return 2;
351                }
352                case ByteOps.FLOAD: {
353                    int idx = bytes.getUnsignedByte(offset + 1);
354                    visitor.visitLocal(ByteOps.ILOAD, offset, 2, idx,
355                                       Type.FLOAT, 0);
356                    return 2;
357                }
358                case ByteOps.DLOAD: {
359                    int idx = bytes.getUnsignedByte(offset + 1);
360                    visitor.visitLocal(ByteOps.ILOAD, offset, 2, idx,
361                                       Type.DOUBLE, 0);
362                    return 2;
363                }
364                case ByteOps.ALOAD: {
365                    int idx = bytes.getUnsignedByte(offset + 1);
366                    visitor.visitLocal(ByteOps.ILOAD, offset, 2, idx,
367                                       Type.OBJECT, 0);
368                    return 2;
369                }
370                case ByteOps.ILOAD_0:
371                case ByteOps.ILOAD_1:
372                case ByteOps.ILOAD_2:
373                case ByteOps.ILOAD_3: {
374                    int idx = opcode - ByteOps.ILOAD_0;
375                    visitor.visitLocal(ByteOps.ILOAD, offset, 1, idx,
376                                       Type.INT, 0);
377                    return 1;
378                }
379                case ByteOps.LLOAD_0:
380                case ByteOps.LLOAD_1:
381                case ByteOps.LLOAD_2:
382                case ByteOps.LLOAD_3: {
383                    int idx = opcode - ByteOps.LLOAD_0;
384                    visitor.visitLocal(ByteOps.ILOAD, offset, 1, idx,
385                                       Type.LONG, 0);
386                    return 1;
387                }
388                case ByteOps.FLOAD_0:
389                case ByteOps.FLOAD_1:
390                case ByteOps.FLOAD_2:
391                case ByteOps.FLOAD_3: {
392                    int idx = opcode - ByteOps.FLOAD_0;
393                    visitor.visitLocal(ByteOps.ILOAD, offset, 1, idx,
394                                       Type.FLOAT, 0);
395                    return 1;
396                }
397                case ByteOps.DLOAD_0:
398                case ByteOps.DLOAD_1:
399                case ByteOps.DLOAD_2:
400                case ByteOps.DLOAD_3: {
401                    int idx = opcode - ByteOps.DLOAD_0;
402                    visitor.visitLocal(ByteOps.ILOAD, offset, 1, idx,
403                                       Type.DOUBLE, 0);
404                    return 1;
405                }
406                case ByteOps.ALOAD_0:
407                case ByteOps.ALOAD_1:
408                case ByteOps.ALOAD_2:
409                case ByteOps.ALOAD_3: {
410                    int idx = opcode - ByteOps.ALOAD_0;
411                    visitor.visitLocal(ByteOps.ILOAD, offset, 1, idx,
412                                       Type.OBJECT, 0);
413                    return 1;
414                }
415                case ByteOps.IALOAD: {
416                    visitor.visitNoArgs(ByteOps.IALOAD, offset, 1, Type.INT);
417                    return 1;
418                }
419                case ByteOps.LALOAD: {
420                    visitor.visitNoArgs(ByteOps.IALOAD, offset, 1, Type.LONG);
421                    return 1;
422                }
423                case ByteOps.FALOAD: {
424                    visitor.visitNoArgs(ByteOps.IALOAD, offset, 1,
425                                        Type.FLOAT);
426                    return 1;
427                }
428                case ByteOps.DALOAD: {
429                    visitor.visitNoArgs(ByteOps.IALOAD, offset, 1,
430                                        Type.DOUBLE);
431                    return 1;
432                }
433                case ByteOps.AALOAD: {
434                    visitor.visitNoArgs(ByteOps.IALOAD, offset, 1,
435                                        Type.OBJECT);
436                    return 1;
437                }
438                case ByteOps.BALOAD: {
439                    /*
440                     * Note: This is a load from either a byte[] or a
441                     * boolean[].
442                     */
443                    visitor.visitNoArgs(ByteOps.IALOAD, offset, 1, Type.BYTE);
444                    return 1;
445                }
446                case ByteOps.CALOAD: {
447                    visitor.visitNoArgs(ByteOps.IALOAD, offset, 1, Type.CHAR);
448                    return 1;
449                }
450                case ByteOps.SALOAD: {
451                    visitor.visitNoArgs(ByteOps.IALOAD, offset, 1,
452                                        Type.SHORT);
453                    return 1;
454                }
455                case ByteOps.ISTORE: {
456                    int idx = bytes.getUnsignedByte(offset + 1);
457                    visitor.visitLocal(ByteOps.ISTORE, offset, 2, idx,
458                                       Type.INT, 0);
459                    return 2;
460                }
461                case ByteOps.LSTORE: {
462                    int idx = bytes.getUnsignedByte(offset + 1);
463                    visitor.visitLocal(ByteOps.ISTORE, offset, 2, idx,
464                                       Type.LONG, 0);
465                    return 2;
466                }
467                case ByteOps.FSTORE: {
468                    int idx = bytes.getUnsignedByte(offset + 1);
469                    visitor.visitLocal(ByteOps.ISTORE, offset, 2, idx,
470                                       Type.FLOAT, 0);
471                    return 2;
472                }
473                case ByteOps.DSTORE: {
474                    int idx = bytes.getUnsignedByte(offset + 1);
475                    visitor.visitLocal(ByteOps.ISTORE, offset, 2, idx,
476                                       Type.DOUBLE, 0);
477                    return 2;
478                }
479                case ByteOps.ASTORE: {
480                    int idx = bytes.getUnsignedByte(offset + 1);
481                    visitor.visitLocal(ByteOps.ISTORE, offset, 2, idx,
482                                       Type.OBJECT, 0);
483                    return 2;
484                }
485                case ByteOps.ISTORE_0:
486                case ByteOps.ISTORE_1:
487                case ByteOps.ISTORE_2:
488                case ByteOps.ISTORE_3: {
489                    int idx = opcode - ByteOps.ISTORE_0;
490                    visitor.visitLocal(ByteOps.ISTORE, offset, 1, idx,
491                                       Type.INT, 0);
492                    return 1;
493                }
494                case ByteOps.LSTORE_0:
495                case ByteOps.LSTORE_1:
496                case ByteOps.LSTORE_2:
497                case ByteOps.LSTORE_3: {
498                    int idx = opcode - ByteOps.LSTORE_0;
499                    visitor.visitLocal(ByteOps.ISTORE, offset, 1, idx,
500                                       Type.LONG, 0);
501                    return 1;
502                }
503                case ByteOps.FSTORE_0:
504                case ByteOps.FSTORE_1:
505                case ByteOps.FSTORE_2:
506                case ByteOps.FSTORE_3: {
507                    int idx = opcode - ByteOps.FSTORE_0;
508                    visitor.visitLocal(ByteOps.ISTORE, offset, 1, idx,
509                                       Type.FLOAT, 0);
510                    return 1;
511                }
512                case ByteOps.DSTORE_0:
513                case ByteOps.DSTORE_1:
514                case ByteOps.DSTORE_2:
515                case ByteOps.DSTORE_3: {
516                    int idx = opcode - ByteOps.DSTORE_0;
517                    visitor.visitLocal(ByteOps.ISTORE, offset, 1, idx,
518                                       Type.DOUBLE, 0);
519                    return 1;
520                }
521                case ByteOps.ASTORE_0:
522                case ByteOps.ASTORE_1:
523                case ByteOps.ASTORE_2:
524                case ByteOps.ASTORE_3: {
525                    int idx = opcode - ByteOps.ASTORE_0;
526                    visitor.visitLocal(ByteOps.ISTORE, offset, 1, idx,
527                                       Type.OBJECT, 0);
528                    return 1;
529                }
530                case ByteOps.IASTORE: {
531                    visitor.visitNoArgs(ByteOps.IASTORE, offset, 1, Type.INT);
532                    return 1;
533                }
534                case ByteOps.LASTORE: {
535                    visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
536                                        Type.LONG);
537                    return 1;
538                }
539                case ByteOps.FASTORE: {
540                    visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
541                                        Type.FLOAT);
542                    return 1;
543                }
544                case ByteOps.DASTORE: {
545                    visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
546                                        Type.DOUBLE);
547                    return 1;
548                }
549                case ByteOps.AASTORE: {
550                    visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
551                                        Type.OBJECT);
552                    return 1;
553                }
554                case ByteOps.BASTORE: {
555                    /*
556                     * Note: This is a load from either a byte[] or a
557                     * boolean[].
558                     */
559                    visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
560                                        Type.BYTE);
561                    return 1;
562                }
563                case ByteOps.CASTORE: {
564                    visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
565                                        Type.CHAR);
566                    return 1;
567                }
568                case ByteOps.SASTORE: {
569                    visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
570                                        Type.SHORT);
571                    return 1;
572                }
573                case ByteOps.POP:
574                case ByteOps.POP2:
575                case ByteOps.DUP:
576                case ByteOps.DUP_X1:
577                case ByteOps.DUP_X2:
578                case ByteOps.DUP2:
579                case ByteOps.DUP2_X1:
580                case ByteOps.DUP2_X2:
581                case ByteOps.SWAP: {
582                    visitor.visitNoArgs(opcode, offset, 1, Type.VOID);
583                    return 1;
584                }
585                case ByteOps.IADD:
586                case ByteOps.ISUB:
587                case ByteOps.IMUL:
588                case ByteOps.IDIV:
589                case ByteOps.IREM:
590                case ByteOps.INEG:
591                case ByteOps.ISHL:
592                case ByteOps.ISHR:
593                case ByteOps.IUSHR:
594                case ByteOps.IAND:
595                case ByteOps.IOR:
596                case ByteOps.IXOR: {
597                    visitor.visitNoArgs(opcode, offset, 1, Type.INT);
598                    return 1;
599                }
600                case ByteOps.LADD:
601                case ByteOps.LSUB:
602                case ByteOps.LMUL:
603                case ByteOps.LDIV:
604                case ByteOps.LREM:
605                case ByteOps.LNEG:
606                case ByteOps.LSHL:
607                case ByteOps.LSHR:
608                case ByteOps.LUSHR:
609                case ByteOps.LAND:
610                case ByteOps.LOR:
611                case ByteOps.LXOR: {
612                    /*
613                     * It's "opcode - 1" because, conveniently enough, all
614                     * these long ops are one past the int variants.
615                     */
616                    visitor.visitNoArgs(opcode - 1, offset, 1, Type.LONG);
617                    return 1;
618                }
619                case ByteOps.FADD:
620                case ByteOps.FSUB:
621                case ByteOps.FMUL:
622                case ByteOps.FDIV:
623                case ByteOps.FREM:
624                case ByteOps.FNEG: {
625                    /*
626                     * It's "opcode - 2" because, conveniently enough, all
627                     * these float ops are two past the int variants.
628                     */
629                    visitor.visitNoArgs(opcode - 2, offset, 1, Type.FLOAT);
630                    return 1;
631                }
632                case ByteOps.DADD:
633                case ByteOps.DSUB:
634                case ByteOps.DMUL:
635                case ByteOps.DDIV:
636                case ByteOps.DREM:
637                case ByteOps.DNEG: {
638                    /*
639                     * It's "opcode - 3" because, conveniently enough, all
640                     * these double ops are three past the int variants.
641                     */
642                    visitor.visitNoArgs(opcode - 3, offset, 1, Type.DOUBLE);
643                    return 1;
644                }
645                case ByteOps.IINC: {
646                    int idx = bytes.getUnsignedByte(offset + 1);
647                    int value = bytes.getByte(offset + 2);
648                    visitor.visitLocal(opcode, offset, 3, idx,
649                                       Type.INT, value);
650                    return 3;
651                }
652                case ByteOps.I2L:
653                case ByteOps.F2L:
654                case ByteOps.D2L: {
655                    visitor.visitNoArgs(opcode, offset, 1, Type.LONG);
656                    return 1;
657                }
658                case ByteOps.I2F:
659                case ByteOps.L2F:
660                case ByteOps.D2F: {
661                    visitor.visitNoArgs(opcode, offset, 1, Type.FLOAT);
662                    return 1;
663                }
664                case ByteOps.I2D:
665                case ByteOps.L2D:
666                case ByteOps.F2D: {
667                    visitor.visitNoArgs(opcode, offset, 1, Type.DOUBLE);
668                    return 1;
669                }
670                case ByteOps.L2I:
671                case ByteOps.F2I:
672                case ByteOps.D2I:
673                case ByteOps.I2B:
674                case ByteOps.I2C:
675                case ByteOps.I2S:
676                case ByteOps.LCMP:
677                case ByteOps.FCMPL:
678                case ByteOps.FCMPG:
679                case ByteOps.DCMPL:
680                case ByteOps.DCMPG:
681                case ByteOps.ARRAYLENGTH: {
682                    visitor.visitNoArgs(opcode, offset, 1, Type.INT);
683                    return 1;
684                }
685                case ByteOps.IFEQ:
686                case ByteOps.IFNE:
687                case ByteOps.IFLT:
688                case ByteOps.IFGE:
689                case ByteOps.IFGT:
690                case ByteOps.IFLE:
691                case ByteOps.IF_ICMPEQ:
692                case ByteOps.IF_ICMPNE:
693                case ByteOps.IF_ICMPLT:
694                case ByteOps.IF_ICMPGE:
695                case ByteOps.IF_ICMPGT:
696                case ByteOps.IF_ICMPLE:
697                case ByteOps.IF_ACMPEQ:
698                case ByteOps.IF_ACMPNE:
699                case ByteOps.GOTO:
700                case ByteOps.JSR:
701                case ByteOps.IFNULL:
702                case ByteOps.IFNONNULL: {
703                    int target = offset + bytes.getShort(offset + 1);
704                    visitor.visitBranch(opcode, offset, 3, target);
705                    return 3;
706                }
707                case ByteOps.RET: {
708                    int idx = bytes.getUnsignedByte(offset + 1);
709                    visitor.visitLocal(opcode, offset, 2, idx,
710                                       Type.RETURN_ADDRESS, 0);
711                    return 2;
712                }
713                case ByteOps.TABLESWITCH: {
714                    return parseTableswitch(offset, visitor);
715                }
716                case ByteOps.LOOKUPSWITCH: {
717                    return parseLookupswitch(offset, visitor);
718                }
719                case ByteOps.IRETURN: {
720                    visitor.visitNoArgs(ByteOps.IRETURN, offset, 1, Type.INT);
721                    return 1;
722                }
723                case ByteOps.LRETURN: {
724                    visitor.visitNoArgs(ByteOps.IRETURN, offset, 1,
725                                        Type.LONG);
726                    return 1;
727                }
728                case ByteOps.FRETURN: {
729                    visitor.visitNoArgs(ByteOps.IRETURN, offset, 1,
730                                        Type.FLOAT);
731                    return 1;
732                }
733                case ByteOps.DRETURN: {
734                    visitor.visitNoArgs(ByteOps.IRETURN, offset, 1,
735                                        Type.DOUBLE);
736                    return 1;
737                }
738                case ByteOps.ARETURN: {
739                    visitor.visitNoArgs(ByteOps.IRETURN, offset, 1,
740                                        Type.OBJECT);
741                    return 1;
742                }
743                case ByteOps.RETURN:
744                case ByteOps.ATHROW:
745                case ByteOps.MONITORENTER:
746                case ByteOps.MONITOREXIT: {
747                    visitor.visitNoArgs(opcode, offset, 1, Type.VOID);
748                    return 1;
749                }
750                case ByteOps.GETSTATIC:
751                case ByteOps.PUTSTATIC:
752                case ByteOps.GETFIELD:
753                case ByteOps.PUTFIELD:
754                case ByteOps.INVOKEVIRTUAL:
755                case ByteOps.INVOKESPECIAL:
756                case ByteOps.INVOKESTATIC:
757                case ByteOps.NEW:
758                case ByteOps.ANEWARRAY:
759                case ByteOps.CHECKCAST:
760                case ByteOps.INSTANCEOF: {
761                    int idx = bytes.getUnsignedShort(offset + 1);
762                    Constant cst = pool.get(idx);
763                    visitor.visitConstant(opcode, offset, 3, cst, 0);
764                    return 3;
765                }
766                case ByteOps.INVOKEINTERFACE: {
767                    int idx = bytes.getUnsignedShort(offset + 1);
768                    int count = bytes.getUnsignedByte(offset + 3);
769                    int expectZero = bytes.getUnsignedByte(offset + 4);
770                    Constant cst = pool.get(idx);
771                    visitor.visitConstant(opcode, offset, 5, cst,
772                                          count | (expectZero << 8));
773                    return 5;
774                }
775                case ByteOps.NEWARRAY: {
776                    return parseNewarray(offset, visitor);
777                }
778                case ByteOps.WIDE: {
779                    return parseWide(offset, visitor);
780                }
781                case ByteOps.MULTIANEWARRAY: {
782                    int idx = bytes.getUnsignedShort(offset + 1);
783                    int dimensions = bytes.getUnsignedByte(offset + 3);
784                    Constant cst = pool.get(idx);
785                    visitor.visitConstant(opcode, offset, 4, cst, dimensions);
786                    return 4;
787                }
788                case ByteOps.GOTO_W:
789                case ByteOps.JSR_W: {
790                    int target = offset + bytes.getInt(offset + 1);
791                    int newop =
792                        (opcode == ByteOps.GOTO_W) ? ByteOps.GOTO :
793                        ByteOps.JSR;
794                    visitor.visitBranch(newop, offset, 5, target);
795                    return 5;
796                }
797                default: {
798                    visitor.visitInvalid(opcode, offset, 1);
799                    return 1;
800                }
801            }
802        } catch (SimException ex) {
803            ex.addContext("...at bytecode offset " + Hex.u4(offset));
804            throw ex;
805        } catch (RuntimeException ex) {
806            SimException se = new SimException(ex);
807            se.addContext("...at bytecode offset " + Hex.u4(offset));
808            throw se;
809        }
810    }
811
812    /**
813     * Helper to deal with {@code tableswitch}.
814     *
815     * @param offset the offset to the {@code tableswitch} opcode itself
816     * @param visitor {@code non-null;} visitor to use
817     * @return instruction length, in bytes
818     */
819    private int parseTableswitch(int offset, Visitor visitor) {
820        int at = (offset + 4) & ~3; // "at" skips the padding.
821
822        // Collect the padding.
823        int padding = 0;
824        for (int i = offset + 1; i < at; i++) {
825            padding = (padding << 8) | bytes.getUnsignedByte(i);
826        }
827
828        int defaultTarget = offset + bytes.getInt(at);
829        int low = bytes.getInt(at + 4);
830        int high = bytes.getInt(at + 8);
831        int count = high - low + 1;
832        at += 12;
833
834        if (low > high) {
835            throw new SimException("low / high inversion");
836        }
837
838        SwitchList cases = new SwitchList(count);
839        for (int i = 0; i < count; i++) {
840            int target = offset + bytes.getInt(at);
841            at += 4;
842            cases.add(low + i, target);
843        }
844        cases.setDefaultTarget(defaultTarget);
845        cases.removeSuperfluousDefaults();
846        cases.setImmutable();
847
848        int length = at - offset;
849        visitor.visitSwitch(ByteOps.LOOKUPSWITCH, offset, length, cases,
850                            padding);
851
852        return length;
853    }
854
855    /**
856     * Helper to deal with {@code lookupswitch}.
857     *
858     * @param offset the offset to the {@code lookupswitch} opcode itself
859     * @param visitor {@code non-null;} visitor to use
860     * @return instruction length, in bytes
861     */
862    private int parseLookupswitch(int offset, Visitor visitor) {
863        int at = (offset + 4) & ~3; // "at" skips the padding.
864
865        // Collect the padding.
866        int padding = 0;
867        for (int i = offset + 1; i < at; i++) {
868            padding = (padding << 8) | bytes.getUnsignedByte(i);
869        }
870
871        int defaultTarget = offset + bytes.getInt(at);
872        int npairs = bytes.getInt(at + 4);
873        at += 8;
874
875        SwitchList cases = new SwitchList(npairs);
876        for (int i = 0; i < npairs; i++) {
877            int match = bytes.getInt(at);
878            int target = offset + bytes.getInt(at + 4);
879            at += 8;
880            cases.add(match, target);
881        }
882        cases.setDefaultTarget(defaultTarget);
883        cases.removeSuperfluousDefaults();
884        cases.setImmutable();
885
886        int length = at - offset;
887        visitor.visitSwitch(ByteOps.LOOKUPSWITCH, offset, length, cases,
888                            padding);
889
890        return length;
891    }
892
893    /**
894     * Helper to deal with {@code newarray}.
895     *
896     * @param offset the offset to the {@code newarray} opcode itself
897     * @param visitor {@code non-null;} visitor to use
898     * @return instruction length, in bytes
899     */
900    private int parseNewarray(int offset, Visitor visitor) {
901        int value = bytes.getUnsignedByte(offset + 1);
902        CstType type;
903        switch (value) {
904            case ByteOps.NEWARRAY_BOOLEAN: {
905                type = CstType.BOOLEAN_ARRAY;
906                break;
907            }
908            case ByteOps.NEWARRAY_CHAR: {
909                type = CstType.CHAR_ARRAY;
910                break;
911            }
912            case ByteOps.NEWARRAY_DOUBLE: {
913                type = CstType.DOUBLE_ARRAY;
914                break;
915            }
916            case ByteOps.NEWARRAY_FLOAT: {
917                type = CstType.FLOAT_ARRAY;
918                break;
919            }
920            case ByteOps.NEWARRAY_BYTE: {
921                type = CstType.BYTE_ARRAY;
922                break;
923            }
924            case ByteOps.NEWARRAY_SHORT: {
925                type = CstType.SHORT_ARRAY;
926                break;
927            }
928            case ByteOps.NEWARRAY_INT: {
929                type = CstType.INT_ARRAY;
930                break;
931            }
932            case ByteOps.NEWARRAY_LONG: {
933                type = CstType.LONG_ARRAY;
934                break;
935            }
936            default: {
937                throw new SimException("bad newarray code " +
938                        Hex.u1(value));
939            }
940        }
941
942        // Revisit the previous bytecode to find out the length of the array
943        int previousOffset = visitor.getPreviousOffset();
944        ConstantParserVisitor constantVisitor = new ConstantParserVisitor();
945        int arrayLength = 0;
946
947        /*
948         * For visitors that don't record the previous offset, -1 will be
949         * seen here
950         */
951        if (previousOffset >= 0) {
952            parseInstruction(previousOffset, constantVisitor);
953            if (constantVisitor.cst instanceof CstInteger &&
954                    constantVisitor.length + previousOffset == offset) {
955                arrayLength = constantVisitor.value;
956
957            }
958        }
959
960        /*
961         * Try to match the array initialization idiom. For example, if the
962         * subsequent code is initializing an int array, we are expecting the
963         * following pattern repeatedly:
964         *  dup
965         *  push index
966         *  push value
967         *  *astore
968         *
969         * where the index value will be incrimented sequentially from 0 up.
970         */
971        int nInit = 0;
972        int curOffset = offset+2;
973        int lastOffset = curOffset;
974        ArrayList<Constant> initVals = new ArrayList<Constant>();
975
976        if (arrayLength != 0) {
977            while (true) {
978                boolean punt = false;
979
980                // First, check if the next bytecode is dup.
981                int nextByte = bytes.getUnsignedByte(curOffset++);
982                if (nextByte != ByteOps.DUP)
983                    break;
984
985                /*
986                 * Next, check if the expected array index is pushed to
987                 * the stack.
988                 */
989                parseInstruction(curOffset, constantVisitor);
990                if (constantVisitor.length == 0 ||
991                        !(constantVisitor.cst instanceof CstInteger) ||
992                        constantVisitor.value != nInit)
993                    break;
994
995                // Next, fetch the init value and record it.
996                curOffset += constantVisitor.length;
997
998                /*
999                 * Next, find out what kind of constant is pushed onto
1000                 * the stack.
1001                 */
1002                parseInstruction(curOffset, constantVisitor);
1003                if (constantVisitor.length == 0 ||
1004                        !(constantVisitor.cst instanceof CstLiteralBits))
1005                    break;
1006
1007                curOffset += constantVisitor.length;
1008                initVals.add(constantVisitor.cst);
1009
1010                nextByte = bytes.getUnsignedByte(curOffset++);
1011                // Now, check if the value is stored to the array properly.
1012                switch (value) {
1013                    case ByteOps.NEWARRAY_BYTE:
1014                    case ByteOps.NEWARRAY_BOOLEAN: {
1015                        if (nextByte != ByteOps.BASTORE) {
1016                            punt = true;
1017                        }
1018                        break;
1019                    }
1020                    case ByteOps.NEWARRAY_CHAR: {
1021                        if (nextByte != ByteOps.CASTORE) {
1022                            punt = true;
1023                        }
1024                        break;
1025                    }
1026                    case ByteOps.NEWARRAY_DOUBLE: {
1027                        if (nextByte != ByteOps.DASTORE) {
1028                            punt = true;
1029                        }
1030                        break;
1031                    }
1032                    case ByteOps.NEWARRAY_FLOAT: {
1033                        if (nextByte != ByteOps.FASTORE) {
1034                            punt = true;
1035                        }
1036                        break;
1037                    }
1038                    case ByteOps.NEWARRAY_SHORT: {
1039                        if (nextByte != ByteOps.SASTORE) {
1040                            punt = true;
1041                        }
1042                        break;
1043                    }
1044                    case ByteOps.NEWARRAY_INT: {
1045                        if (nextByte != ByteOps.IASTORE) {
1046                            punt = true;
1047                        }
1048                        break;
1049                    }
1050                    case ByteOps.NEWARRAY_LONG: {
1051                        if (nextByte != ByteOps.LASTORE) {
1052                            punt = true;
1053                        }
1054                        break;
1055                    }
1056                    default:
1057                        punt = true;
1058                        break;
1059                }
1060                if (punt) {
1061                    break;
1062                }
1063                lastOffset = curOffset;
1064                nInit++;
1065            }
1066        }
1067
1068        /*
1069         * For singleton arrays it is still more economical to
1070         * generate the aput.
1071         */
1072        if (nInit < 2 || nInit != arrayLength) {
1073            visitor.visitNewarray(offset, 2, type, null);
1074            return 2;
1075        } else {
1076            visitor.visitNewarray(offset, lastOffset - offset, type, initVals);
1077            return lastOffset - offset;
1078        }
1079     }
1080
1081
1082    /**
1083     * Helper to deal with {@code wide}.
1084     *
1085     * @param offset the offset to the {@code wide} opcode itself
1086     * @param visitor {@code non-null;} visitor to use
1087     * @return instruction length, in bytes
1088     */
1089    private int parseWide(int offset, Visitor visitor) {
1090        int opcode = bytes.getUnsignedByte(offset + 1);
1091        int idx = bytes.getUnsignedShort(offset + 2);
1092        switch (opcode) {
1093            case ByteOps.ILOAD: {
1094                visitor.visitLocal(ByteOps.ILOAD, offset, 4, idx,
1095                                   Type.INT, 0);
1096                return 4;
1097            }
1098            case ByteOps.LLOAD: {
1099                visitor.visitLocal(ByteOps.ILOAD, offset, 4, idx,
1100                                   Type.LONG, 0);
1101                return 4;
1102            }
1103            case ByteOps.FLOAD: {
1104                visitor.visitLocal(ByteOps.ILOAD, offset, 4, idx,
1105                                   Type.FLOAT, 0);
1106                return 4;
1107            }
1108            case ByteOps.DLOAD: {
1109                visitor.visitLocal(ByteOps.ILOAD, offset, 4, idx,
1110                                   Type.DOUBLE, 0);
1111                return 4;
1112            }
1113            case ByteOps.ALOAD: {
1114                visitor.visitLocal(ByteOps.ILOAD, offset, 4, idx,
1115                                   Type.OBJECT, 0);
1116                return 4;
1117            }
1118            case ByteOps.ISTORE: {
1119                visitor.visitLocal(ByteOps.ISTORE, offset, 4, idx,
1120                                   Type.INT, 0);
1121                return 4;
1122            }
1123            case ByteOps.LSTORE: {
1124                visitor.visitLocal(ByteOps.ISTORE, offset, 4, idx,
1125                                   Type.LONG, 0);
1126                return 4;
1127            }
1128            case ByteOps.FSTORE: {
1129                visitor.visitLocal(ByteOps.ISTORE, offset, 4, idx,
1130                                   Type.FLOAT, 0);
1131                return 4;
1132            }
1133            case ByteOps.DSTORE: {
1134                visitor.visitLocal(ByteOps.ISTORE, offset, 4, idx,
1135                                   Type.DOUBLE, 0);
1136                return 4;
1137            }
1138            case ByteOps.ASTORE: {
1139                visitor.visitLocal(ByteOps.ISTORE, offset, 4, idx,
1140                                   Type.OBJECT, 0);
1141                return 4;
1142            }
1143            case ByteOps.RET: {
1144                visitor.visitLocal(opcode, offset, 4, idx,
1145                                   Type.RETURN_ADDRESS, 0);
1146                return 4;
1147            }
1148            case ByteOps.IINC: {
1149                int value = bytes.getShort(offset + 4);
1150                visitor.visitLocal(opcode, offset, 6, idx,
1151                                   Type.INT, value);
1152                return 6;
1153            }
1154            default: {
1155                visitor.visitInvalid(ByteOps.WIDE, offset, 1);
1156                return 1;
1157            }
1158        }
1159    }
1160
1161    /**
1162     * Instruction visitor interface.
1163     */
1164    public interface Visitor {
1165        /**
1166         * Visits an invalid instruction.
1167         *
1168         * @param opcode the opcode
1169         * @param offset offset to the instruction
1170         * @param length length of the instruction, in bytes
1171         */
1172        public void visitInvalid(int opcode, int offset, int length);
1173
1174        /**
1175         * Visits an instruction which has no inline arguments
1176         * (implicit or explicit).
1177         *
1178         * @param opcode the opcode
1179         * @param offset offset to the instruction
1180         * @param length length of the instruction, in bytes
1181         * @param type {@code non-null;} type the instruction operates on
1182         */
1183        public void visitNoArgs(int opcode, int offset, int length,
1184                Type type);
1185
1186        /**
1187         * Visits an instruction which has a local variable index argument.
1188         *
1189         * @param opcode the opcode
1190         * @param offset offset to the instruction
1191         * @param length length of the instruction, in bytes
1192         * @param idx the local variable index
1193         * @param type {@code non-null;} the type of the accessed value
1194         * @param value additional literal integer argument, if salient (i.e.,
1195         * for {@code iinc})
1196         */
1197        public void visitLocal(int opcode, int offset, int length,
1198                int idx, Type type, int value);
1199
1200        /**
1201         * Visits an instruction which has a (possibly synthetic)
1202         * constant argument, and possibly also an
1203         * additional literal integer argument. In the case of
1204         * {@code multianewarray}, the argument is the count of
1205         * dimensions. In the case of {@code invokeinterface},
1206         * the argument is the parameter count or'ed with the
1207         * should-be-zero value left-shifted by 8. In the case of entries
1208         * of type {@code int}, the {@code value} field always
1209         * holds the raw value (for convenience of clients).
1210         *
1211         * <p><b>Note:</b> In order to avoid giving it a barely-useful
1212         * visitor all its own, {@code newarray} also uses this
1213         * form, passing {@code value} as the array type code and
1214         * {@code cst} as a {@link CstType} instance
1215         * corresponding to the array type.</p>
1216         *
1217         * @param opcode the opcode
1218         * @param offset offset to the instruction
1219         * @param length length of the instruction, in bytes
1220         * @param cst {@code non-null;} the constant
1221         * @param value additional literal integer argument, if salient
1222         * (ignore if not)
1223         */
1224        public void visitConstant(int opcode, int offset, int length,
1225                Constant cst, int value);
1226
1227        /**
1228         * Visits an instruction which has a branch target argument.
1229         *
1230         * @param opcode the opcode
1231         * @param offset offset to the instruction
1232         * @param length length of the instruction, in bytes
1233         * @param target the absolute (not relative) branch target
1234         */
1235        public void visitBranch(int opcode, int offset, int length,
1236                int target);
1237
1238        /**
1239         * Visits a switch instruction.
1240         *
1241         * @param opcode the opcode
1242         * @param offset offset to the instruction
1243         * @param length length of the instruction, in bytes
1244         * @param cases {@code non-null;} list of (value, target)
1245         * pairs, plus the default target
1246         * @param padding the bytes found in the padding area (if any),
1247         * packed
1248         */
1249        public void visitSwitch(int opcode, int offset, int length,
1250                SwitchList cases, int padding);
1251
1252        /**
1253         * Visits a newarray instruction.
1254         *
1255         * @param offset   offset to the instruction
1256         * @param length   length of the instruction, in bytes
1257         * @param type {@code non-null;} the type of the array
1258         * @param initVals {@code non-null;} list of bytecode offsets
1259         * for init values
1260         */
1261        public void visitNewarray(int offset, int length, CstType type,
1262                ArrayList<Constant> initVals);
1263
1264        /**
1265         * Set previous bytecode offset
1266         * @param offset    offset of the previous fully parsed bytecode
1267         */
1268        public void setPreviousOffset(int offset);
1269
1270        /**
1271         * Get previous bytecode offset
1272         * @return return the recored offset of the previous bytecode
1273         */
1274        public int getPreviousOffset();
1275    }
1276
1277    /**
1278     * Base implementation of {@link Visitor}, which has empty method
1279     * bodies for all methods.
1280     */
1281    public static class BaseVisitor implements Visitor {
1282
1283        /** offset of the previously parsed bytecode */
1284        private int previousOffset;
1285
1286        BaseVisitor() {
1287            previousOffset = -1;
1288        }
1289
1290        /** {@inheritDoc} */
1291        public void visitInvalid(int opcode, int offset, int length) {
1292            // This space intentionally left blank.
1293        }
1294
1295        /** {@inheritDoc} */
1296        public void visitNoArgs(int opcode, int offset, int length,
1297                Type type) {
1298            // This space intentionally left blank.
1299        }
1300
1301        /** {@inheritDoc} */
1302        public void visitLocal(int opcode, int offset, int length,
1303                int idx, Type type, int value) {
1304            // This space intentionally left blank.
1305        }
1306
1307        /** {@inheritDoc} */
1308        public void visitConstant(int opcode, int offset, int length,
1309                Constant cst, int value) {
1310            // This space intentionally left blank.
1311        }
1312
1313        /** {@inheritDoc} */
1314        public void visitBranch(int opcode, int offset, int length,
1315                int target) {
1316            // This space intentionally left blank.
1317        }
1318
1319        /** {@inheritDoc} */
1320        public void visitSwitch(int opcode, int offset, int length,
1321                SwitchList cases, int padding) {
1322            // This space intentionally left blank.
1323        }
1324
1325        /** {@inheritDoc} */
1326        public void visitNewarray(int offset, int length, CstType type,
1327                ArrayList<Constant> initValues) {
1328            // This space intentionally left blank.
1329        }
1330
1331        /** {@inheritDoc} */
1332        public void setPreviousOffset(int offset) {
1333            previousOffset = offset;
1334        }
1335
1336        /** {@inheritDoc} */
1337        public int getPreviousOffset() {
1338            return previousOffset;
1339        }
1340    }
1341
1342    /**
1343     * Implementation of {@link Visitor}, which just pays attention
1344     * to constant values.
1345     */
1346    class ConstantParserVisitor extends BaseVisitor {
1347        Constant cst;
1348        int length;
1349        int value;
1350
1351        /** Empty constructor */
1352        ConstantParserVisitor() {
1353        }
1354
1355        private void clear() {
1356            length = 0;
1357        }
1358
1359        /** {@inheritDoc} */
1360        @Override
1361        public void visitInvalid(int opcode, int offset, int length) {
1362            clear();
1363        }
1364
1365        /** {@inheritDoc} */
1366        @Override
1367        public void visitNoArgs(int opcode, int offset, int length,
1368                Type type) {
1369            clear();
1370        }
1371
1372        /** {@inheritDoc} */
1373        @Override
1374        public void visitLocal(int opcode, int offset, int length,
1375                int idx, Type type, int value) {
1376            clear();
1377        }
1378
1379        /** {@inheritDoc} */
1380        @Override
1381        public void visitConstant(int opcode, int offset, int length,
1382                Constant cst, int value) {
1383            this.cst = cst;
1384            this.length = length;
1385            this.value = value;
1386        }
1387
1388        /** {@inheritDoc} */
1389        @Override
1390        public void visitBranch(int opcode, int offset, int length,
1391                int target) {
1392            clear();
1393        }
1394
1395        /** {@inheritDoc} */
1396        @Override
1397        public void visitSwitch(int opcode, int offset, int length,
1398                SwitchList cases, int padding) {
1399            clear();
1400        }
1401
1402        /** {@inheritDoc} */
1403        @Override
1404        public void visitNewarray(int offset, int length, CstType type,
1405                ArrayList<Constant> initVals) {
1406            clear();
1407        }
1408
1409        /** {@inheritDoc} */
1410        @Override
1411        public void setPreviousOffset(int offset) {
1412            // Intentionally left empty
1413        }
1414
1415        /** {@inheritDoc} */
1416        @Override
1417        public int getPreviousOffset() {
1418            // Intentionally left empty
1419            return -1;
1420        }
1421    }
1422}
1423