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);
}