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

Diff of /trunk/instrument-js.cpp

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

revision 459 by siliconforks, Mon Sep 7 21:18:00 2009 UTC revision 460 by siliconforks, Sat Sep 26 23:15:22 2009 UTC
# Line 26  Line 26 
26  #include <stdlib.h>  #include <stdlib.h>
27  #include <string.h>  #include <string.h>
28    
29    // needed by jsparse.h
30    #include <jsbit.h>
31    #include <jscntxt.h>
32    #include <jsscript.h>
33    
34  #include <jsapi.h>  #include <jsapi.h>
35  #include <jsarena.h>  #include <jsarena.h>
36  #include <jsatom.h>  #include <jsatom.h>
# Line 349  Line 354 
354  static void instrument_function(JSParseNode * node, Stream * f, int indent, enum FunctionType type) {  static void instrument_function(JSParseNode * node, Stream * f, int indent, enum FunctionType type) {
355    assert(node->pn_type == TOK_FUNCTION);    assert(node->pn_type == TOK_FUNCTION);
356    assert(node->pn_arity == PN_FUNC);    assert(node->pn_arity == PN_FUNC);
357    JSObject * object = node->pn_funpob->object;    JSObject * object = node->pn_funbox->object;
358    assert(JS_ObjectIsFunction(context, object));    assert(JS_ObjectIsFunction(context, object));
359    JSFunction * function = (JSFunction *) JS_GetPrivate(context, object);    JSFunction * function = (JSFunction *) JS_GetPrivate(context, object);
360    assert(function);    assert(function);
# Line 372  Line 377 
377    JSArenaPool pool;    JSArenaPool pool;
378    JS_INIT_ARENA_POOL(&pool, "instrument_function", 256, 1, &context->scriptStackQuota);    JS_INIT_ARENA_POOL(&pool, "instrument_function", 256, 1, &context->scriptStackQuota);
379    jsuword * local_names = NULL;    jsuword * local_names = NULL;
380    if (JS_GET_LOCAL_NAME_COUNT(function)) {    if (function->hasLocalNames()) {
381      local_names = js_GetLocalNameArray(context, function, &pool);      local_names = js_GetLocalNameArray(context, function, &pool);
382      if (local_names == NULL) {      if (local_names == NULL) {
383        fatal("out of memory");        fatal("out of memory");
# Line 386  Line 391 
391      JSAtom * param = JS_LOCAL_NAME_TO_ATOM(local_names[i]);      JSAtom * param = JS_LOCAL_NAME_TO_ATOM(local_names[i]);
392      if (param == NULL) {      if (param == NULL) {
393        destructuring = true;        destructuring = true;
394    
395          JSParseNode * p = node->pn_body;
396          if (p->pn_type == TOK_UPVARS) {
397            assert(p->pn_arity == PN_NAMESET);
398            p = p->pn_tree;
399          }
400    
401          if (p->pn_type == TOK_ARGSBODY) {
402            assert(p->pn_arity == PN_LIST);
403            // the function body is the final element of the list
404            for (p = p->pn_head; p->pn_next != NULL; p = p->pn_next) {
405              ;
406            }
407          }
408    
409        JSParseNode * expression = NULL;        JSParseNode * expression = NULL;
410        assert(node->pn_body->pn_type == TOK_LC || node->pn_body->pn_type == TOK_SEQ);        assert(p->pn_type == TOK_LC || p->pn_type == TOK_SEQ);
411        JSParseNode * semi = node->pn_body->pn_head;        assert(p->pn_arity == PN_LIST);
412          JSParseNode * semi = p->pn_head;
413        assert(semi->pn_type == TOK_SEMI);        assert(semi->pn_type == TOK_SEMI);
414        JSParseNode * comma = semi->pn_kid;        JSParseNode * comma = semi->pn_kid;
415        assert(comma->pn_type == TOK_COMMA);        assert(comma->pn_type == TOK_COMMA);
# Line 396  Line 417 
417          assert(p->pn_type == TOK_ASSIGN);          assert(p->pn_type == TOK_ASSIGN);
418          JSParseNode * rhs = p->pn_right;          JSParseNode * rhs = p->pn_right;
419          assert(JSSTRING_LENGTH(ATOM_TO_STRING(rhs->pn_atom)) == 0);          assert(JSSTRING_LENGTH(ATOM_TO_STRING(rhs->pn_atom)) == 0);
420          if (rhs->pn_slot == i) {          if (UPVAR_FRAME_SLOT(rhs->pn_cookie) == i) {
421            expression = p->pn_left;            expression = p->pn_left;
422            break;            break;
423          }          }
# Line 412  Line 433 
433    Stream_write_string(f, ") {\n");    Stream_write_string(f, ") {\n");
434    
435    /* function body */    /* function body */
436    
437      JSParseNode * p = node->pn_body;
438      if (p->pn_type == TOK_UPVARS) {
439        assert(p->pn_arity == PN_NAMESET);
440        p = p->pn_tree;
441      }
442    
443      if (p->pn_type == TOK_ARGSBODY) {
444        assert(p->pn_arity == PN_LIST);
445        // the function body is the final element of the list
446        for (p = p->pn_head; p->pn_next != NULL; p = p->pn_next) {
447          ;
448        }
449      }
450    
451    if (function->flags & JSFUN_EXPR_CLOSURE) {    if (function->flags & JSFUN_EXPR_CLOSURE) {
452      /* expression closure - use output_statement instead of instrument_statement */      /* expression closure - use output_statement instead of instrument_statement */
453      if (node->pn_body->pn_type == TOK_SEQ) {      if (p->pn_type == TOK_SEQ) {
454        assert(node->pn_body->pn_arity == PN_LIST);        assert(p->pn_arity == PN_LIST);
455        assert(node->pn_body->pn_count == 2);        assert(p->pn_count == 2);
456        output_statement(node->pn_body->pn_head->pn_next, f, indent + 2, false);        output_statement(p->pn_head->pn_next, f, indent + 2, false);
457      }      }
458      else {      else {
459        output_statement(node->pn_body, f, indent + 2, false);        output_statement(p, f, indent + 2, false);
460      }      }
461    }    }
462    else {    else {
463      assert(node->pn_body->pn_type == TOK_LC);      assert(p->pn_type == TOK_LC);
464      assert(node->pn_body->pn_arity == PN_LIST);      assert(p->pn_arity == PN_LIST);
465      JSParseNode * p = node->pn_body->pn_head;      p = p->pn_head;
466      if (destructuring) {      if (destructuring) {
467        p = p->pn_next;        p = p->pn_next;
468      }      }
# Line 453  Line 489 
489  static void instrument_function_call(JSParseNode * node, Stream * f) {  static void instrument_function_call(JSParseNode * node, Stream * f) {
490    JSParseNode * function_node = node->pn_head;    JSParseNode * function_node = node->pn_head;
491    if (function_node->pn_type == TOK_FUNCTION) {    if (function_node->pn_type == TOK_FUNCTION) {
492      JSObject * object = function_node->pn_funpob->object;      JSObject * object = function_node->pn_funbox->object;
493      assert(JS_ObjectIsFunction(context, object));      assert(JS_ObjectIsFunction(context, object));
494      JSFunction * function = (JSFunction *) JS_GetPrivate(context, object);      JSFunction * function = (JSFunction *) JS_GetPrivate(context, object);
495      assert(function);      assert(function);
496      assert(object == &function->object);      assert(object == &function->object);
497    
498      if (function_node->pn_flags & TCF_GENEXP_LAMBDA) {      if (function_node->pn_funbox->tcflags & TCF_GENEXP_LAMBDA) {
499        /* it's a generator expression */        /* it's a generator expression */
500        Stream_write_char(f, '(');        Stream_write_char(f, '(');
501        output_array_comprehension_or_generator_expression(function_node->pn_body, f);        JSParseNode * p = function_node->pn_body;
502          if (p->pn_type == TOK_UPVARS) {
503            assert(p->pn_arity == PN_NAMESET);
504            p = p->pn_tree;
505          }
506          output_array_comprehension_or_generator_expression(p, f);
507        Stream_write_char(f, ')');        Stream_write_char(f, ')');
508        return;        return;
509      }      }
# Line 477  Line 518 
518      if (p != list->pn_head) {      if (p != list->pn_head) {
519        Stream_write_string(f, ", ");        Stream_write_string(f, ", ");
520      }      }
521      output_expression(p, f, false);  
522        switch (p->pn_type) {
523        case TOK_NAME:
524          print_string_atom(p->pn_atom, f);
525          if (p->pn_expr != NULL) {
526            Stream_write_string(f, " = ");
527            output_expression(p->pn_expr, f, false);
528          }
529          break;
530        default:
531          output_expression(p, f, false);
532          break;
533        }
534    }    }
535  }  }
536    
# Line 728  Line 781 
781          output_expression(p, f, false);          output_expression(p, f, false);
782        }        }
783      }      }
784      if (node->pn_extra == PNX_ENDCOMMA) {      if (node->pn_xflags & PNX_ENDCOMMA) {
785        Stream_write_char(f, ',');        Stream_write_char(f, ',');
786      }      }
787      Stream_write_char(f, ']');      Stream_write_char(f, ']');
# Line 782  Line 835 
835      break;      break;
836    case TOK_NAME:    case TOK_NAME:
837      print_string_atom(node->pn_atom, f);      print_string_atom(node->pn_atom, f);
     if (node->pn_expr != NULL) {  
       Stream_write_string(f, " = ");  
       output_expression(node->pn_expr, f, false);  
     }  
838      break;      break;
839    case TOK_STRING:    case TOK_STRING:
840      print_quoted_string_atom(node->pn_atom, f);      print_quoted_string_atom(node->pn_atom, f);
# Line 793  Line 842 
842    case TOK_REGEXP:    case TOK_REGEXP:
843      assert(node->pn_op == JSOP_REGEXP);      assert(node->pn_op == JSOP_REGEXP);
844      {      {
845        JSObject * object = node->pn_pob->object;        JSObject * object = node->pn_objbox->object;
846        jsval result;        jsval result;
847        js_regexp_toString(context, object, &result);        js_regexp_toString(context, object, &result);
848        print_regex(result, f);        print_regex(result, f);
# Line 1249  Line 1298 
1298        instrument_statement(p, f, indent, false);        instrument_statement(p, f, indent, false);
1299      }      }
1300      break;      break;
1301      case TOK_NAME:
1302        // this is a duplicate function
1303        JSParseNode function_node;
1304        function_node.pn_type = TOK_FUNCTION;
1305        function_node.pn_arity = PN_FUNC;
1306        function_node.pn_funbox = node->pn_u.name.funbox2;
1307        function_node.pn_expr = node->pn_u.name.expr2;
1308        instrument_function(&function_node, f, indent, FUNCTION_NORMAL);
1309        Stream_write_char(f, '\n');
1310        break;
1311    default:    default:
1312      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);
1313    }    }
# Line 1318  Line 1377 
1377    file_id = id;    file_id = id;
1378    
1379    /* parse the javascript */    /* parse the javascript */
1380    JSParseContext parse_context;    JSCompiler compiler(context);
1381    if (! js_InitParseContext(context, &parse_context, NULL, NULL, characters, num_characters, NULL, NULL, 1)) {    if (! compiler.init(characters, num_characters, NULL, id, 1)) {
1382      fatal("cannot create token stream from file %s", file_id);      fatal("cannot create token stream from file %s", file_id);
1383    }    }
1384    JSErrorReporter old_error_reporter = JS_SetErrorReporter(context, error_reporter);    JSErrorReporter old_error_reporter = JS_SetErrorReporter(context, error_reporter);
1385    JSParseNode * node = js_ParseScript(context, global, &parse_context);    JSParseNode * node = compiler.parse(global);
1386    if (node == NULL) {    if (node == NULL) {
1387      js_ReportUncaughtException(context);      js_ReportUncaughtException(context);
1388      fatal("parse error in file %s", file_id);      fatal("parse error in file %s", file_id);
# Line 1410  Line 1469 
1469    
1470    Stream * instrumented = Stream_new(0);    Stream * instrumented = Stream_new(0);
1471    instrument_statement(node, instrumented, 0, false);    instrument_statement(node, instrumented, 0, false);
   js_FinishParseContext(context, &parse_context);  
1472    
1473    /* write line number info to the output */    /* write line number info to the output */
1474    Stream_write_string(output, JSCOVERAGE_INSTRUMENTED_HEADER);    Stream_write_string(output, JSCOVERAGE_INSTRUMENTED_HEADER);
# Line 1714  Line 1772 
1772    
1773    JS_free(context, base);    JS_free(context, base);
1774    
1775    JSParseContext parse_context;    JSCompiler compiler(context);
1776    if (! js_InitParseContext(context, &parse_context, NULL, NULL, parenthesized_json, length + 2, NULL, NULL, 1)) {    if (! compiler.init(parenthesized_json, length + 2, NULL, NULL, 1)) {
1777      free(parenthesized_json);      free(parenthesized_json);
1778      return -1;      return -1;
1779    }    }
1780    JSParseNode * root = js_ParseScript(context, global, &parse_context);    JSParseNode * root = compiler.parse(global);
1781    free(parenthesized_json);    free(parenthesized_json);
1782    
1783    JSParseNode * semi = NULL;    JSParseNode * semi = NULL;
# Line 1908  Line 1966 
1966    }    }
1967    
1968  done:  done:
   js_FinishParseContext(context, &parse_context);  
1969    return result;    return result;
1970  }  }

Legend:
Removed from v.459  
changed lines
  Added in v.460

  ViewVC Help
Powered by ViewVC 1.1.24