package com.intellij.lang.javascript.flex.importer; import com.intellij.openapi.util.text.StringUtil; import static com.intellij.lang.javascript.flex.importer.Abc.*; /** * @author Maxim.Mossienko * Date: Oct 20, 2008 * Time: 7:00:56 PM */ class MethodInfo extends MemberInfo { int flags; String debugName; Multiname paramTypes[]; String paramNames[]; Multiname optionalValues[]; Multiname returnType; int local_count; int max_scope; int max_stack; ByteBuffer code; Traits activation; boolean anon; void dump(Abc abc, String indent, String attr, final FlexByteCodeInformationProcessor processor) { if (!processor.doDumpMember(this)) return; processor.processFunction(this, false, abc, indent, attr); } protected void dumpCode(Abc abc, String indent, FlexByteCodeInformationProcessor processor) { processor.append(indent + "{\n"); String oldindent = indent; indent += TAB; if ((flags & NEED_ACTIVATION) != 0) { processor.append(indent + "activation {\n"); activation.dump(abc, indent + TAB, "", processor); processor.append(indent + "}\n"); } processor.append(indent + "// local_count=" + local_count + " max_scope=" + max_scope + " max_stack=" + max_stack + " code_len=" + code.bytesSize() + "\n"); code.setPosition(0); LabelInfo labels = new LabelInfo(); while (!code.eof()) { int start = code.getPosition(); int opcode = code.readUnsignedByte(); if (opcode == OP_label || (labels.containsKey(start))) { processor.append(indent + "\n"); processor.append(indent + labels.labelFor(start) + ": \n"); } String str = indent + start; processor.append(str); for(int i = str.length(); i < 12; ++i) processor.append(" "); processor.append(opNames[opcode]); processor.append(opNames[opcode].length() < 8 ? "\t\t" : "\t"); switch (opcode) { case OP_debugfile: case OP_pushstring: processor.append('"' + StringUtil.replace(StringUtil.replace(abc.strings[readU32()], "\n", "\\n"), "\t", "\\t") + '"'); break; case OP_pushnamespace: processor.append(abc.namespaces[readU32()]); break; case OP_pushint: int i = abc.ints[readU32()]; processor.append(i + "\t// 0x" + Integer.toString(i, 16)); break; case OP_pushuint: int u = abc.uints[readU32()]; processor.append(u + "\t// 0x" + Integer.toString(u, 16)); break; case OP_pushdouble: processor.append(abc.doubles[readU32()].toString()); break; case OP_getsuper: case OP_setsuper: case OP_getproperty: case OP_initproperty: case OP_setproperty: case OP_getlex: case OP_findpropstrict: case OP_findproperty: case OP_finddef: case OP_deleteproperty: case OP_istype: case OP_coerce: case OP_astype: case OP_getdescendants: processor.append(abc.names[readU32()].toString()); break; case OP_constructprop: case OP_callproperty: case OP_callproplex: case OP_callsuper: case OP_callsupervoid: case OP_callpropvoid: processor.append(abc.names[readU32()].toString()); processor.append(" (" + readU32() + ")"); break; case OP_newfunction: { int method_id = readU32(); processor.processFunction(abc.methods[method_id], true, abc, "", ""); abc.methods[method_id].anon = true; break; } case OP_callstatic: processor.processFunction(abc.methods[readU32()], true, abc, "", ""); processor.append(" (" + readU32() + ")"); break; case OP_newclass: processor.append(abc.instances[readU32()].toString()); break; case OP_lookupswitch: int pos = start; int target = pos + readS24(); int maxindex = readU32(); processor.append("default:" + labels.labelFor(target)); // target + "("+(target-pos)+")" processor.append(" maxcase:" + maxindex); for (i = 0; i <= maxindex; i++) { target = pos + readS24(); processor.append(" " + labels.labelFor(target)); // target + "("+(target-pos)+")" } break; case OP_jump: case OP_iftrue: case OP_iffalse: case OP_ifeq: case OP_ifne: case OP_ifge: case OP_ifnge: case OP_ifgt: case OP_ifngt: case OP_ifle: case OP_ifnle: case OP_iflt: case OP_ifnlt: case OP_ifstricteq: case OP_ifstrictne: int offset = readS24(); target = code.getPosition() + offset; //s += target + " ("+offset+")" processor.append(labels.labelFor(target)); if (!(labels.containsKey(code.getPosition()))) processor.append("\n"); break; case OP_inclocal: case OP_declocal: case OP_inclocal_i: case OP_declocal_i: case OP_getlocal: case OP_kill: case OP_setlocal: case OP_debugline: case OP_getglobalslot: case OP_getslot: case OP_setglobalslot: case OP_setslot: case OP_pushshort: case OP_newcatch: processor.append(""+readU32()); break; case OP_debug: processor.append(""+code.readUnsignedByte()); processor.append(" " + readU32()); processor.append(" " + code.readUnsignedByte()); processor.append(" " + readU32()); break; case OP_newobject: processor.append("{" + readU32() + "}"); break; case OP_newarray: processor.append("[" + readU32() + "]"); break; case OP_call: case OP_construct: case OP_constructsuper: processor.append("(" + readU32() + ")"); break; case OP_pushbyte: case OP_getscopeobject: processor.append(""+code.readByte()); break; case OP_hasnext2: processor.append(readU32() + " " + readU32()); default: /*if (opNames[opcode] == ("0x"+opcode.toString(16).toUpperCase())) s += " UNKNOWN OPCODE"*/ break; } int size = code.getPosition() - start; abc.totalSize += size; abc.opSizes[opcode] += size; processor.append("\n"); } processor.append(oldindent + "}\n"); } int readU32() { return code.readU32(); } int readS24() { int b = code.readUnsignedByte(); b |= code.readUnsignedByte() << 8; b |= code.readByte() << 16; return b; } boolean isGetMethod() { return kind == TraitType.Getter; } boolean isSetMethod() { return kind == TraitType.Setter; } }