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