void readCode()

in compiler/src/main/java/org/apache/royale/abc/ABCParser.java [852:1179]


    void readCode(MethodBodyInfo mb, IMethodBodyVisitor m, ABCReader p)
    {
        int end_pos = p.pos + mb.code_len;

        //  Read the exception information to get label information 
        //  that can't be deduced from the instructions themselves.
        Map<Integer, Label> labels_by_pos = readExceptions(p, m, end_pos);

        while (p.pos < end_pos)
        {
            int insn_pos = p.pos;
            int op = p.readU8();

            switch (op)
            {
                //  Instructions with no operands.
                case OP_add:
                case OP_add_i:
                case OP_astypelate:
                case OP_bitand:
                case OP_bitnot:
                case OP_bitor:
                case OP_bitxor:
                case OP_checkfilter:
                case OP_coerce_a:
                case OP_coerce_b:
                case OP_coerce_d:
                case OP_coerce_i:
                case OP_coerce_s:
                case OP_convert_b:
                case OP_convert_i:
                case OP_convert_d:
                case OP_convert_o:
                case OP_convert_u:
                case OP_convert_s:
                case OP_decrement:
                case OP_decrement_i:
                case OP_divide:
                case OP_dup:
                case OP_dxnslate:
                case OP_equals:
                case OP_esc_xattr:
                case OP_esc_xelem:
                case OP_getglobalscope:
                case OP_getlocal0:
                case OP_getlocal1:
                case OP_getlocal2:
                case OP_getlocal3:
                case OP_greaterequals:
                case OP_greaterthan:
                case OP_hasnext:
                case OP_in:
                case OP_increment:
                case OP_increment_i:
                case OP_instanceof:
                case OP_istypelate:
                case OP_lessequals:
                case OP_lessthan:
                case OP_lshift:
                case OP_modulo:
                case OP_multiply:
                case OP_multiply_i:
                case OP_negate:
                case OP_negate_i:
                case OP_newactivation:
                case OP_nextname:
                case OP_nextvalue:
                case OP_nop:
                case OP_not:
                case OP_pop:
                case OP_popscope:
                case OP_pushfalse:
                case OP_pushtrue:
                case OP_pushnan:
                case OP_pushnull:
                case OP_pushscope:
                case OP_pushundefined:
                case OP_pushwith:
                case OP_returnvalue:
                case OP_returnvoid:
                case OP_rshift:
                case OP_setlocal0:
                case OP_setlocal1:
                case OP_setlocal2:
                case OP_setlocal3:
                case OP_strictequals:
                case OP_subtract:
                case OP_subtract_i:
                case OP_swap:
                case OP_throw:
                case OP_typeof:
                case OP_unplus:
                case OP_urshift:
                case OP_bkpt:
                case OP_timestamp:
                case OP_coerce_o:
                case OP_li8:
                case OP_li16:
                case OP_li32:
                case OP_lf32:
                case OP_lf64:
                case OP_si8:
                case OP_si16:
                case OP_si32:
                case OP_sf32:
                case OP_sf64:
                case OP_sxi1:
                case OP_sxi8:
                case OP_sxi16:
                {
                    m.visitInstruction(op);
                    break;
                }

                // Opcodes with two uint operands.
                case OP_hasnext2:
                {
                    m.visitInstruction(op, new Object[] {Integer.valueOf(p.readU30()), Integer.valueOf(p.readU30())});
                    break;
                }

                // Opcodes with a MethodInfo and an integer operand.
                case OP_callstatic:
                {
                    m.visitInstruction(op, new Object[] {this.readPool(methodInfos, p.readU30(), "methodInfo"), Integer.valueOf(p.readU30())});
                    break;
                }

                // Opcodes with one name operand.
                case OP_findproperty:
                case OP_findpropstrict:
                case OP_getlex:
                case OP_getsuper:
                case OP_setsuper:
                case OP_getproperty:
                case OP_setproperty:
                case OP_deleteproperty:
                case OP_getdescendants:
                case OP_initproperty:
                case OP_istype:
                case OP_coerce:
                case OP_astype:
                case OP_finddef:
                {
                    m.visitInstruction(op, readPool(names, p.readU30(), "name"));
                    break;
                }
                
                // Opcodes with a name and an integer operand.
                case OP_callproperty:
                case OP_callproplex:
                case OP_callpropvoid:
                case OP_callsuper:
                case OP_callsupervoid:
                case OP_constructprop:
                {
                    m.visitInstruction(op, new Object[] {readPool(names, p.readU30(), "name"), p.readU30()});
                    break;
                }

                // Opcodes with an unsigned immediate operand.
                case OP_constructsuper:
                case OP_call:
                case OP_construct:
                case OP_newarray:
                case OP_newobject:
                {
                    m.visitInstruction(op, p.readU30());
                    break;
                }

                // Opcodes with a branch operand (a signed immediate operand
                // that designates a jump target).
                case OP_ifnlt:
                case OP_ifnle:
                case OP_ifngt:
                case OP_ifnge:
                case OP_iftrue:
                case OP_iffalse:
                case OP_ifeq:
                case OP_ifne:
                case OP_iflt:
                case OP_ifle:
                case OP_ifgt:
                case OP_ifge:
                case OP_ifstricteq:
                case OP_ifstrictne:
                case OP_jump:
                {
                    //  Jump offset computed from the
                    //  instruction following the branch.
                    int jump_target = p.readS24() + p.pos;

                    if (jump_target < insn_pos)
                    {
                        assert (labels_by_pos.containsKey(jump_target)) : "Unmapped backwards branch target " + jump_target + ", insn_pos " + insn_pos + ": " + labels_by_pos;
                    }

                    m.visitInstruction(op, addLabel(jump_target, labels_by_pos));
                    break;
                }

                // Lookupswitch, with a table of labels.
                case OP_lookupswitch:
                {
                    int default_case = p.readS24() + insn_pos;
                    Label default_label = addLabel(default_case, labels_by_pos);

                    int case_count = p.readU30() + 1;
                    Label[] switch_labels = new Label[case_count + 1];
                    switch_labels[case_count] = default_label;

                    for (int i = 0; i < case_count; i++)
                    {
                        int current_case = p.readS24() + insn_pos;
                        switch_labels[i] = addLabel(current_case, labels_by_pos);
                    }

                    m.visitInstruction(op, switch_labels);
                    break;
                }

                // OP_label, no operands generates a label as a side effect.
                case OP_label:
                {
                    addLabel(insn_pos, labels_by_pos);
                    m.visitInstruction(op);
                    break;
                }

                // Opcodes with an immediate integer operand.
                case OP_getlocal:
                case OP_setlocal:
                case OP_getslot:
                case OP_setslot:
                case OP_kill:
                case OP_inclocal:
                case OP_declocal:
                case OP_inclocal_i:
                case OP_declocal_i:
                case OP_newcatch:
                case OP_getglobalslot:
                case OP_setglobalslot:
                case OP_applytype:
                case OP_pushshort:
                case OP_debugline:
                case OP_bkptline:
                {
                    m.visitInstruction(op, p.readU30());
                    break;
                }

                // Opcodes with an instance operand.
                case OP_newclass:
                {
                    m.visitInstruction(op, this.readPool(classInfos, p.readU30(), "classInfo"));
                    break;
                }

                // Opcodes with a byte operand.
                case OP_pushbyte:
                case OP_getscopeobject:
                {
                    m.visitInstruction(op, p.readU8());
                    break;
                }

                // Opcodes with a string operand.
                case OP_pushstring:
                case OP_dxns:
                case OP_debugfile:
                {
                    m.visitInstruction(op, this.readPool(strings, p.readU30(), "string"));
                    break;
                }

                // Opcodes with a namespace operand.
                case OP_pushnamespace:
                {
                    m.visitInstruction(op, this.readPool(namespaces, p.readU30(), "namespace"));
                    break;
                }

                // Opcodes with a pooled operand.
                case OP_pushint:
                {
                    m.visitInstruction(op, Integer.valueOf(this.readIntPool(p.readU30())));
                    break;
                }
                case OP_pushuint:
                {
                    m.visitInstruction(op, Long.valueOf(this.readUintPool(p.readU30())));
                    break;
                }
                case OP_pushdouble:
                {
                    m.visitInstruction(op, Double.valueOf(this.readDoublePool(p.readU30())));
                    break;
                }

                // Opcodes with a function operand.
                case OP_newfunction:
                {
                    m.visitInstruction(op, this.readPool(methodInfos, p.readU30(), "methodInfo"));
                    break;
                }
                
                // Opcodes with a grab-bag of operands.
                case OP_debug:
                {
                    m.visitInstruction(op, new Object[] {p.readU8(), this.readPool(strings, p.readU30(), "string"), p.readU8(), p.readU30()});
                    break;
                }
                
                default:
                {
                    throw new IllegalArgumentException(String.format("Unknown ABC bytecode 0x%x", op));
                }
            }

            Label insn_label = labels_by_pos.get(insn_pos);
            if (insn_label != null)
                m.labelCurrent(insn_label);
        }

        //  Skip over the exception table, it's already been read.
        skipExceptions(p);
    }