1/*
2 * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26/*
27 * This file is available under and governed by the GNU General Public
28 * License version 2 only, as published by the Free Software Foundation.
29 * However, the following notice accompanied the original version of this
30 * file:
31 *
32 * ASM: a very small and fast Java bytecode manipulation framework
33 * Copyright (c) 2000-2007 INRIA, France Telecom
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 *    notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 *    notice, this list of conditions and the following disclaimer in the
43 *    documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the copyright holders nor the names of its
45 *    contributors may be used to endorse or promote products derived from
46 *    this software without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
49 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
52 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
58 * THE POSSIBILITY OF SUCH DAMAGE.
59 */
60package com.sun.xml.internal.ws.org.objectweb.asm;
61
62/**
63 * Information about the input and output stack map frames of a basic block.
64 *
65 * @author Eric Bruneton
66 */
67final class Frame {
68
69    /*
70     * Frames are computed in a two steps process: during the visit of each
71     * instruction, the state of the frame at the end of current basic block is
72     * updated by simulating the action of the instruction on the previous state
73     * of this so called "output frame". In visitMaxs, a fix point algorithm is
74     * used to compute the "input frame" of each basic block, i.e. the stack map
75     * frame at the begining of the basic block, starting from the input frame
76     * of the first basic block (which is computed from the method descriptor),
77     * and by using the previously computed output frames to compute the input
78     * state of the other blocks.
79     *
80     * All output and input frames are stored as arrays of integers. Reference
81     * and array types are represented by an index into a type table (which is
82     * not the same as the constant pool of the class, in order to avoid adding
83     * unnecessary constants in the pool - not all computed frames will end up
84     * being stored in the stack map table). This allows very fast type
85     * comparisons.
86     *
87     * Output stack map frames are computed relatively to the input frame of the
88     * basic block, which is not yet known when output frames are computed. It
89     * is therefore necessary to be able to represent abstract types such as
90     * "the type at position x in the input frame locals" or "the type at
91     * position x from the top of the input frame stack" or even "the type at
92     * position x in the input frame, with y more (or less) array dimensions".
93     * This explains the rather complicated type format used in output frames.
94     *
95     * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
96     * signed number of array dimensions (from -8 to 7). KIND is either BASE,
97     * LOCAL or STACK. BASE is used for types that are not relative to the input
98     * frame. LOCAL is used for types that are relative to the input local
99     * variable types. STACK is used for types that are relative to the input
100     * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
101     * the input local variable types. For STACK types, it is a position
102     * relatively to the top of input frame stack. For BASE types, it is either
103     * one of the constants defined in FrameVisitor, or for OBJECT and
104     * UNINITIALIZED types, a tag and an index in the type table.
105     *
106     * Output frames can contain types of any kind and with a positive or
107     * negative dimension (and even unassigned types, represented by 0 - which
108     * does not correspond to any valid type value). Input frames can only
109     * contain BASE types of positive or null dimension. In all cases the type
110     * table contains only internal type names (array type descriptors are
111     * forbidden - dimensions must be represented through the DIM field).
112     *
113     * The LONG and DOUBLE types are always represented by using two slots (LONG +
114     * TOP or DOUBLE + TOP), for local variable types as well as in the operand
115     * stack. This is necessary to be able to simulate DUPx_y instructions,
116     * whose effect would be dependent on the actual type values if types were
117     * always represented by a single slot in the stack (and this is not
118     * possible, since actual type values are not always known - cf LOCAL and
119     * STACK type kinds).
120     */
121
122    /**
123     * Mask to get the dimension of a frame type. This dimension is a signed
124     * integer between -8 and 7.
125     */
126    static final int DIM = 0xF0000000;
127
128    /**
129     * Constant to be added to a type to get a type with one more dimension.
130     */
131    static final int ARRAY_OF = 0x10000000;
132
133    /**
134     * Constant to be added to a type to get a type with one less dimension.
135     */
136    static final int ELEMENT_OF = 0xF0000000;
137
138    /**
139     * Mask to get the kind of a frame type.
140     *
141     * @see #BASE
142     * @see #LOCAL
143     * @see #STACK
144     */
145    static final int KIND = 0xF000000;
146
147    /**
148     * Mask to get the value of a frame type.
149     */
150    static final int VALUE = 0xFFFFFF;
151
152    /**
153     * Mask to get the kind of base types.
154     */
155    static final int BASE_KIND = 0xFF00000;
156
157    /**
158     * Mask to get the value of base types.
159     */
160    static final int BASE_VALUE = 0xFFFFF;
161
162    /**
163     * Kind of the types that are not relative to an input stack map frame.
164     */
165    static final int BASE = 0x1000000;
166
167    /**
168     * Base kind of the base reference types. The BASE_VALUE of such types is an
169     * index into the type table.
170     */
171    static final int OBJECT = BASE | 0x700000;
172
173    /**
174     * Base kind of the uninitialized base types. The BASE_VALUE of such types
175     * in an index into the type table (the Item at that index contains both an
176     * instruction offset and an internal class name).
177     */
178    static final int UNINITIALIZED = BASE | 0x800000;
179
180    /**
181     * Kind of the types that are relative to the local variable types of an
182     * input stack map frame. The value of such types is a local variable index.
183     */
184    private static final int LOCAL = 0x2000000;
185
186    /**
187     * Kind of the the types that are relative to the stack of an input stack
188     * map frame. The value of such types is a position relatively to the top of
189     * this stack.
190     */
191    private static final int STACK = 0x3000000;
192
193    /**
194     * The TOP type. This is a BASE type.
195     */
196    static final int TOP = BASE | 0;
197
198    /**
199     * The BOOLEAN type. This is a BASE type mainly used for array types.
200     */
201    static final int BOOLEAN = BASE | 9;
202
203    /**
204     * The BYTE type. This is a BASE type mainly used for array types.
205     */
206    static final int BYTE = BASE | 10;
207
208    /**
209     * The CHAR type. This is a BASE type mainly used for array types.
210     */
211    static final int CHAR = BASE | 11;
212
213    /**
214     * The SHORT type. This is a BASE type mainly used for array types.
215     */
216    static final int SHORT = BASE | 12;
217
218    /**
219     * The INTEGER type. This is a BASE type.
220     */
221    static final int INTEGER = BASE | 1;
222
223    /**
224     * The FLOAT type. This is a BASE type.
225     */
226    static final int FLOAT = BASE | 2;
227
228    /**
229     * The DOUBLE type. This is a BASE type.
230     */
231    static final int DOUBLE = BASE | 3;
232
233    /**
234     * The LONG type. This is a BASE type.
235     */
236    static final int LONG = BASE | 4;
237
238    /**
239     * The NULL type. This is a BASE type.
240     */
241    static final int NULL = BASE | 5;
242
243    /**
244     * The UNINITIALIZED_THIS type. This is a BASE type.
245     */
246    static final int UNINITIALIZED_THIS = BASE | 6;
247
248    /**
249     * The stack size variation corresponding to each JVM instruction. This
250     * stack variation is equal to the size of the values produced by an
251     * instruction, minus the size of the values consumed by this instruction.
252     */
253    static final int[] SIZE;
254
255    /**
256     * Computes the stack size variation corresponding to each JVM instruction.
257     */
258    static {
259        int i;
260        int[] b = new int[202];
261        String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
262                + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
263                + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
264                + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
265        for (i = 0; i < b.length; ++i) {
266            b[i] = s.charAt(i) - 'E';
267        }
268        SIZE = b;
269
270        // code to generate the above string
271        //
272        // int NA = 0; // not applicable (unused opcode or variable size opcode)
273        //
274        // b = new int[] {
275        // 0, //NOP, // visitInsn
276        // 1, //ACONST_NULL, // -
277        // 1, //ICONST_M1, // -
278        // 1, //ICONST_0, // -
279        // 1, //ICONST_1, // -
280        // 1, //ICONST_2, // -
281        // 1, //ICONST_3, // -
282        // 1, //ICONST_4, // -
283        // 1, //ICONST_5, // -
284        // 2, //LCONST_0, // -
285        // 2, //LCONST_1, // -
286        // 1, //FCONST_0, // -
287        // 1, //FCONST_1, // -
288        // 1, //FCONST_2, // -
289        // 2, //DCONST_0, // -
290        // 2, //DCONST_1, // -
291        // 1, //BIPUSH, // visitIntInsn
292        // 1, //SIPUSH, // -
293        // 1, //LDC, // visitLdcInsn
294        // NA, //LDC_W, // -
295        // NA, //LDC2_W, // -
296        // 1, //ILOAD, // visitVarInsn
297        // 2, //LLOAD, // -
298        // 1, //FLOAD, // -
299        // 2, //DLOAD, // -
300        // 1, //ALOAD, // -
301        // NA, //ILOAD_0, // -
302        // NA, //ILOAD_1, // -
303        // NA, //ILOAD_2, // -
304        // NA, //ILOAD_3, // -
305        // NA, //LLOAD_0, // -
306        // NA, //LLOAD_1, // -
307        // NA, //LLOAD_2, // -
308        // NA, //LLOAD_3, // -
309        // NA, //FLOAD_0, // -
310        // NA, //FLOAD_1, // -
311        // NA, //FLOAD_2, // -
312        // NA, //FLOAD_3, // -
313        // NA, //DLOAD_0, // -
314        // NA, //DLOAD_1, // -
315        // NA, //DLOAD_2, // -
316        // NA, //DLOAD_3, // -
317        // NA, //ALOAD_0, // -
318        // NA, //ALOAD_1, // -
319        // NA, //ALOAD_2, // -
320        // NA, //ALOAD_3, // -
321        // -1, //IALOAD, // visitInsn
322        // 0, //LALOAD, // -
323        // -1, //FALOAD, // -
324        // 0, //DALOAD, // -
325        // -1, //AALOAD, // -
326        // -1, //BALOAD, // -
327        // -1, //CALOAD, // -
328        // -1, //SALOAD, // -
329        // -1, //ISTORE, // visitVarInsn
330        // -2, //LSTORE, // -
331        // -1, //FSTORE, // -
332        // -2, //DSTORE, // -
333        // -1, //ASTORE, // -
334        // NA, //ISTORE_0, // -
335        // NA, //ISTORE_1, // -
336        // NA, //ISTORE_2, // -
337        // NA, //ISTORE_3, // -
338        // NA, //LSTORE_0, // -
339        // NA, //LSTORE_1, // -
340        // NA, //LSTORE_2, // -
341        // NA, //LSTORE_3, // -
342        // NA, //FSTORE_0, // -
343        // NA, //FSTORE_1, // -
344        // NA, //FSTORE_2, // -
345        // NA, //FSTORE_3, // -
346        // NA, //DSTORE_0, // -
347        // NA, //DSTORE_1, // -
348        // NA, //DSTORE_2, // -
349        // NA, //DSTORE_3, // -
350        // NA, //ASTORE_0, // -
351        // NA, //ASTORE_1, // -
352        // NA, //ASTORE_2, // -
353        // NA, //ASTORE_3, // -
354        // -3, //IASTORE, // visitInsn
355        // -4, //LASTORE, // -
356        // -3, //FASTORE, // -
357        // -4, //DASTORE, // -
358        // -3, //AASTORE, // -
359        // -3, //BASTORE, // -
360        // -3, //CASTORE, // -
361        // -3, //SASTORE, // -
362        // -1, //POP, // -
363        // -2, //POP2, // -
364        // 1, //DUP, // -
365        // 1, //DUP_X1, // -
366        // 1, //DUP_X2, // -
367        // 2, //DUP2, // -
368        // 2, //DUP2_X1, // -
369        // 2, //DUP2_X2, // -
370        // 0, //SWAP, // -
371        // -1, //IADD, // -
372        // -2, //LADD, // -
373        // -1, //FADD, // -
374        // -2, //DADD, // -
375        // -1, //ISUB, // -
376        // -2, //LSUB, // -
377        // -1, //FSUB, // -
378        // -2, //DSUB, // -
379        // -1, //IMUL, // -
380        // -2, //LMUL, // -
381        // -1, //FMUL, // -
382        // -2, //DMUL, // -
383        // -1, //IDIV, // -
384        // -2, //LDIV, // -
385        // -1, //FDIV, // -
386        // -2, //DDIV, // -
387        // -1, //IREM, // -
388        // -2, //LREM, // -
389        // -1, //FREM, // -
390        // -2, //DREM, // -
391        // 0, //INEG, // -
392        // 0, //LNEG, // -
393        // 0, //FNEG, // -
394        // 0, //DNEG, // -
395        // -1, //ISHL, // -
396        // -1, //LSHL, // -
397        // -1, //ISHR, // -
398        // -1, //LSHR, // -
399        // -1, //IUSHR, // -
400        // -1, //LUSHR, // -
401        // -1, //IAND, // -
402        // -2, //LAND, // -
403        // -1, //IOR, // -
404        // -2, //LOR, // -
405        // -1, //IXOR, // -
406        // -2, //LXOR, // -
407        // 0, //IINC, // visitIincInsn
408        // 1, //I2L, // visitInsn
409        // 0, //I2F, // -
410        // 1, //I2D, // -
411        // -1, //L2I, // -
412        // -1, //L2F, // -
413        // 0, //L2D, // -
414        // 0, //F2I, // -
415        // 1, //F2L, // -
416        // 1, //F2D, // -
417        // -1, //D2I, // -
418        // 0, //D2L, // -
419        // -1, //D2F, // -
420        // 0, //I2B, // -
421        // 0, //I2C, // -
422        // 0, //I2S, // -
423        // -3, //LCMP, // -
424        // -1, //FCMPL, // -
425        // -1, //FCMPG, // -
426        // -3, //DCMPL, // -
427        // -3, //DCMPG, // -
428        // -1, //IFEQ, // visitJumpInsn
429        // -1, //IFNE, // -
430        // -1, //IFLT, // -
431        // -1, //IFGE, // -
432        // -1, //IFGT, // -
433        // -1, //IFLE, // -
434        // -2, //IF_ICMPEQ, // -
435        // -2, //IF_ICMPNE, // -
436        // -2, //IF_ICMPLT, // -
437        // -2, //IF_ICMPGE, // -
438        // -2, //IF_ICMPGT, // -
439        // -2, //IF_ICMPLE, // -
440        // -2, //IF_ACMPEQ, // -
441        // -2, //IF_ACMPNE, // -
442        // 0, //GOTO, // -
443        // 1, //JSR, // -
444        // 0, //RET, // visitVarInsn
445        // -1, //TABLESWITCH, // visiTableSwitchInsn
446        // -1, //LOOKUPSWITCH, // visitLookupSwitch
447        // -1, //IRETURN, // visitInsn
448        // -2, //LRETURN, // -
449        // -1, //FRETURN, // -
450        // -2, //DRETURN, // -
451        // -1, //ARETURN, // -
452        // 0, //RETURN, // -
453        // NA, //GETSTATIC, // visitFieldInsn
454        // NA, //PUTSTATIC, // -
455        // NA, //GETFIELD, // -
456        // NA, //PUTFIELD, // -
457        // NA, //INVOKEVIRTUAL, // visitMethodInsn
458        // NA, //INVOKESPECIAL, // -
459        // NA, //INVOKESTATIC, // -
460        // NA, //INVOKEINTERFACE, // -
461        // NA, //UNUSED, // NOT VISITED
462        // 1, //NEW, // visitTypeInsn
463        // 0, //NEWARRAY, // visitIntInsn
464        // 0, //ANEWARRAY, // visitTypeInsn
465        // 0, //ARRAYLENGTH, // visitInsn
466        // NA, //ATHROW, // -
467        // 0, //CHECKCAST, // visitTypeInsn
468        // 0, //INSTANCEOF, // -
469        // -1, //MONITORENTER, // visitInsn
470        // -1, //MONITOREXIT, // -
471        // NA, //WIDE, // NOT VISITED
472        // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
473        // -1, //IFNULL, // visitJumpInsn
474        // -1, //IFNONNULL, // -
475        // NA, //GOTO_W, // -
476        // NA, //JSR_W, // -
477        // };
478        // for (i = 0; i < b.length; ++i) {
479        // System.err.print((char)('E' + b[i]));
480        // }
481        // System.err.println();
482    }
483
484    /**
485     * The label (i.e. basic block) to which these input and output stack map
486     * frames correspond.
487     */
488    Label owner;
489
490    /**
491     * The input stack map frame locals.
492     */
493    int[] inputLocals;
494
495    /**
496     * The input stack map frame stack.
497     */
498    int[] inputStack;
499
500    /**
501     * The output stack map frame locals.
502     */
503    private int[] outputLocals;
504
505    /**
506     * The output stack map frame stack.
507     */
508    private int[] outputStack;
509
510    /**
511     * Relative size of the output stack. The exact semantics of this field
512     * depends on the algorithm that is used.
513     *
514     * When only the maximum stack size is computed, this field is the size of
515     * the output stack relatively to the top of the input stack.
516     *
517     * When the stack map frames are completely computed, this field is the
518     * actual number of types in {@link #outputStack}.
519     */
520    private int outputStackTop;
521
522    /**
523     * Number of types that are initialized in the basic block.
524     *
525     * @see #initializations
526     */
527    private int initializationCount;
528
529    /**
530     * The types that are initialized in the basic block. A constructor
531     * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
532     * <i>every occurence</i> of this type in the local variables and in the
533     * operand stack. This cannot be done during the first phase of the
534     * algorithm since, during this phase, the local variables and the operand
535     * stack are not completely computed. It is therefore necessary to store the
536     * types on which constructors are invoked in the basic block, in order to
537     * do this replacement during the second phase of the algorithm, where the
538     * frames are fully computed. Note that this array can contain types that
539     * are relative to input locals or to the input stack (see below for the
540     * description of the algorithm).
541     */
542    private int[] initializations;
543
544    /**
545     * Returns the output frame local variable type at the given index.
546     *
547     * @param local the index of the local that must be returned.
548     * @return the output frame local variable type at the given index.
549     */
550    private int get(final int local) {
551        if (outputLocals == null || local >= outputLocals.length) {
552            // this local has never been assigned in this basic block,
553            // so it is still equal to its value in the input frame
554            return LOCAL | local;
555        } else {
556            int type = outputLocals[local];
557            if (type == 0) {
558                // this local has never been assigned in this basic block,
559                // so it is still equal to its value in the input frame
560                type = outputLocals[local] = LOCAL | local;
561            }
562            return type;
563        }
564    }
565
566    /**
567     * Sets the output frame local variable type at the given index.
568     *
569     * @param local the index of the local that must be set.
570     * @param type the value of the local that must be set.
571     */
572    private void set(final int local, final int type) {
573        // creates and/or resizes the output local variables array if necessary
574        if (outputLocals == null) {
575            outputLocals = new int[10];
576        }
577        int n = outputLocals.length;
578        if (local >= n) {
579            int[] t = new int[Math.max(local + 1, 2 * n)];
580            System.arraycopy(outputLocals, 0, t, 0, n);
581            outputLocals = t;
582        }
583        // sets the local variable
584        outputLocals[local] = type;
585    }
586
587    /**
588     * Pushes a new type onto the output frame stack.
589     *
590     * @param type the type that must be pushed.
591     */
592    private void push(final int type) {
593        // creates and/or resizes the output stack array if necessary
594        if (outputStack == null) {
595            outputStack = new int[10];
596        }
597        int n = outputStack.length;
598        if (outputStackTop >= n) {
599            int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];
600            System.arraycopy(outputStack, 0, t, 0, n);
601            outputStack = t;
602        }
603        // pushes the type on the output stack
604        outputStack[outputStackTop++] = type;
605        // updates the maximun height reached by the output stack, if needed
606        int top = owner.inputStackTop + outputStackTop;
607        if (top > owner.outputStackMax) {
608            owner.outputStackMax = top;
609        }
610    }
611
612    /**
613     * Pushes a new type onto the output frame stack.
614     *
615     * @param cw the ClassWriter to which this label belongs.
616     * @param desc the descriptor of the type to be pushed. Can also be a method
617     *        descriptor (in this case this method pushes its return type onto
618     *        the output frame stack).
619     */
620    private void push(final ClassWriter cw, final String desc) {
621        int type = type(cw, desc);
622        if (type != 0) {
623            push(type);
624            if (type == LONG || type == DOUBLE) {
625                push(TOP);
626            }
627        }
628    }
629
630    /**
631     * Returns the int encoding of the given type.
632     *
633     * @param cw the ClassWriter to which this label belongs.
634     * @param desc a type descriptor.
635     * @return the int encoding of the given type.
636     */
637    private static int type(final ClassWriter cw, final String desc) {
638        String t;
639        int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
640        switch (desc.charAt(index)) {
641            case 'V':
642                return 0;
643            case 'Z':
644            case 'C':
645            case 'B':
646            case 'S':
647            case 'I':
648                return INTEGER;
649            case 'F':
650                return FLOAT;
651            case 'J':
652                return LONG;
653            case 'D':
654                return DOUBLE;
655            case 'L':
656                // stores the internal name, not the descriptor!
657                t = desc.substring(index + 1, desc.length() - 1);
658                return OBJECT | cw.addType(t);
659                // case '[':
660            default:
661                // extracts the dimensions and the element type
662                int data;
663                int dims = index + 1;
664                while (desc.charAt(dims) == '[') {
665                    ++dims;
666                }
667                switch (desc.charAt(dims)) {
668                    case 'Z':
669                        data = BOOLEAN;
670                        break;
671                    case 'C':
672                        data = CHAR;
673                        break;
674                    case 'B':
675                        data = BYTE;
676                        break;
677                    case 'S':
678                        data = SHORT;
679                        break;
680                    case 'I':
681                        data = INTEGER;
682                        break;
683                    case 'F':
684                        data = FLOAT;
685                        break;
686                    case 'J':
687                        data = LONG;
688                        break;
689                    case 'D':
690                        data = DOUBLE;
691                        break;
692                    // case 'L':
693                    default:
694                        // stores the internal name, not the descriptor
695                        t = desc.substring(dims + 1, desc.length() - 1);
696                        data = OBJECT | cw.addType(t);
697                }
698                return (dims - index) << 28 | data;
699        }
700    }
701
702    /**
703     * Pops a type from the output frame stack and returns its value.
704     *
705     * @return the type that has been popped from the output frame stack.
706     */
707    private int pop() {
708        if (outputStackTop > 0) {
709            return outputStack[--outputStackTop];
710        } else {
711            // if the output frame stack is empty, pops from the input stack
712            return STACK | -(--owner.inputStackTop);
713        }
714    }
715
716    /**
717     * Pops the given number of types from the output frame stack.
718     *
719     * @param elements the number of types that must be popped.
720     */
721    private void pop(final int elements) {
722        if (outputStackTop >= elements) {
723            outputStackTop -= elements;
724        } else {
725            // if the number of elements to be popped is greater than the number
726            // of elements in the output stack, clear it, and pops the remaining
727            // elements from the input stack.
728            owner.inputStackTop -= elements - outputStackTop;
729            outputStackTop = 0;
730        }
731    }
732
733    /**
734     * Pops a type from the output frame stack.
735     *
736     * @param desc the descriptor of the type to be popped. Can also be a method
737     *        descriptor (in this case this method pops the types corresponding
738     *        to the method arguments).
739     */
740    private void pop(final String desc) {
741        char c = desc.charAt(0);
742        if (c == '(') {
743            pop((MethodWriter.getArgumentsAndReturnSizes(desc) >> 2) - 1);
744        } else if (c == 'J' || c == 'D') {
745            pop(2);
746        } else {
747            pop(1);
748        }
749    }
750
751    /**
752     * Adds a new type to the list of types on which a constructor is invoked in
753     * the basic block.
754     *
755     * @param var a type on a which a constructor is invoked.
756     */
757    private void init(final int var) {
758        // creates and/or resizes the initializations array if necessary
759        if (initializations == null) {
760            initializations = new int[2];
761        }
762        int n = initializations.length;
763        if (initializationCount >= n) {
764            int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
765            System.arraycopy(initializations, 0, t, 0, n);
766            initializations = t;
767        }
768        // stores the type to be initialized
769        initializations[initializationCount++] = var;
770    }
771
772    /**
773     * Replaces the given type with the appropriate type if it is one of the
774     * types on which a constructor is invoked in the basic block.
775     *
776     * @param cw the ClassWriter to which this label belongs.
777     * @param t a type
778     * @return t or, if t is one of the types on which a constructor is invoked
779     *         in the basic block, the type corresponding to this constructor.
780     */
781    private int init(final ClassWriter cw, final int t) {
782        int s;
783        if (t == UNINITIALIZED_THIS) {
784            s = OBJECT | cw.addType(cw.thisName);
785        } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) {
786            String type = cw.typeTable[t & BASE_VALUE].strVal1;
787            s = OBJECT | cw.addType(type);
788        } else {
789            return t;
790        }
791        for (int j = 0; j < initializationCount; ++j) {
792            int u = initializations[j];
793            int dim = u & DIM;
794            int kind = u & KIND;
795            if (kind == LOCAL) {
796                u = dim + inputLocals[u & VALUE];
797            } else if (kind == STACK) {
798                u = dim + inputStack[inputStack.length - (u & VALUE)];
799            }
800            if (t == u) {
801                return s;
802            }
803        }
804        return t;
805    }
806
807    /**
808     * Initializes the input frame of the first basic block from the method
809     * descriptor.
810     *
811     * @param cw the ClassWriter to which this label belongs.
812     * @param access the access flags of the method to which this label belongs.
813     * @param args the formal parameter types of this method.
814     * @param maxLocals the maximum number of local variables of this method.
815     */
816    void initInputFrame(
817        final ClassWriter cw,
818        final int access,
819        final Type[] args,
820        final int maxLocals)
821    {
822        inputLocals = new int[maxLocals];
823        inputStack = new int[0];
824        int i = 0;
825        if ((access & Opcodes.ACC_STATIC) == 0) {
826            if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) {
827                inputLocals[i++] = OBJECT | cw.addType(cw.thisName);
828            } else {
829                inputLocals[i++] = UNINITIALIZED_THIS;
830            }
831        }
832        for (int j = 0; j < args.length; ++j) {
833            int t = type(cw, args[j].getDescriptor());
834            inputLocals[i++] = t;
835            if (t == LONG || t == DOUBLE) {
836                inputLocals[i++] = TOP;
837            }
838        }
839        while (i < maxLocals) {
840            inputLocals[i++] = TOP;
841        }
842    }
843
844    /**
845     * Simulates the action of the given instruction on the output stack frame.
846     *
847     * @param opcode the opcode of the instruction.
848     * @param arg the operand of the instruction, if any.
849     * @param cw the class writer to which this label belongs.
850     * @param item the operand of the instructions, if any.
851     */
852    void execute(
853        final int opcode,
854        final int arg,
855        final ClassWriter cw,
856        final Item item)
857    {
858        int t1, t2, t3, t4;
859        switch (opcode) {
860            case Opcodes.NOP:
861            case Opcodes.INEG:
862            case Opcodes.LNEG:
863            case Opcodes.FNEG:
864            case Opcodes.DNEG:
865            case Opcodes.I2B:
866            case Opcodes.I2C:
867            case Opcodes.I2S:
868            case Opcodes.GOTO:
869            case Opcodes.RETURN:
870                break;
871            case Opcodes.ACONST_NULL:
872                push(NULL);
873                break;
874            case Opcodes.ICONST_M1:
875            case Opcodes.ICONST_0:
876            case Opcodes.ICONST_1:
877            case Opcodes.ICONST_2:
878            case Opcodes.ICONST_3:
879            case Opcodes.ICONST_4:
880            case Opcodes.ICONST_5:
881            case Opcodes.BIPUSH:
882            case Opcodes.SIPUSH:
883            case Opcodes.ILOAD:
884                push(INTEGER);
885                break;
886            case Opcodes.LCONST_0:
887            case Opcodes.LCONST_1:
888            case Opcodes.LLOAD:
889                push(LONG);
890                push(TOP);
891                break;
892            case Opcodes.FCONST_0:
893            case Opcodes.FCONST_1:
894            case Opcodes.FCONST_2:
895            case Opcodes.FLOAD:
896                push(FLOAT);
897                break;
898            case Opcodes.DCONST_0:
899            case Opcodes.DCONST_1:
900            case Opcodes.DLOAD:
901                push(DOUBLE);
902                push(TOP);
903                break;
904            case Opcodes.LDC:
905                switch (item.type) {
906                    case ClassWriter.INT:
907                        push(INTEGER);
908                        break;
909                    case ClassWriter.LONG:
910                        push(LONG);
911                        push(TOP);
912                        break;
913                    case ClassWriter.FLOAT:
914                        push(FLOAT);
915                        break;
916                    case ClassWriter.DOUBLE:
917                        push(DOUBLE);
918                        push(TOP);
919                        break;
920                    case ClassWriter.CLASS:
921                        push(OBJECT | cw.addType("java/lang/Class"));
922                        break;
923                    // case ClassWriter.STR:
924                    default:
925                        push(OBJECT | cw.addType("java/lang/String"));
926                }
927                break;
928            case Opcodes.ALOAD:
929                push(get(arg));
930                break;
931            case Opcodes.IALOAD:
932            case Opcodes.BALOAD:
933            case Opcodes.CALOAD:
934            case Opcodes.SALOAD:
935                pop(2);
936                push(INTEGER);
937                break;
938            case Opcodes.LALOAD:
939            case Opcodes.D2L:
940                pop(2);
941                push(LONG);
942                push(TOP);
943                break;
944            case Opcodes.FALOAD:
945                pop(2);
946                push(FLOAT);
947                break;
948            case Opcodes.DALOAD:
949            case Opcodes.L2D:
950                pop(2);
951                push(DOUBLE);
952                push(TOP);
953                break;
954            case Opcodes.AALOAD:
955                pop(1);
956                t1 = pop();
957                push(ELEMENT_OF + t1);
958                break;
959            case Opcodes.ISTORE:
960            case Opcodes.FSTORE:
961            case Opcodes.ASTORE:
962                t1 = pop();
963                set(arg, t1);
964                if (arg > 0) {
965                    t2 = get(arg - 1);
966                    // if t2 is of kind STACK or LOCAL we cannot know its size!
967                    if (t2 == LONG || t2 == DOUBLE) {
968                        set(arg - 1, TOP);
969                    }
970                }
971                break;
972            case Opcodes.LSTORE:
973            case Opcodes.DSTORE:
974                pop(1);
975                t1 = pop();
976                set(arg, t1);
977                set(arg + 1, TOP);
978                if (arg > 0) {
979                    t2 = get(arg - 1);
980                    // if t2 is of kind STACK or LOCAL we cannot know its size!
981                    if (t2 == LONG || t2 == DOUBLE) {
982                        set(arg - 1, TOP);
983                    }
984                }
985                break;
986            case Opcodes.IASTORE:
987            case Opcodes.BASTORE:
988            case Opcodes.CASTORE:
989            case Opcodes.SASTORE:
990            case Opcodes.FASTORE:
991            case Opcodes.AASTORE:
992                pop(3);
993                break;
994            case Opcodes.LASTORE:
995            case Opcodes.DASTORE:
996                pop(4);
997                break;
998            case Opcodes.POP:
999            case Opcodes.IFEQ:
1000            case Opcodes.IFNE:
1001            case Opcodes.IFLT:
1002            case Opcodes.IFGE:
1003            case Opcodes.IFGT:
1004            case Opcodes.IFLE:
1005            case Opcodes.IRETURN:
1006            case Opcodes.FRETURN:
1007            case Opcodes.ARETURN:
1008            case Opcodes.TABLESWITCH:
1009            case Opcodes.LOOKUPSWITCH:
1010            case Opcodes.ATHROW:
1011            case Opcodes.MONITORENTER:
1012            case Opcodes.MONITOREXIT:
1013            case Opcodes.IFNULL:
1014            case Opcodes.IFNONNULL:
1015                pop(1);
1016                break;
1017            case Opcodes.POP2:
1018            case Opcodes.IF_ICMPEQ:
1019            case Opcodes.IF_ICMPNE:
1020            case Opcodes.IF_ICMPLT:
1021            case Opcodes.IF_ICMPGE:
1022            case Opcodes.IF_ICMPGT:
1023            case Opcodes.IF_ICMPLE:
1024            case Opcodes.IF_ACMPEQ:
1025            case Opcodes.IF_ACMPNE:
1026            case Opcodes.LRETURN:
1027            case Opcodes.DRETURN:
1028                pop(2);
1029                break;
1030            case Opcodes.DUP:
1031                t1 = pop();
1032                push(t1);
1033                push(t1);
1034                break;
1035            case Opcodes.DUP_X1:
1036                t1 = pop();
1037                t2 = pop();
1038                push(t1);
1039                push(t2);
1040                push(t1);
1041                break;
1042            case Opcodes.DUP_X2:
1043                t1 = pop();
1044                t2 = pop();
1045                t3 = pop();
1046                push(t1);
1047                push(t3);
1048                push(t2);
1049                push(t1);
1050                break;
1051            case Opcodes.DUP2:
1052                t1 = pop();
1053                t2 = pop();
1054                push(t2);
1055                push(t1);
1056                push(t2);
1057                push(t1);
1058                break;
1059            case Opcodes.DUP2_X1:
1060                t1 = pop();
1061                t2 = pop();
1062                t3 = pop();
1063                push(t2);
1064                push(t1);
1065                push(t3);
1066                push(t2);
1067                push(t1);
1068                break;
1069            case Opcodes.DUP2_X2:
1070                t1 = pop();
1071                t2 = pop();
1072                t3 = pop();
1073                t4 = pop();
1074                push(t2);
1075                push(t1);
1076                push(t4);
1077                push(t3);
1078                push(t2);
1079                push(t1);
1080                break;
1081            case Opcodes.SWAP:
1082                t1 = pop();
1083                t2 = pop();
1084                push(t1);
1085                push(t2);
1086                break;
1087            case Opcodes.IADD:
1088            case Opcodes.ISUB:
1089            case Opcodes.IMUL:
1090            case Opcodes.IDIV:
1091            case Opcodes.IREM:
1092            case Opcodes.IAND:
1093            case Opcodes.IOR:
1094            case Opcodes.IXOR:
1095            case Opcodes.ISHL:
1096            case Opcodes.ISHR:
1097            case Opcodes.IUSHR:
1098            case Opcodes.L2I:
1099            case Opcodes.D2I:
1100            case Opcodes.FCMPL:
1101            case Opcodes.FCMPG:
1102                pop(2);
1103                push(INTEGER);
1104                break;
1105            case Opcodes.LADD:
1106            case Opcodes.LSUB:
1107            case Opcodes.LMUL:
1108            case Opcodes.LDIV:
1109            case Opcodes.LREM:
1110            case Opcodes.LAND:
1111            case Opcodes.LOR:
1112            case Opcodes.LXOR:
1113                pop(4);
1114                push(LONG);
1115                push(TOP);
1116                break;
1117            case Opcodes.FADD:
1118            case Opcodes.FSUB:
1119            case Opcodes.FMUL:
1120            case Opcodes.FDIV:
1121            case Opcodes.FREM:
1122            case Opcodes.L2F:
1123            case Opcodes.D2F:
1124                pop(2);
1125                push(FLOAT);
1126                break;
1127            case Opcodes.DADD:
1128            case Opcodes.DSUB:
1129            case Opcodes.DMUL:
1130            case Opcodes.DDIV:
1131            case Opcodes.DREM:
1132                pop(4);
1133                push(DOUBLE);
1134                push(TOP);
1135                break;
1136            case Opcodes.LSHL:
1137            case Opcodes.LSHR:
1138            case Opcodes.LUSHR:
1139                pop(3);
1140                push(LONG);
1141                push(TOP);
1142                break;
1143            case Opcodes.IINC:
1144                set(arg, INTEGER);
1145                break;
1146            case Opcodes.I2L:
1147            case Opcodes.F2L:
1148                pop(1);
1149                push(LONG);
1150                push(TOP);
1151                break;
1152            case Opcodes.I2F:
1153                pop(1);
1154                push(FLOAT);
1155                break;
1156            case Opcodes.I2D:
1157            case Opcodes.F2D:
1158                pop(1);
1159                push(DOUBLE);
1160                push(TOP);
1161                break;
1162            case Opcodes.F2I:
1163            case Opcodes.ARRAYLENGTH:
1164            case Opcodes.INSTANCEOF:
1165                pop(1);
1166                push(INTEGER);
1167                break;
1168            case Opcodes.LCMP:
1169            case Opcodes.DCMPL:
1170            case Opcodes.DCMPG:
1171                pop(4);
1172                push(INTEGER);
1173                break;
1174            case Opcodes.JSR:
1175            case Opcodes.RET:
1176                throw new RuntimeException("JSR/RET are not supported with computeFrames option");
1177            case Opcodes.GETSTATIC:
1178                push(cw, item.strVal3);
1179                break;
1180            case Opcodes.PUTSTATIC:
1181                pop(item.strVal3);
1182                break;
1183            case Opcodes.GETFIELD:
1184                pop(1);
1185                push(cw, item.strVal3);
1186                break;
1187            case Opcodes.PUTFIELD:
1188                pop(item.strVal3);
1189                pop();
1190                break;
1191            case Opcodes.INVOKEVIRTUAL:
1192            case Opcodes.INVOKESPECIAL:
1193            case Opcodes.INVOKESTATIC:
1194            case Opcodes.INVOKEINTERFACE:
1195                pop(item.strVal3);
1196                if (opcode != Opcodes.INVOKESTATIC) {
1197                    t1 = pop();
1198                    if (opcode == Opcodes.INVOKESPECIAL
1199                            && item.strVal2.charAt(0) == '<')
1200                    {
1201                        init(t1);
1202                    }
1203                }
1204                push(cw, item.strVal3);
1205                break;
1206            case Opcodes.NEW:
1207                push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
1208                break;
1209            case Opcodes.NEWARRAY:
1210                pop();
1211                switch (arg) {
1212                    case Opcodes.T_BOOLEAN:
1213                        push(ARRAY_OF | BOOLEAN);
1214                        break;
1215                    case Opcodes.T_CHAR:
1216                        push(ARRAY_OF | CHAR);
1217                        break;
1218                    case Opcodes.T_BYTE:
1219                        push(ARRAY_OF | BYTE);
1220                        break;
1221                    case Opcodes.T_SHORT:
1222                        push(ARRAY_OF | SHORT);
1223                        break;
1224                    case Opcodes.T_INT:
1225                        push(ARRAY_OF | INTEGER);
1226                        break;
1227                    case Opcodes.T_FLOAT:
1228                        push(ARRAY_OF | FLOAT);
1229                        break;
1230                    case Opcodes.T_DOUBLE:
1231                        push(ARRAY_OF | DOUBLE);
1232                        break;
1233                    // case Opcodes.T_LONG:
1234                    default:
1235                        push(ARRAY_OF | LONG);
1236                        break;
1237                }
1238                break;
1239            case Opcodes.ANEWARRAY:
1240                String s = item.strVal1;
1241                pop();
1242                if (s.charAt(0) == '[') {
1243                    push(cw, '[' + s);
1244                } else {
1245                    push(ARRAY_OF | OBJECT | cw.addType(s));
1246                }
1247                break;
1248            case Opcodes.CHECKCAST:
1249                s = item.strVal1;
1250                pop();
1251                if (s.charAt(0) == '[') {
1252                    push(cw, s);
1253                } else {
1254                    push(OBJECT | cw.addType(s));
1255                }
1256                break;
1257            // case Opcodes.MULTIANEWARRAY:
1258            default:
1259                pop(arg);
1260                push(cw, item.strVal1);
1261                break;
1262        }
1263    }
1264
1265    /**
1266     * Merges the input frame of the given basic block with the input and output
1267     * frames of this basic block. Returns <tt>true</tt> if the input frame of
1268     * the given label has been changed by this operation.
1269     *
1270     * @param cw the ClassWriter to which this label belongs.
1271     * @param frame the basic block whose input frame must be updated.
1272     * @param edge the kind of the {@link Edge} between this label and 'label'.
1273     *        See {@link Edge#info}.
1274     * @return <tt>true</tt> if the input frame of the given label has been
1275     *         changed by this operation.
1276     */
1277    boolean merge(final ClassWriter cw, final Frame frame, final int edge) {
1278        boolean changed = false;
1279        int i, s, dim, kind, t;
1280
1281        int nLocal = inputLocals.length;
1282        int nStack = inputStack.length;
1283        if (frame.inputLocals == null) {
1284            frame.inputLocals = new int[nLocal];
1285            changed = true;
1286        }
1287
1288        for (i = 0; i < nLocal; ++i) {
1289            if (outputLocals != null && i < outputLocals.length) {
1290                s = outputLocals[i];
1291                if (s == 0) {
1292                    t = inputLocals[i];
1293                } else {
1294                    dim = s & DIM;
1295                    kind = s & KIND;
1296                    if (kind == LOCAL) {
1297                        t = dim + inputLocals[s & VALUE];
1298                    } else if (kind == STACK) {
1299                        t = dim + inputStack[nStack - (s & VALUE)];
1300                    } else {
1301                        t = s;
1302                    }
1303                }
1304            } else {
1305                t = inputLocals[i];
1306            }
1307            if (initializations != null) {
1308                t = init(cw, t);
1309            }
1310            changed |= merge(cw, t, frame.inputLocals, i);
1311        }
1312
1313        if (edge > 0) {
1314            for (i = 0; i < nLocal; ++i) {
1315                t = inputLocals[i];
1316                changed |= merge(cw, t, frame.inputLocals, i);
1317            }
1318            if (frame.inputStack == null) {
1319                frame.inputStack = new int[1];
1320                changed = true;
1321            }
1322            changed |= merge(cw, edge, frame.inputStack, 0);
1323            return changed;
1324        }
1325
1326        int nInputStack = inputStack.length + owner.inputStackTop;
1327        if (frame.inputStack == null) {
1328            frame.inputStack = new int[nInputStack + outputStackTop];
1329            changed = true;
1330        }
1331
1332        for (i = 0; i < nInputStack; ++i) {
1333            t = inputStack[i];
1334            if (initializations != null) {
1335                t = init(cw, t);
1336            }
1337            changed |= merge(cw, t, frame.inputStack, i);
1338        }
1339        for (i = 0; i < outputStackTop; ++i) {
1340            s = outputStack[i];
1341            dim = s & DIM;
1342            kind = s & KIND;
1343            if (kind == LOCAL) {
1344                t = dim + inputLocals[s & VALUE];
1345            } else if (kind == STACK) {
1346                t = dim + inputStack[nStack - (s & VALUE)];
1347            } else {
1348                t = s;
1349            }
1350            if (initializations != null) {
1351                t = init(cw, t);
1352            }
1353            changed |= merge(cw, t, frame.inputStack, nInputStack + i);
1354        }
1355        return changed;
1356    }
1357
1358    /**
1359     * Merges the type at the given index in the given type array with the given
1360     * type. Returns <tt>true</tt> if the type array has been modified by this
1361     * operation.
1362     *
1363     * @param cw the ClassWriter to which this label belongs.
1364     * @param t the type with which the type array element must be merged.
1365     * @param types an array of types.
1366     * @param index the index of the type that must be merged in 'types'.
1367     * @return <tt>true</tt> if the type array has been modified by this
1368     *         operation.
1369     */
1370    private static boolean merge(
1371        final ClassWriter cw,
1372        int t,
1373        final int[] types,
1374        final int index)
1375    {
1376        int u = types[index];
1377        if (u == t) {
1378            // if the types are equal, merge(u,t)=u, so there is no change
1379            return false;
1380        }
1381        if ((t & ~DIM) == NULL) {
1382            if (u == NULL) {
1383                return false;
1384            }
1385            t = NULL;
1386        }
1387        if (u == 0) {
1388            // if types[index] has never been assigned, merge(u,t)=t
1389            types[index] = t;
1390            return true;
1391        }
1392        int v;
1393        if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) {
1394            // if u is a reference type of any dimension
1395            if (t == NULL) {
1396                // if t is the NULL type, merge(u,t)=u, so there is no change
1397                return false;
1398            } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {
1399                if ((u & BASE_KIND) == OBJECT) {
1400                    // if t is also a reference type, and if u and t have the
1401                    // same dimension merge(u,t) = dim(t) | common parent of the
1402                    // element types of u and t
1403                    v = (t & DIM) | OBJECT
1404                            | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE);
1405                } else {
1406                    // if u and t are array types, but not with the same element
1407                    // type, merge(u,t)=java/lang/Object
1408                    v = OBJECT | cw.addType("java/lang/Object");
1409                }
1410            } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
1411                // if t is any other reference or array type,
1412                // merge(u,t)=java/lang/Object
1413                v = OBJECT | cw.addType("java/lang/Object");
1414            } else {
1415                // if t is any other type, merge(u,t)=TOP
1416                v = TOP;
1417            }
1418        } else if (u == NULL) {
1419            // if u is the NULL type, merge(u,t)=t,
1420            // or TOP if t is not a reference type
1421            v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP;
1422        } else {
1423            // if u is any other type, merge(u,t)=TOP whatever t
1424            v = TOP;
1425        }
1426        if (u != v) {
1427            types[index] = v;
1428            return true;
1429        }
1430        return false;
1431    }
1432}
1433