private IMethod makeUnaryObjectConstructor(IClass cls) {
    JSInstructionFactory insts =
        (JSInstructionFactory) cls.getClassLoader().getInstructionFactory();
    MethodReference ref = JavaScriptMethods.makeCtorReference(JavaScriptTypes.Object);
    JavaScriptSummary S = new JavaScriptSummary(ref, 2);

    S.addStatement(insts.ReturnInstruction(2, false));
    S.getNextProgramCounter();

    return new JavaScriptConstructor(ref, S, cls);
  }
  private IMethod makeNullaryNumberCall(IClass cls) {
    JSInstructionFactory insts =
        (JSInstructionFactory) cls.getClassLoader().getInstructionFactory();
    MethodReference ref = AstMethodReference.fnReference(JavaScriptTypes.Number);
    JavaScriptSummary S = new JavaScriptSummary(ref, 1);

    S.addConstant(new Integer(2), new ConstantValue(0.0));
    S.addStatement(insts.ReturnInstruction(2, false));
    S.getNextProgramCounter();

    return new JavaScriptConstructor(ref, S, cls);
  }
  private IMethod makeUnaryNumberCall(IClass cls) {
    JSInstructionFactory insts =
        (JSInstructionFactory) cls.getClassLoader().getInstructionFactory();
    MethodReference ref = AstMethodReference.fnReference(JavaScriptTypes.Number);
    JavaScriptSummary S = new JavaScriptSummary(ref, 2);

    S.addStatement(insts.GetInstruction(4, 2, "toNumber"));
    S.getNextProgramCounter();

    CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter());
    S.addStatement(insts.Invoke(4, 5, new int[] {2}, 6, cs));

    S.addStatement(insts.ReturnInstruction(5, false));
    S.getNextProgramCounter();

    return new JavaScriptConstructor(ref, S, cls);
  }
  private IMethod makeFunctionObjectConstructor(IClass cls, int nargs) {
    JSInstructionFactory insts =
        (JSInstructionFactory) cls.getClassLoader().getInstructionFactory();
    Object key = Pair.make(cls, new Integer(nargs));
    if (constructors.containsKey(key)) return constructors.get(key);

    MethodReference ref = JavaScriptMethods.makeCtorReference(cls.getReference());
    JavaScriptSummary S = new JavaScriptSummary(ref, nargs + 1);
    S.addStatement(insts.GetInstruction(nargs + 4, 1, "prototype"));
    S.getNextProgramCounter();

    S.addStatement(
        insts.NewInstruction(
            nargs + 5, NewSiteReference.make(S.getNextProgramCounter(), JavaScriptTypes.Object)));

    S.addStatement(insts.SetPrototype(nargs + 5, nargs + 4));
    // S.addStatement(insts.PutInstruction(nargs + 5, nargs + 4, "__proto__"));
    S.getNextProgramCounter();

    CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter());
    int[] args = new int[nargs + 1];
    args[0] = nargs + 5;
    for (int i = 0; i < nargs; i++) args[i + 1] = i + 2;
    S.addStatement(insts.Invoke(1, nargs + 7, args, nargs + 8, cs));

    S.addStatement(insts.ReturnInstruction(nargs + 7, false));
    S.getNextProgramCounter();

    S.addStatement(insts.ReturnInstruction(nargs + 5, false));
    S.getNextProgramCounter();

    // S.addConstant(nargs + 9, new ConstantValue("__proto__"));

    return record(key, new JavaScriptConstructor(ref, S, cls));
  }
  private IMethod makeNullaryValueConstructor(IClass cls, Object value) {
    JSInstructionFactory insts =
        (JSInstructionFactory) cls.getClassLoader().getInstructionFactory();
    MethodReference ref = JavaScriptMethods.makeCtorReference(cls.getReference());
    JavaScriptSummary S = new JavaScriptSummary(ref, 1);

    S.addStatement(insts.GetInstruction(4, 1, "prototype"));
    S.getNextProgramCounter();

    S.addStatement(
        insts.NewInstruction(
            5, NewSiteReference.make(S.getNextProgramCounter(), cls.getReference())));

    S.addStatement(insts.SetPrototype(5, 4));
    // S.addStatement(insts.PutInstruction(5, 4, "__proto__"));
    S.getNextProgramCounter();

    S.addConstant(new Integer(8), new ConstantValue(value));
    S.addStatement(insts.PutInstruction(5, 8, "$value"));
    S.getNextProgramCounter();

    S.addStatement(insts.ReturnInstruction(5, false));
    S.getNextProgramCounter();

    // S.addConstant(9, new ConstantValue("__proto__"));

    return new JavaScriptConstructor(ref, S, cls);
  }
  private IMethod makeArrayLengthConstructor(IClass cls) {
    JSInstructionFactory insts =
        (JSInstructionFactory) cls.getClassLoader().getInstructionFactory();
    MethodReference ref = JavaScriptMethods.makeCtorReference(JavaScriptTypes.Array);
    JavaScriptSummary S = new JavaScriptSummary(ref, 2);

    S.addStatement(insts.GetInstruction(5, 1, "prototype"));
    S.getNextProgramCounter();

    S.addStatement(
        insts.NewInstruction(
            6, NewSiteReference.make(S.getNextProgramCounter(), JavaScriptTypes.Array)));

    S.addStatement(insts.SetPrototype(6, 5));
    // S.addStatement(insts.PutInstruction(6, 5, "__proto__"));
    S.getNextProgramCounter();

    S.addStatement(insts.PutInstruction(6, 2, "length"));
    S.getNextProgramCounter();

    S.addStatement(insts.ReturnInstruction(6, false));
    S.getNextProgramCounter();

    // S.addConstant(7, new ConstantValue("__proto__"));

    return new JavaScriptConstructor(ref, S, cls);
  }
  private IMethod makeFunctionConstructor(IClass receiver, IClass cls) {
    JSInstructionFactory insts =
        (JSInstructionFactory) cls.getClassLoader().getInstructionFactory();
    Pair<IClass, IClass> tableKey = Pair.make(receiver, cls);
    if (constructors.containsKey(tableKey)) return constructors.get(tableKey);

    MethodReference ref = JavaScriptMethods.makeCtorReference(receiver.getReference());
    JavaScriptSummary S = new JavaScriptSummary(ref, 1);

    S.addStatement(insts.GetInstruction(4, 1, "prototype"));
    S.getNextProgramCounter();

    S.addStatement(
        insts.NewInstruction(
            5, NewSiteReference.make(S.getNextProgramCounter(), cls.getReference())));

    S.addStatement(
        insts.NewInstruction(
            7, NewSiteReference.make(S.getNextProgramCounter(), JavaScriptTypes.Object)));

    S.addStatement(insts.SetPrototype(5, 4));
    // S.addStatement(insts.PutInstruction(5, 4, "__proto__"));
    S.getNextProgramCounter();

    S.addStatement(insts.PutInstruction(5, 7, "prototype"));
    S.getNextProgramCounter();

    S.addStatement(insts.PutInstruction(7, 5, "constructor"));
    S.getNextProgramCounter();

    // TODO we need to set v7.__proto__ to Object.prototype
    S.addStatement(insts.ReturnInstruction(5, false));
    S.getNextProgramCounter();

    // S.addConstant(8, new ConstantValue("__proto__"));

    if (receiver != cls)
      return record(
          tableKey,
          new JavaScriptConstructor(ref, S, receiver, "(" + cls.getReference().getName() + ")"));
    else return record(tableKey, new JavaScriptConstructor(ref, S, receiver));
  }
  private IMethod makeArrayContentsConstructor(IClass cls, int nargs) {
    JSInstructionFactory insts =
        (JSInstructionFactory) cls.getClassLoader().getInstructionFactory();
    MethodReference ref = JavaScriptMethods.makeCtorReference(JavaScriptTypes.Array);
    JavaScriptSummary S = new JavaScriptSummary(ref, nargs + 1);

    S.addConstant(new Integer(nargs + 3), new ConstantValue("prototype"));
    S.addStatement(insts.PropertyRead(nargs + 4, 1, nargs + 3));
    S.getNextProgramCounter();

    S.addStatement(
        insts.NewInstruction(
            nargs + 5, NewSiteReference.make(S.getNextProgramCounter(), JavaScriptTypes.Array)));

    S.addStatement(insts.SetPrototype(nargs + 5, nargs + 4));
    // S.addStatement(insts.PutInstruction(nargs + 5, nargs + 4, "__proto__"));
    S.getNextProgramCounter();

    S.addConstant(new Integer(nargs + 7), new ConstantValue(nargs));
    S.addStatement(insts.PutInstruction(nargs + 5, nargs + 7, "length"));
    S.getNextProgramCounter();

    int vn = nargs + 9;
    for (int i = 0; i < nargs; i++, vn += 2) {
      S.addConstant(new Integer(vn), new ConstantValue(i));
      S.addStatement(insts.PropertyWrite(nargs + 5, vn, i + 1));
      S.getNextProgramCounter();
    }

    S.addStatement(insts.ReturnInstruction(5, false));
    S.getNextProgramCounter();

    // S.addConstant(vn, new ConstantValue("__proto__"));

    return new JavaScriptConstructor(ref, S, cls);
  }