/[jscoverage]/trunk/instrument-js.cpp
ViewVC logotype

Diff of /trunk/instrument-js.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/instrument-js.c revision 390 by siliconforks, Thu Oct 30 17:53:39 2008 UTC trunk/instrument-js.cpp revision 427 by siliconforks, Wed Feb 18 16:08:33 2009 UTC
# Line 1  Line 1 
1  /*  /*
2      instrument-js.c - JavaScript instrumentation routines      instrument-js.cpp - JavaScript instrumentation routines
3      Copyright (C) 2007, 2008 siliconforks.com      Copyright (C) 2007, 2008, 2009 siliconforks.com
4    
5      This program is free software; you can redistribute it and/or modify      This program is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published by      it under the terms of the GNU General Public License as published by
# Line 305  Line 305 
305      assert(if_node->pn_arity == PN_TERNARY);      assert(if_node->pn_arity == PN_TERNARY);
306      p = if_node->pn_kid2;      p = if_node->pn_kid2;
307    }    }
308    assert(p->pn_arity == PN_UNARY);    switch (p->pn_arity) {
309    p = p->pn_kid;    case PN_UNARY:
   if (p->pn_type == TOK_YIELD) {  
     /* for generator expressions */  
310      p = p->pn_kid;      p = p->pn_kid;
311        if (p->pn_type == TOK_YIELD) {
312          /* for generator expressions */
313          p = p->pn_kid;
314        }
315        output_expression(p, f, false);
316        break;
317      case PN_LIST:
318        /*
319        When the array comprehension contains "if (0)", it will be optimized away and
320        the result will be an empty TOK_LC list.
321        */
322        assert(p->pn_type == TOK_LC);
323        assert(p->pn_head == NULL);
324        /* the "1" is arbitrary (since the list is empty) */
325        Stream_write_char(f, '1');
326        break;
327      default:
328        abort();
329        break;
330    }    }
331    
   output_expression(p, f, false);  
332    p = for_node;    p = for_node;
333    while (p->pn_type == TOK_FOR) {    while (p->pn_type == TOK_FOR) {
334      Stream_write_char(f, ' ');      Stream_write_char(f, ' ');
335      output_for_in(p, f);      output_for_in(p, f);
336      p = p->pn_right;      p = p->pn_right;
337    }    }
338    if (if_node) {    if (p->pn_type == TOK_LC) {
339        /* this is the optimized-away "if (0)" */
340        Stream_write_string(f, " if (0)");
341      }
342      else if (if_node) {
343      Stream_write_string(f, " if (");      Stream_write_string(f, " if (");
344      output_expression(if_node->pn_kid1, f, false);      output_expression(if_node->pn_kid1, f, false);
345      Stream_write_char(f, ')');      Stream_write_char(f, ')');
# Line 367  Line 387 
387      if (param == NULL) {      if (param == NULL) {
388        destructuring = true;        destructuring = true;
389        JSParseNode * expression = NULL;        JSParseNode * expression = NULL;
390        assert(node->pn_body->pn_type == TOK_LC || node->pn_body->pn_type == TOK_BODY);        assert(node->pn_body->pn_type == TOK_LC || node->pn_body->pn_type == TOK_SEQ);
391        JSParseNode * semi = node->pn_body->pn_head;        JSParseNode * semi = node->pn_body->pn_head;
392        assert(semi->pn_type == TOK_SEMI);        assert(semi->pn_type == TOK_SEMI);
393        JSParseNode * comma = semi->pn_kid;        JSParseNode * comma = semi->pn_kid;
# Line 394  Line 414 
414    /* function body */    /* function body */
415    if (function->flags & JSFUN_EXPR_CLOSURE) {    if (function->flags & JSFUN_EXPR_CLOSURE) {
416      /* expression closure - use output_statement instead of instrument_statement */      /* expression closure - use output_statement instead of instrument_statement */
417      if (node->pn_body->pn_type == TOK_BODY) {      if (node->pn_body->pn_type == TOK_SEQ) {
418        assert(node->pn_body->pn_arity == PN_LIST);        assert(node->pn_body->pn_arity == PN_LIST);
419        assert(node->pn_body->pn_count == 2);        assert(node->pn_body->pn_count == 2);
420        output_statement(node->pn_body->pn_head->pn_next, f, indent + 2, false);        output_statement(node->pn_body->pn_head->pn_next, f, indent + 2, false);
# Line 715  Line 735 
735            Stream_write_string(f, "set ");            Stream_write_string(f, "set ");
736          }          }
737          output_expression(p->pn_left, f, false);          output_expression(p->pn_left, f, false);
738            Stream_write_char(f, ' ');
739          if (p->pn_right->pn_type != TOK_FUNCTION) {          if (p->pn_right->pn_type != TOK_FUNCTION) {
740            fatal_source(file_id, p->pn_pos.begin.lineno, "expected function");            fatal_source(file_id, p->pn_pos.begin.lineno, "expected function");
741          }          }
# Line 777  Line 798 
798      else if (node->pn_dval == -INFINITY) {      else if (node->pn_dval == -INFINITY) {
799        Stream_write_string(f, "Number.NEGATIVE_INFINITY");        Stream_write_string(f, "Number.NEGATIVE_INFINITY");
800      }      }
801      else if (node->pn_dval == NAN) {      else if (isnan(node->pn_dval)) {
802        Stream_write_string(f, "Number.NaN");        Stream_write_string(f, "Number.NaN");
803      }      }
804      else {      else {
# Line 1000  Line 1021 
1021        assert(node->pn_left->pn_arity == PN_BINARY);        assert(node->pn_left->pn_arity == PN_BINARY);
1022        output_for_in(node, f);        output_for_in(node, f);
1023        break;        break;
1024      case TOK_RESERVED:      case TOK_FORHEAD:
1025        /* for (;;) */        /* for (;;) */
1026        assert(node->pn_left->pn_arity == PN_TERNARY);        assert(node->pn_left->pn_arity == PN_TERNARY);
1027        Stream_write_string(f, "for (");        Stream_write_string(f, "for (");
# Line 1044  Line 1065 
1065        assert(node->pn_kid2->pn_type == TOK_RESERVED);        assert(node->pn_kid2->pn_type == TOK_RESERVED);
1066        for (JSParseNode * scope = node->pn_kid2->pn_head; scope != NULL; scope = scope->pn_next) {        for (JSParseNode * scope = node->pn_kid2->pn_head; scope != NULL; scope = scope->pn_next) {
1067          assert(scope->pn_type == TOK_LEXICALSCOPE);          assert(scope->pn_type == TOK_LEXICALSCOPE);
1068          JSParseNode * catch = scope->pn_expr;          JSParseNode * catch_node = scope->pn_expr;
1069          assert(catch->pn_type == TOK_CATCH);          assert(catch_node->pn_type == TOK_CATCH);
1070          Stream_printf(f, "%*s", indent, "");          Stream_printf(f, "%*s", indent, "");
1071          Stream_write_string(f, "catch (");          Stream_write_string(f, "catch (");
1072          output_expression(catch->pn_kid1, f, false);          output_expression(catch_node->pn_kid1, f, false);
1073          if (catch->pn_kid2) {          if (catch_node->pn_kid2) {
1074            Stream_write_string(f, " if ");            Stream_write_string(f, " if ");
1075            output_expression(catch->pn_kid2, f, false);            output_expression(catch_node->pn_kid2, f, false);
1076          }          }
1077          Stream_write_string(f, ") {\n");          Stream_write_string(f, ") {\n");
1078          instrument_statement(catch->pn_kid3, f, indent + 2, false);          instrument_statement(catch_node->pn_kid3, f, indent + 2, false);
1079          Stream_printf(f, "%*s", indent, "");          Stream_printf(f, "%*s", indent, "");
1080          Stream_write_string(f, "}\n");          Stream_write_string(f, "}\n");
1081        }        }
# Line 1075  Line 1096 
1096      assert(node->pn_arity == PN_NAME || node->pn_arity == PN_NULLARY);      assert(node->pn_arity == PN_NAME || node->pn_arity == PN_NULLARY);
1097      Stream_printf(f, "%*s", indent, "");      Stream_printf(f, "%*s", indent, "");
1098      Stream_write_string(f, node->pn_type == TOK_BREAK? "break": "continue");      Stream_write_string(f, node->pn_type == TOK_BREAK? "break": "continue");
1099      JSAtom * atom = node->pn_u.name.atom;      if (node->pn_atom != NULL) {
     if (atom != NULL) {  
1100        Stream_write_char(f, ' ');        Stream_write_char(f, ' ');
1101        print_string_atom(node->pn_atom, f);        print_string_atom(node->pn_atom, f);
1102      }      }
# Line 1197  Line 1217 
1217      Stream_printf(f, "%*s", indent, "");      Stream_printf(f, "%*s", indent, "");
1218      Stream_write_string(f, "debugger;\n");      Stream_write_string(f, "debugger;\n");
1219      break;      break;
1220      case TOK_SEQ:
1221        /*
1222        This occurs with the statement:
1223        for (var a = b in c) {}
1224        */
1225        assert(node->pn_arity == PN_LIST);
1226        for (JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) {
1227          instrument_statement(p, f, indent, false);
1228        }
1229        break;
1230    default:    default:
1231      fatal_source(file_id, node->pn_pos.begin.lineno, "unsupported node type (%d)", node->pn_type);      fatal_source(file_id, node->pn_pos.begin.lineno, "unsupported node type (%d)", node->pn_type);
1232    }    }
# Line 1278  Line 1308 
1308    }    }
1309    JS_SetErrorReporter(context, old_error_reporter);    JS_SetErrorReporter(context, old_error_reporter);
1310    num_lines = node->pn_pos.end.lineno;    num_lines = node->pn_pos.end.lineno;
1311    lines = xmalloc(num_lines);    lines = (char *) xmalloc(num_lines);
1312    for (unsigned int i = 0; i < num_lines; i++) {    for (unsigned int i = 0; i < num_lines; i++) {
1313      lines[i] = 0;      lines[i] = 0;
1314    }    }
# Line 1591  Line 1621 
1621  };  };
1622    
1623  static int compare_strings(const void * p1, const void * p2) {  static int compare_strings(const void * p1, const void * p2) {
1624    return strcmp(p1, p2) == 0;    return strcmp((const char *) p1, (const char *) p2) == 0;
1625  }  }
1626    
1627  Coverage * Coverage_new(void) {  Coverage * Coverage_new(void) {
1628    Coverage * result = xmalloc(sizeof(Coverage));    Coverage * result = (Coverage *) xmalloc(sizeof(Coverage));
1629    result->coverage_table = JS_NewHashTable(1024, JS_HashString, compare_strings, NULL, NULL, NULL);    result->coverage_table = JS_NewHashTable(1024, JS_HashString, compare_strings, NULL, NULL, NULL);
1630    if (result->coverage_table == NULL) {    if (result->coverage_table == NULL) {
1631      fatal("cannot create hash table");      fatal("cannot create hash table");
# Line 1630  Line 1660 
1660  };  };
1661    
1662  static intN enumerator(JSHashEntry * entry, intN i, void * arg) {  static intN enumerator(JSHashEntry * entry, intN i, void * arg) {
1663    struct EnumeratorArg * enumerator_arg = arg;    struct EnumeratorArg * enumerator_arg = (struct EnumeratorArg *) arg;
1664    enumerator_arg->f(entry->value, i, enumerator_arg->p);    enumerator_arg->f((FileCoverage *) entry->value, i, enumerator_arg->p);
1665    return 0;    return 0;
1666  }  }
1667    
# Line 1664  Line 1694 
1694    }    }
1695    JSParseNode * root = js_ParseScript(context, global, &parse_context);    JSParseNode * root = js_ParseScript(context, global, &parse_context);
1696    free(parenthesized_json);    free(parenthesized_json);
1697    
1698      JSParseNode * semi = NULL;
1699      JSParseNode * object = NULL;
1700    
1701    if (root == NULL) {    if (root == NULL) {
1702      result = -1;      result = -1;
1703      goto done;      goto done;
# Line 1674  Line 1708 
1708      result = -1;      result = -1;
1709      goto done;      goto done;
1710    }    }
1711    JSParseNode * semi = root->pn_u.list.head;    semi = root->pn_u.list.head;
1712    
1713    /* the list must be TOK_SEMI and it must contain only one element */    /* the list must be TOK_SEMI and it must contain only one element */
1714    if (semi->pn_type != TOK_SEMI || semi->pn_next != NULL) {    if (semi->pn_type != TOK_SEMI || semi->pn_next != NULL) {
1715      result = -1;      result = -1;
1716      goto done;      goto done;
1717    }    }
1718    JSParseNode * parenthesized = semi->pn_kid;    object = semi->pn_kid;
   
   /* this must be a parenthesized expression */  
   if (parenthesized->pn_type != TOK_RP) {  
     result = -1;  
     goto done;  
   }  
   JSParseNode * object = parenthesized->pn_kid;  
1719    
1720    /* this must be an object literal */    /* this must be an object literal */
1721    if (object->pn_type != TOK_RC) {    if (object->pn_type != TOK_RC) {
# Line 1772  Line 1799 
1799      }      }
1800    
1801      /* look up the file in the coverage table */      /* look up the file in the coverage table */
1802      FileCoverage * file_coverage = JS_HashTableLookup(coverage->coverage_table, id_bytes);      FileCoverage * file_coverage = (FileCoverage *) JS_HashTableLookup(coverage->coverage_table, id_bytes);
1803      if (file_coverage == NULL) {      if (file_coverage == NULL) {
1804        /* not there: create a new one */        /* not there: create a new one */
1805        char * id = xstrdup(id_bytes);        char * id = xstrdup(id_bytes);
1806        file_coverage = xmalloc(sizeof(FileCoverage));        file_coverage = (FileCoverage *) xmalloc(sizeof(FileCoverage));
1807        file_coverage->id = id;        file_coverage->id = id;
1808        file_coverage->num_coverage_lines = array->pn_count;        file_coverage->num_coverage_lines = array->pn_count;
1809        file_coverage->coverage_lines = xnew(int, array->pn_count);        file_coverage->coverage_lines = xnew(int, array->pn_count);
# Line 1800  Line 1827 
1827    
1828        /* add to the hash table */        /* add to the hash table */
1829        JS_HashTableAdd(coverage->coverage_table, id, file_coverage);        JS_HashTableAdd(coverage->coverage_table, id, file_coverage);
1830        struct FileCoverageList * coverage_list = xmalloc(sizeof(struct FileCoverageList));        struct FileCoverageList * coverage_list = (FileCoverageList *) xmalloc(sizeof(struct FileCoverageList));
1831        coverage_list->file_coverage = file_coverage;        coverage_list->file_coverage = file_coverage;
1832        coverage_list->next = coverage->coverage_list;        coverage_list->next = coverage->coverage_list;
1833        coverage->coverage_list = coverage_list;        coverage->coverage_list = coverage_list;

Legend:
Removed from v.390  
changed lines
  Added in v.427

  ViewVC Help
Powered by ViewVC 1.1.24