<commit_before>/*
 * Copyright 2013 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
module Shumway.AVM2.ABC {
  import assert = Shumway.Debug.assert;
  import notImplemented = Shumway.Debug.notImplemented;

  var filter = new Shumway.Options.Option("f", "filter", "string", "SpciMsmNtu", "[S]ource, constant[p]ool, [c]lasses, [i]nstances, [M]etadata, [s]cripts, [m]ethods, multi[N]ames, S[t]atistics, [u]tf");

  function traceArray(writer, name, array, abc = null) {
    if (array.length === 0) {
      return;
    }
    writer.enter(name + " {");
    array.forEach(function (a, idx) {
      a.trace(writer, abc);
    });
    writer.leave("}");
  }

  AbcFile.prototype.trace = function trace(writer) {
    if (filter.value.indexOf("p") >= 0) {
      this.constantPool.trace(writer);
    }
    if (filter.value.indexOf("N") >= 0) {
      traceMultinamesOnly(this.constantPool, writer);
    }
    if (filter.value.indexOf("c") >= 0) {
      traceArray(writer, "classes", this.classes);
    }
    if (filter.value.indexOf("i") >= 0) {
      traceArray(writer, "instances", this.instances);
    }
    if (filter.value.indexOf("M") >= 0) {
      traceArray(writer, "metadata", this.metadata);
    }
    if (filter.value.indexOf("s") >= 0) {
      traceArray(writer, "scripts", this.scripts);
    }
    if (filter.value.indexOf("m") >= 0) {
      traceArray(writer, "methods", this.methods, this);
    }
    if (filter.value.indexOf("S") >= 0) {
      traceSource(writer, this);
    }
    if (filter.value.indexOf("t") >= 0) {
      traceStatistics(writer, this);
    }
  };

  ConstantPool.prototype.trace = function (writer) {
    writer.enter("constantPool {");
    for (var key in this) {
      /* Special-case namespaces to print out full names. */
      if (key === "namespaces") {
        writer.enter("namespaces {");
        this.namespaces.forEach(function (ns, i) {
          writer.writeLn(("" + i).padRight(' ', 3) +
                   (ns ? ns.toString() : "*"));
        });
        writer.leave("}");
      } else if (this[key] instanceof Array) {
        writer.enter(key + " " + this[key].length + " {");
        writer.writeArray(this[key]);
        writer.leave("}");
      }
    }
    writer.leave("}");
  };

  function traceMultinamesOnly(constantPool: ConstantPool, writer) {
    writer.writeArray(constantPool.multinames, null, true);
  }

  ClassInfo.prototype.trace = function (writer) {
    writer.enter("class " + this + " {");
    traceArray(writer, "traits", this.traits);
    writer.leave("}");
  };

  MetaDataInfo.prototype.trace = function (writer) {
    writer.enter(this + " {");
    this.value.forEach(function (item) {
      writer.writeLn((item.key ? item.key + ": " : "") + "\"" + item.value + "\"");
    });
    writer.leave("}");
  };

  InstanceInfo.prototype.trace = function (writer) {
    writer.enter("instance " + this + " {");
    traceArray(writer, "traits", this.traits);
    writer.leave("}");
  };

  ScriptInfo.prototype.trace = function (writer) {
    writer.enter("script " + this + " {");
    traceArray(writer, "traits", this.traits);
    writer.leave("}");
  };

  Trait.prototype.trace = function (writer) {
    if (this.metadata) {
      for (var key in this.metadata) {
        if (this.metadata.hasOwnProperty(key)) {
          this.metadata[key].trace(writer);
        }
      }
    }
    writer.writeLn(this);
  };

  function traceAbc(writer, abc) {
    abc.trace(writer);
  }

  function traceOperand(operand, abc, code) {
    var value = 0;
    switch(operand.size) {
     case OpcodeSize.s08: value = code.readS8(); break;
     case OpcodeSize.u08: value = code.readU8(); break;
     case OpcodeSize.s16: value = code.readS16(); break;
     case OpcodeSize.s24: value = code.readS24(); break;
     case OpcodeSize.u30: value = code.readU30(); break;
     case OpcodeSize.u32: value = code.readU32(); break;
      default: release || assert(false); break;
    }
    var description = "";
    switch(operand.type) {
      case "": break;
      case "I": description = abc.constantPool.ints[value]; break;
      case "U": description = abc.constantPool.uints[value]; break;
      case "D": description = abc.constantPool.doubles[value]; break;
      case "S": description = abc.constantPool.strings[value]; break;
      case "N": description = abc.constantPool.namespaces[value]; break;
      case "CI": description = abc.classes[value]; break;
      case "M":
        return abc.constantPool.multinames[value];
      default: description = "?"; break;
    }
    return operand.name + ":" + value + (description === "" ? "" : " (" + description + ")");
  }

  function traceOperands(opcode, abc, code, rewind = false) {
    var old = code.position;
    var str = "";
    if (opcode.operands === null) {
      str = "null";
    } else {
      opcode.operands.forEach(function (op, i) {
        str += traceOperand(op, abc, code);
        if (i < opcode.operands.length - 1) {
          str += ", ";
        }
      });
    }
    if (rewind) {
      code.seek(old);
    }
    return str;
  }

  MethodInfo.prototype.trace = function trace(writer) {
    var abc = this.abc;
    writer.enter("method" + (this.name ? " " + this.name : "") + " {");
    writer.writeLn("flags: " + Shumway.IntegerUtilities.getFlags(this.flags, "NEED_ARGUMENTS|NEED_ACTIVATION|NEED_REST|HAS_OPTIONAL||NATIVE|SET_DXN|HAS_PARAM_NAMES".split("|")));
    writer.writeLn("parameters: " + this.parameters.map(function (x) {
      return (x.type ? Multiname.getQualifiedName(x.type) + "::" : "") + x.name;
    }));

    if (!this.code) {
      writer.leave("}");
      return;
    }

    var code = new AbcStream(this.code);

    traceArray(writer, "traits", this.traits);

    writer.enter("code {");
    while (code.remaining() > 0) {
      var bc = code.readU8();
      var opcode = Shumway.AVM2.opcodeTable[bc];
      var str, defaultOffset, offset, count;
      str = ("" + code.position).padRight(' ', 6);
      switch (bc) {
        case OP.lookupswitch:
          str += opcodeName(opcode) + ": defaultOffset: " + code.readS24();
          var caseCount = code.readU30();
          str += ", caseCount: " + caseCount;
          for (var i = 0; i < caseCount + 1; i++) {
            str += " offset: " + code.readS24();
          }
          writer.writeLn(str);
          break;
        default:
          if (opcode) {
            str += opcodeName(opcode).padRight(' ', 20);
            if (!opcode.operands) {
              release || assert(false, "Opcode: " + opcodeName(opcode) + " has undefined operands.");
            } else {
              if (opcode.operands.length > 0) {
                str += traceOperands(opcode, abc, code);
              }
              writer.writeLn(str);
            }
          } else {
            release || assert(false, "Opcode: " + bc + " is not implemented.");
          }
          break;
      }
    }
    writer.leave("}");
    writer.leave("}");<commit_msg>Fixes function tracing.<commit_after>/*
 * Copyright 2013 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
module Shumway.AVM2.ABC {
  import assert = Shumway.Debug.assert;
  import notImplemented = Shumway.Debug.notImplemented;

  var filter = new Shumway.Options.Option("f", "filter", "string", "SpciMsmNtu", "[S]ource, constant[p]ool, [c]lasses, [i]nstances, [M]etadata, [s]cripts, [m]ethods, multi[N]ames, S[t]atistics, [u]tf");

  function traceArray(writer, name, array, abc = null) {
    if (array.length === 0) {
      return;
    }
    writer.enter(name + " {");
    array.forEach(function (a, idx) {
      a.trace(writer, abc);
    });
    writer.leave("}");
  }

  AbcFile.prototype.trace = function trace(writer) {
    if (filter.value.indexOf("p") >= 0) {
      this.constantPool.trace(writer);
    }
    if (filter.value.indexOf("N") >= 0) {
      traceMultinamesOnly(this.constantPool, writer);
    }
    if (filter.value.indexOf("c") >= 0) {
      traceArray(writer, "classes", this.classes);
    }
    if (filter.value.indexOf("i") >= 0) {
      traceArray(writer, "instances", this.instances);
    }
    if (filter.value.indexOf("M") >= 0) {
      traceArray(writer, "metadata", this.metadata);
    }
    if (filter.value.indexOf("s") >= 0) {
      traceArray(writer, "scripts", this.scripts);
    }
    if (filter.value.indexOf("m") >= 0) {
      traceArray(writer, "methods", this.methods, this);
    }
    if (filter.value.indexOf("S") >= 0) {
      traceSource(writer, this);
    }
    if (filter.value.indexOf("t") >= 0) {
      traceStatistics(writer, this);
    }
  };

  ConstantPool.prototype.trace = function (writer) {
    writer.enter("constantPool {");
    for (var key in this) {
      /* Special-case namespaces to print out full names. */
      if (key === "namespaces") {
        writer.enter("namespaces {");
        this.namespaces.forEach(function (ns, i) {
          writer.writeLn(("" + i).padRight(' ', 3) +
                   (ns ? ns.toString() : "*"));
        });
        writer.leave("}");
      } else if (this[key] instanceof Array) {
        writer.enter(key + " " + this[key].length + " {");
        writer.writeArray(this[key]);
        writer.leave("}");
      }
    }
    writer.leave("}");
  };

  function traceMultinamesOnly(constantPool: ConstantPool, writer) {
    writer.writeArray(constantPool.multinames, null, true);
  }

  ClassInfo.prototype.trace = function (writer) {
    writer.enter("class " + this + " {");
    traceArray(writer, "traits", this.traits);
    writer.leave("}");
  };

  MetaDataInfo.prototype.trace = function (writer) {
    writer.enter(this + " {");
    this.value.forEach(function (item) {
      writer.writeLn((item.key ? item.key + ": " : "") + "\"" + item.value + "\"");
    });
    writer.leave("}");
  };

  InstanceInfo.prototype.trace = function (writer) {
    writer.enter("instance " + this + " {");
    traceArray(writer, "traits", this.traits);
    writer.leave("}");
  };

  ScriptInfo.prototype.trace = function (writer) {
    writer.enter("script " + this + " {");
    traceArray(writer, "traits", this.traits);
    writer.leave("}");
  };

  Trait.prototype.trace = function (writer) {
    if (this.metadata) {
      for (var key in this.metadata) {
        if (this.metadata.hasOwnProperty(key)) {
          this.metadata[key].trace(writer);
        }
      }
    }
    writer.writeLn(this);
  };

  function traceAbc(writer, abc) {
    abc.trace(writer);
  }

  function traceOperand(operand, abc, code) {
    var value = 0;
    switch(operand.size) {
     case OpcodeSize.s08: value = code.readS8(); break;
     case OpcodeSize.u08: value = code.readU8(); break;
     case OpcodeSize.s16: value = code.readS16(); break;
     case OpcodeSize.s24: value = code.readS24(); break;
     case OpcodeSize.u30: value = code.readU30(); break;
     case OpcodeSize.u32: value = code.readU32(); break;
      default: release || assert(false); break;
    }
    var description = "";
    switch(operand.type) {
      case "": break;
      case "I": description = abc.constantPool.ints[value]; break;
      case "U": description = abc.constantPool.uints[value]; break;
      case "D": description = abc.constantPool.doubles[value]; break;
      case "S": description = abc.constantPool.strings[value]; break;
      case "N": description = abc.constantPool.namespaces[value]; break;
      case "CI": description = abc.classes[value]; break;
      case "M":
        return abc.constantPool.multinames[value];
      default: description = "?"; break;
    }
    return operand.name + ":" + value + (description === "" ? "" : " (" + description + ")");
  }

  function traceOperands(opcode, abc, code, rewind = false) {
    var old = code.position;
    var str = "";
    if (opcode.operands === null) {
      str = "null";
    } else {
      opcode.operands.forEach(function (op, i) {
        str += traceOperand(op, abc, code);
        if (i < opcode.operands.length - 1) {
          str += ", ";
        }
      });
    }
    if (rewind) {
      code.seek(old);
    }
    return str;
  }

  MethodInfo.prototype.trace = function trace(writer) {
    var abc = this.abc;
    writer.enter("method" + (this.name ? " " + this.name : "") + " {");
    writer.writeLn("flags: " + Shumway.IntegerUtilities.getFlags(this.flags, "NEED_ARGUMENTS|NEED_ACTIVATION|NEED_REST|HAS_OPTIONAL||NATIVE|SET_DXN|HAS_PARAM_NAMES".split("|")));
    writer.writeLn("parameters: " + this.parameters.map(function (x) {
      return (x.type ? Multiname.getQualifiedName(x.type) + "::" : "") + x.name;
    }));

    if (!this.code) {
      writer.leave("}");
      return;
    }

    var code = new AbcStream(this.code);

    traceArray(writer, "traits", this.traits);

    writer.enter("code {");
    while (code.remaining() > 0) {
      var bc = code.readU8();
      var opcode = Shumway.AVM2.opcodeTable[bc];
      var str, defaultOffset, offset, count;
      str = ("" + code.position).padRight(' ', 6);
      switch (bc) {
        case OP.lookupswitch:
          str += opcodeName(bc) + ": defaultOffset: " + code.readS24();
          var caseCount = code.readU30();
          str += ", caseCount: " + caseCount;
          for (var i = 0; i < caseCount + 1; i++) {
            str += " offset: " + code.readS24();
          }
          writer.writeLn(str);
          break;
        default:
          if (opcode) {
            str += opcodeName(bc).padRight(' ', 20);
            if (!opcode.operands) {
              release || assert(false, "Opcode: " + opcodeName(bc) + " has undefined operands.");
            } else {
              if (opcode.operands.length > 0) {
                str += traceOperands(opcode, abc, code);
              }
              writer.writeLn(str);
            }
          } else {
            release || assert(false, "Opcode: " + bc + " is not implemented.");
          }
          break;
      }
    }
    writer.leave("}");
    writer.leave("}");
{'fraction_non_alphanumeric': 0.16539593365436062, 'fraction_numerical': 0.007891920813269128, 'mean_word_length': 2.584132310642378, 'pattern_counts': {'":': 24, '<': 7, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2618398', 'n_tokens_mistral': 4872, 'n_tokens_neox': 4790, 'n_words': 1025}