Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(105)

Side by Side Diff: Python/compile.c

Issue 20103: http://bugs.python.org/issue2459 -- speed up loops SVN Base: http://svn.python.org/view/*checkout*/python/trunk/
Patch Set: Created 9 months, 1 week ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file compiles an abstract syntax tree (AST) into Python bytecode. 2 * This file compiles an abstract syntax tree (AST) into Python bytecode.
3 * 3 *
4 * The primary entry point is PyAST_Compile(), which returns a 4 * The primary entry point is PyAST_Compile(), which returns a
5 * PyCodeObject. The compiler makes several passes to build the code 5 * PyCodeObject. The compiler makes several passes to build the code
6 * object: 6 * object:
7 * 1. Checks for future statements. See future.c 7 * 1. Checks for future statements. See future.c
8 * 2. Builds a symbol table. See symtable.c. 8 * 2. Builds a symbol table. See symtable.c.
9 * 3. Generate code for basic blocks. See compiler_mod() in this file. 9 * 3. Generate code for basic blocks. See compiler_mod() in this file.
10 * 4. Assemble the basic blocks into final code. See assemble() in 10 * 4. Assemble the basic blocks into final code. See assemble() in
(...skipping 1587 matching lines...) Expand 10 before | Expand all | Expand 10 after
1598 assert(s->kind == If_kind); 1598 assert(s->kind == If_kind);
1599 end = compiler_new_block(c); 1599 end = compiler_new_block(c);
1600 if (end == NULL) 1600 if (end == NULL)
1601 return 0; 1601 return 0;
1602 1602
1603 constant = expr_constant(s->v.If.test); 1603 constant = expr_constant(s->v.If.test);
1604 /* constant = 0: "if 0" 1604 /* constant = 0: "if 0"
1605 * constant = 1: "if 1", "if 2", ... 1605 * constant = 1: "if 1", "if 2", ...
1606 * constant = -1: rest */ 1606 * constant = -1: rest */
1607 if (constant == 0) { 1607 if (constant == 0) {
1608 » » if (s->v.If.orelse) 1608 » » if (asdl_seq_LEN(s->v.If.orelse))
1609 VISIT_SEQ(c, stmt, s->v.If.orelse); 1609 VISIT_SEQ(c, stmt, s->v.If.orelse);
1610 } else if (constant == 1) { 1610 } else if (constant == 1) {
1611 VISIT_SEQ(c, stmt, s->v.If.body); 1611 VISIT_SEQ(c, stmt, s->v.If.body);
1612 } else { 1612 } else {
1613 » » if (s->v.If.orelse) { 1613 » » if (asdl_seq_LEN(s->v.If.orelse)) {
1614 next = compiler_new_block(c); 1614 next = compiler_new_block(c);
1615 if (next == NULL) 1615 if (next == NULL)
1616 return 0; 1616 return 0;
1617 } 1617 }
1618 else 1618 else
1619 next = end; 1619 next = end;
1620 VISIT(c, expr, s->v.If.test); 1620 VISIT(c, expr, s->v.If.test);
1621 ADDOP_JABS(c, POP_JUMP_IF_FALSE, next); 1621 ADDOP_JABS(c, POP_JUMP_IF_FALSE, next);
1622 VISIT_SEQ(c, stmt, s->v.If.body); 1622 VISIT_SEQ(c, stmt, s->v.If.body);
1623 » » ADDOP_JREL(c, JUMP_FORWARD, end); 1623 » » if (asdl_seq_LEN(s->v.If.orelse)) {
1624 » » if (s->v.If.orelse) { 1624 » » » ADDOP_JREL(c, JUMP_FORWARD, end);
1625 compiler_use_next_block(c, next); 1625 compiler_use_next_block(c, next);
1626 VISIT_SEQ(c, stmt, s->v.If.orelse); 1626 VISIT_SEQ(c, stmt, s->v.If.orelse);
1627 } 1627 }
1628 } 1628 }
1629 compiler_use_next_block(c, end); 1629 compiler_use_next_block(c, end);
1630 return 1; 1630 return 1;
1631 } 1631 }
1632 1632
1633 static int 1633 static int
1634 compiler_for(struct compiler *c, stmt_ty s) 1634 compiler_for(struct compiler *c, stmt_ty s)
1635 { 1635 {
1636 » basicblock *start, *cleanup, *end; 1636 » basicblock *start, *body, *tail, *cleanup, *end;
1637 » int for_lineno;
1637 1638
1638 start = compiler_new_block(c); 1639 start = compiler_new_block(c);
1640 body = compiler_new_block(c);
1641 tail = compiler_new_block(c);
1639 cleanup = compiler_new_block(c); 1642 cleanup = compiler_new_block(c);
1640 end = compiler_new_block(c); 1643 end = compiler_new_block(c);
1641 » if (start == NULL || end == NULL || cleanup == NULL) 1644 » if (start == NULL || body == NULL || tail == NULL
1645 » » || end == NULL || cleanup == NULL)
1642 return 0; 1646 return 0;
1643 ADDOP_JREL(c, SETUP_LOOP, end); 1647 ADDOP_JREL(c, SETUP_LOOP, end);
1644 if (!compiler_push_fblock(c, LOOP, start)) 1648 if (!compiler_push_fblock(c, LOOP, start))
1645 return 0; 1649 return 0;
1646 VISIT(c, expr, s->v.For.iter); 1650 VISIT(c, expr, s->v.For.iter);
1651 for_lineno = c->u->u_lineno;
1647 ADDOP(c, GET_ITER); 1652 ADDOP(c, GET_ITER);
1648 compiler_use_next_block(c, start); 1653 compiler_use_next_block(c, start);
1654 ADDOP_JREL(c, JUMP_FORWARD, tail);
1655 compiler_use_next_block(c, body);
1656 VISIT(c, expr, s->v.For.target);
1657 VISIT_SEQ(c, stmt, s->v.For.body);
1658 compiler_use_next_block(c, tail);
1649 /* for expressions must be traced on each iteration, 1659 /* for expressions must be traced on each iteration,
1650 so we need to set an extra line number. */ 1660 so we need to set an extra line number. */
1651 c->u->u_lineno_set = false; 1661 c->u->u_lineno_set = false;
1652 » ADDOP_JREL(c, FOR_ITER, cleanup); 1662 » c->u->u_lineno = for_lineno;
1653 » VISIT(c, expr, s->v.For.target); 1663 » ADDOP_JABS(c, FOR_ITER, body);
1654 » VISIT_SEQ(c, stmt, s->v.For.body);
1655 » ADDOP_JABS(c, JUMP_ABSOLUTE, start);
1656 compiler_use_next_block(c, cleanup); 1664 compiler_use_next_block(c, cleanup);
1657 ADDOP(c, POP_BLOCK); 1665 ADDOP(c, POP_BLOCK);
1658 compiler_pop_fblock(c, LOOP, start); 1666 compiler_pop_fblock(c, LOOP, start);
1659 VISIT_SEQ(c, stmt, s->v.For.orelse); 1667 VISIT_SEQ(c, stmt, s->v.For.orelse);
1660 compiler_use_next_block(c, end); 1668 compiler_use_next_block(c, end);
1661 return 1; 1669 return 1;
1662 } 1670 }
1663 1671
1664 static int 1672 static int
1665 compiler_while(struct compiler *c, stmt_ty s) 1673 compiler_while(struct compiler *c, stmt_ty s)
1666 { 1674 {
1667 » basicblock *loop, *orelse, *end, *anchor = NULL; 1675 » basicblock *loop, *orelse, *end;
1676 » /* These are unused if the condition is optimized into a constant */
1677 » basicblock *body = NULL, *tail = NULL, *anchor = NULL;
1668 int constant = expr_constant(s->v.While.test); 1678 int constant = expr_constant(s->v.While.test);
1679 int while_lineno;
1669 1680
1670 if (constant == 0) { 1681 if (constant == 0) {
1671 if (s->v.While.orelse) 1682 if (s->v.While.orelse)
1672 VISIT_SEQ(c, stmt, s->v.While.orelse); 1683 VISIT_SEQ(c, stmt, s->v.While.orelse);
1673 return 1; 1684 return 1;
1674 } 1685 }
1675 loop = compiler_new_block(c); 1686 loop = compiler_new_block(c);
1676 end = compiler_new_block(c); 1687 end = compiler_new_block(c);
1677 if (constant == -1) { 1688 if (constant == -1) {
1689 body = compiler_new_block(c);
1690 tail = compiler_new_block(c);
1678 anchor = compiler_new_block(c); 1691 anchor = compiler_new_block(c);
1679 » » if (anchor == NULL) 1692 » » if (body == NULL || tail == NULL || anchor == NULL)
1680 return 0; 1693 return 0;
1681 } 1694 }
1682 if (loop == NULL || end == NULL) 1695 if (loop == NULL || end == NULL)
1683 return 0; 1696 return 0;
1684 » if (s->v.While.orelse) { 1697 » if (asdl_seq_LEN(s->v.While.orelse)) {
1685 orelse = compiler_new_block(c); 1698 orelse = compiler_new_block(c);
1686 if (orelse == NULL) 1699 if (orelse == NULL)
1687 return 0; 1700 return 0;
1688 } 1701 }
1689 else 1702 else
1690 orelse = NULL; 1703 orelse = NULL;
1691 1704
1692 ADDOP_JREL(c, SETUP_LOOP, end); 1705 ADDOP_JREL(c, SETUP_LOOP, end);
1706 while_lineno = c->u->u_lineno;
1693 compiler_use_next_block(c, loop); 1707 compiler_use_next_block(c, loop);
1694 if (!compiler_push_fblock(c, LOOP, loop)) 1708 if (!compiler_push_fblock(c, LOOP, loop))
1695 return 0; 1709 return 0;
1696 if (constant == -1) { 1710 if (constant == -1) {
1711 ADDOP_JREL(c, JUMP_FORWARD, tail);
1712 compiler_use_next_block(c, body);
1713 }
1714 VISIT_SEQ(c, stmt, s->v.While.body);
1715 if (constant == -1) {
1716 compiler_use_next_block(c, tail);
1697 /* while expressions must be traced on each iteration, 1717 /* while expressions must be traced on each iteration,
1698 so we need to set an extra line number. */ 1718 so we need to set an extra line number. */
1699 c->u->u_lineno_set = false; 1719 c->u->u_lineno_set = false;
1720 c->u->u_lineno = while_lineno;
1700 VISIT(c, expr, s->v.While.test); 1721 VISIT(c, expr, s->v.While.test);
1701 » » ADDOP_JABS(c, POP_JUMP_IF_FALSE, anchor); 1722 » » ADDOP_JABS(c, POP_JUMP_IF_TRUE, body);
1702 } 1723 }
1703 » VISIT_SEQ(c, stmt, s->v.While.body); 1724 » else {
1704 » ADDOP_JABS(c, JUMP_ABSOLUTE, loop); 1725 » » ADDOP_JABS(c, JUMP_ABSOLUTE, loop);
1726 » }
1705 1727
1706 /* XXX should the two POP instructions be in a separate block 1728 /* XXX should the two POP instructions be in a separate block
1707 if there is no else clause ? 1729 if there is no else clause ?
1708 */ 1730 */
1709 1731
1710 if (constant == -1) { 1732 if (constant == -1) {
1711 compiler_use_next_block(c, anchor); 1733 compiler_use_next_block(c, anchor);
1712 ADDOP(c, POP_BLOCK); 1734 ADDOP(c, POP_BLOCK);
1713 } 1735 }
1714 compiler_pop_fblock(c, LOOP, loop); 1736 compiler_pop_fblock(c, LOOP, loop);
(...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after
2597 } 2619 }
2598 2620
2599 static int 2621 static int
2600 compiler_listcomp_generator(struct compiler *c, asdl_seq *generators, 2622 compiler_listcomp_generator(struct compiler *c, asdl_seq *generators,
2601 int gen_index, expr_ty elt) 2623 int gen_index, expr_ty elt)
2602 { 2624 {
2603 /* generate code for the iterator, then each of the ifs, 2625 /* generate code for the iterator, then each of the ifs,
2604 and then write to the element */ 2626 and then write to the element */
2605 2627
2606 comprehension_ty l; 2628 comprehension_ty l;
2607 » basicblock *start, *anchor, *skip, *if_cleanup; 2629 » basicblock *start, *body, *tail, *anchor;
2608 int i, n; 2630 int i, n;
2609 2631
2610 start = compiler_new_block(c); 2632 start = compiler_new_block(c);
2611 » skip = compiler_new_block(c); 2633 » body = compiler_new_block(c);
2612 » if_cleanup = compiler_new_block(c); 2634 » tail = compiler_new_block(c);
2613 anchor = compiler_new_block(c); 2635 anchor = compiler_new_block(c);
2614 2636
2615 » if (start == NULL || skip == NULL || if_cleanup == NULL || 2637 » if (start == NULL || body == NULL || tail == NULL || anchor == NULL)
2616 » » anchor == NULL)
2617 return 0; 2638 return 0;
2618 2639
2619 l = (comprehension_ty)asdl_seq_GET(generators, gen_index); 2640 l = (comprehension_ty)asdl_seq_GET(generators, gen_index);
2620 VISIT(c, expr, l->iter); 2641 VISIT(c, expr, l->iter);
2621 ADDOP(c, GET_ITER); 2642 ADDOP(c, GET_ITER);
2622 compiler_use_next_block(c, start); 2643 compiler_use_next_block(c, start);
2623 » ADDOP_JREL(c, FOR_ITER, anchor); 2644 » ADDOP_JREL(c, JUMP_FORWARD, tail);
2624 » NEXT_BLOCK(c); 2645 » compiler_use_next_block(c, body);
2625 VISIT(c, expr, l->target); 2646 VISIT(c, expr, l->target);
2626 2647
2627 /* XXX this needs to be cleaned up...a lot! */ 2648 /* XXX this needs to be cleaned up...a lot! */
2628 n = asdl_seq_LEN(l->ifs); 2649 n = asdl_seq_LEN(l->ifs);
2629 for (i = 0; i < n; i++) { 2650 for (i = 0; i < n; i++) {
2630 expr_ty e = (expr_ty)asdl_seq_GET(l->ifs, i); 2651 expr_ty e = (expr_ty)asdl_seq_GET(l->ifs, i);
2631 VISIT(c, expr, e); 2652 VISIT(c, expr, e);
2632 » » ADDOP_JABS(c, POP_JUMP_IF_FALSE, if_cleanup); 2653 » » ADDOP_JABS(c, POP_JUMP_IF_FALSE, tail);
2633 NEXT_BLOCK(c); 2654 NEXT_BLOCK(c);
2634 } 2655 }
2635 2656
2636 if (++gen_index < asdl_seq_LEN(generators)) 2657 if (++gen_index < asdl_seq_LEN(generators))
2637 if (!compiler_listcomp_generator(c, generators, gen_index, elt)) 2658 if (!compiler_listcomp_generator(c, generators, gen_index, elt))
2638 return 0; 2659 return 0;
2639 2660
2640 /* only append after the last for generator */ 2661 /* only append after the last for generator */
2641 if (gen_index >= asdl_seq_LEN(generators)) { 2662 if (gen_index >= asdl_seq_LEN(generators)) {
2642 VISIT(c, expr, elt); 2663 VISIT(c, expr, elt);
2643 ADDOP_I(c, LIST_APPEND, gen_index+1); 2664 ADDOP_I(c, LIST_APPEND, gen_index+1);
2665 }
2666 compiler_use_next_block(c, tail);
2667 ADDOP_JABS(c, FOR_ITER, body);
2668 compiler_use_next_block(c, anchor);
2644 2669
2645 compiler_use_next_block(c, skip);
2646 }
2647 compiler_use_next_block(c, if_cleanup);
2648 ADDOP_JABS(c, JUMP_ABSOLUTE, start);
2649 compiler_use_next_block(c, anchor);
2650
2651 return 1; 2670 return 1;
2652 } 2671 }
2653 2672
2654 static int 2673 static int
2655 compiler_listcomp(struct compiler *c, expr_ty e) 2674 compiler_listcomp(struct compiler *c, expr_ty e)
2656 { 2675 {
2657 assert(e->kind == ListComp_kind); 2676 assert(e->kind == ListComp_kind);
2658 ADDOP_I(c, BUILD_LIST, 0); 2677 ADDOP_I(c, BUILD_LIST, 0);
2659 return compiler_listcomp_generator(c, e->v.ListComp.generators, 0, 2678 return compiler_listcomp_generator(c, e->v.ListComp.generators, 0,
2660 e->v.ListComp.elt); 2679 e->v.ListComp.elt);
2661 } 2680 }
2662 2681
2663 static int 2682 static int
2664 compiler_genexp_generator(struct compiler *c, 2683 compiler_genexp_generator(struct compiler *c,
2665 asdl_seq *generators, int gen_index, 2684 asdl_seq *generators, int gen_index,
2666 expr_ty elt) 2685 expr_ty elt)
2667 { 2686 {
2668 /* generate code for the iterator, then each of the ifs, 2687 /* generate code for the iterator, then each of the ifs,
2669 and then write to the element */ 2688 and then write to the element */
2670 2689
2671 comprehension_ty ge; 2690 comprehension_ty ge;
2672 » basicblock *start, *anchor, *skip, *if_cleanup, *end; 2691 » basicblock *start, *body, *tail, *end;
2673 int i, n; 2692 int i, n;
2674 2693
2675 start = compiler_new_block(c); 2694 start = compiler_new_block(c);
2676 » skip = compiler_new_block(c); 2695 » body = compiler_new_block(c);
2677 » if_cleanup = compiler_new_block(c); 2696 » tail = compiler_new_block(c);
2678 » anchor = compiler_new_block(c);
2679 end = compiler_new_block(c); 2697 end = compiler_new_block(c);
2680 2698
2681 » if (start == NULL || skip == NULL || if_cleanup == NULL || 2699 » if (start == NULL || body == NULL || tail == NULL || end == NULL)
2682 » anchor == NULL || end == NULL)
2683 return 0; 2700 return 0;
2684 2701
2685 ge = (comprehension_ty)asdl_seq_GET(generators, gen_index); 2702 ge = (comprehension_ty)asdl_seq_GET(generators, gen_index);
2686 ADDOP_JREL(c, SETUP_LOOP, end); 2703 ADDOP_JREL(c, SETUP_LOOP, end);
2687 if (!compiler_push_fblock(c, LOOP, start)) 2704 if (!compiler_push_fblock(c, LOOP, start))
2688 return 0; 2705 return 0;
2689 2706
2690 if (gen_index == 0) { 2707 if (gen_index == 0) {
2691 /* Receive outermost iter as an implicit argument */ 2708 /* Receive outermost iter as an implicit argument */
2692 c->u->u_argcount = 1; 2709 c->u->u_argcount = 1;
2693 ADDOP_I(c, LOAD_FAST, 0); 2710 ADDOP_I(c, LOAD_FAST, 0);
2694 } 2711 }
2695 else { 2712 else {
2696 /* Sub-iter - calculate on the fly */ 2713 /* Sub-iter - calculate on the fly */
2697 VISIT(c, expr, ge->iter); 2714 VISIT(c, expr, ge->iter);
2698 ADDOP(c, GET_ITER); 2715 ADDOP(c, GET_ITER);
2699 } 2716 }
2700 compiler_use_next_block(c, start); 2717 compiler_use_next_block(c, start);
2701 » ADDOP_JREL(c, FOR_ITER, anchor); 2718 » ADDOP_JREL(c, JUMP_FORWARD, tail);
2702 » NEXT_BLOCK(c); 2719 » compiler_use_next_block(c, body);
2703 VISIT(c, expr, ge->target); 2720 VISIT(c, expr, ge->target);
2704 2721
2705 /* XXX this needs to be cleaned up...a lot! */ 2722 /* XXX this needs to be cleaned up...a lot! */
2706 n = asdl_seq_LEN(ge->ifs); 2723 n = asdl_seq_LEN(ge->ifs);
2707 for (i = 0; i < n; i++) { 2724 for (i = 0; i < n; i++) {
2708 expr_ty e = (expr_ty)asdl_seq_GET(ge->ifs, i); 2725 expr_ty e = (expr_ty)asdl_seq_GET(ge->ifs, i);
2709 VISIT(c, expr, e); 2726 VISIT(c, expr, e);
2710 » » ADDOP_JABS(c, POP_JUMP_IF_FALSE, if_cleanup); 2727 » » ADDOP_JABS(c, POP_JUMP_IF_FALSE, tail);
2711 NEXT_BLOCK(c); 2728 NEXT_BLOCK(c);
2712 } 2729 }
2713 2730
2714 if (++gen_index < asdl_seq_LEN(generators)) 2731 if (++gen_index < asdl_seq_LEN(generators))
2715 if (!compiler_genexp_generator(c, generators, gen_index, elt)) 2732 if (!compiler_genexp_generator(c, generators, gen_index, elt))
2716 return 0; 2733 return 0;
2717 2734
2718 /* only append after the last 'for' generator */ 2735 /* only append after the last 'for' generator */
2719 if (gen_index >= asdl_seq_LEN(generators)) { 2736 if (gen_index >= asdl_seq_LEN(generators)) {
2720 VISIT(c, expr, elt); 2737 VISIT(c, expr, elt);
2721 ADDOP(c, YIELD_VALUE); 2738 ADDOP(c, YIELD_VALUE);
2722 ADDOP(c, POP_TOP); 2739 ADDOP(c, POP_TOP);
2723
2724 compiler_use_next_block(c, skip);
2725 } 2740 }
2726 » compiler_use_next_block(c, if_cleanup); 2741 » compiler_use_next_block(c, tail);
2727 » ADDOP_JABS(c, JUMP_ABSOLUTE, start); 2742 » ADDOP_JABS(c, FOR_ITER, body);
2728 » compiler_use_next_block(c, anchor);
2729 ADDOP(c, POP_BLOCK); 2743 ADDOP(c, POP_BLOCK);
2730 compiler_pop_fblock(c, LOOP, start); 2744 compiler_pop_fblock(c, LOOP, start);
2731 compiler_use_next_block(c, end); 2745 compiler_use_next_block(c, end);
2732 2746
2733 return 1; 2747 return 1;
2734 } 2748 }
2735 2749
2736 static int 2750 static int
2737 compiler_genexp(struct compiler *c, expr_ty e) 2751 compiler_genexp(struct compiler *c, expr_ty e)
2738 { 2752 {
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after
3488 int i; 3502 int i;
3489 int size = 0; 3503 int size = 0;
3490 3504
3491 for (i = 0; i < b->b_iused; i++) 3505 for (i = 0; i < b->b_iused; i++)
3492 size += instrsize(&b->b_instr[i]); 3506 size += instrsize(&b->b_instr[i]);
3493 return size; 3507 return size;
3494 } 3508 }
3495 3509
3496 /* All about a_lnotab. 3510 /* All about a_lnotab.
3497 3511
3498 c_lnotab is an array of unsigned bytes disguised as a Python string. 3512 c_lnotab is an array of bytes disguised as a Python string. It is used
3499 It is used to map bytecode offsets to source code line #s (when needed 3513 to map bytecode offsets to source code line #s (when needed for tracebacks).
3500 for tracebacks).
3501 3514
3502 The array is conceptually a list of 3515 The array is conceptually a list of
3503 (bytecode offset increment, line number increment) 3516 (unsigned bytecode offset increment, signed line number increment)
3504 pairs. The details are important and delicate, best illustrated by example: 3517 pairs. The details are important and delicate, best illustrated by example:
3505 3518
3506 byte code offset source code line number 3519 byte code offset source code line number
3507 0 1 3520 0 1
3508 6 2 3521 6 2
3509 50 7 3522 50 7
3510 350 307 3523 350 307
3511 361 308 3524 361 308
3512 3525
3513 The first trick is that these numbers aren't stored, only the increments 3526 The first trick is that these numbers aren't stored, only the increments
3514 from one row to the next (this doesn't really work, but it's a start): 3527 from one row to the next (this doesn't really work, but it's a start):
3515 3528
3516 0, 1, 6, 1, 44, 5, 300, 300, 11, 1 3529 0, 1, 6, 1, 44, 5, 300, 300, 11, 1
3517 3530
3518 The second trick is that an unsigned byte can't hold negative values, or 3531 The second trick is that while bytecode offset increments are unsigned
3519 values larger than 255, so (a) there's a deep assumption that byte code 3532 bytes (byte code offsets are assumed to increase monotonically), line
3520 offsets and their corresponding line #s both increase monotonically, and (b) 3533 number increments can be negative as well as positive (this is necessary
3521 if at least one column jumps by more than 255 from one row to the next, more 3534 to evaluate a loop's condition at the end of the loop, saving an
3522 than one pair is written to the table. In case #b, there's no way to know 3535 unconditional jump). Thus, if either the bytecode increment jumps by more
3523 from looking at the table later how many were written.» That's the delicate 3536 than 255, or the line number increment jumps by more than 127 or less than
3524 part. A user of c_lnotab desiring to find the source line number 3537 -127, more than one pair is written to the table. In this case there's no
3525 corresponding to a bytecode address A should do something like this 3538 way to know from looking at the table later how many were written. That's
3539 the delicate part. A user of c_lnotab desiring to find the source line
3540 number corresponding to a bytecode address A should do something like
3541 this:
3526 3542
3527 lineno = addr = 0 3543 lineno = addr = 0
3528 for addr_incr, line_incr in c_lnotab: 3544 for addr_incr, line_incr in c_lnotab:
3529 addr += addr_incr 3545 addr += addr_incr
3530 if addr > A: 3546 if addr > A:
3531 return lineno 3547 return lineno
3532 lineno += line_incr 3548 lineno += line_incr
3533 3549
3534 In order for this to work, when the addr field increments by more than 255, 3550 In order for this to work, when the addr field increments by more than 255,
3535 the line # increment in each pair generated must be 0 until the remaining addr 3551 the line # increment in each pair generated must be 0 until the remaining addr
3536 increment is < 256. So, in the example above, assemble_lnotab (it used 3552 increment is < 256. So, in the example above, assemble_lnotab (it used
3537 to be called com_set_lineno) should not (as was actually done until 2.2) 3553 to be called com_set_lineno) should not (as was actually done until 2.2)
3538 expand 300, 300 to 255, 255, 45, 45, 3554 expand 300, 300 to 255, 255, 45, 45,
3539 » but to 255,» 0, 45, 255, 0, 45. 3555 » but to 255,» 0, 45, 127, 0, 127, 0, 46.
3540 */ 3556 */
3557
3558 #define MAX_LINENO 127
3559 #define MAX_BYTECODE 255
3541 3560
3542 static int 3561 static int
3543 assemble_lnotab(struct assembler *a, struct instr *i) 3562 assemble_lnotab(struct assembler *a, struct instr *i)
3544 { 3563 {
3545 » int d_bytecode, d_lineno; 3564 » int d_bytecode, d_lineno, d_abs_lineno, d_lineno_sign;
3546 int len; 3565 int len;
3547 unsigned char *lnotab; 3566 unsigned char *lnotab;
3548 3567
3549 d_bytecode = a->a_offset - a->a_lineno_off; 3568 d_bytecode = a->a_offset - a->a_lineno_off;
3550 d_lineno = i->i_lineno - a->a_lineno; 3569 d_lineno = i->i_lineno - a->a_lineno;
3570 d_abs_lineno = abs(d_lineno);
3571 d_lineno_sign = (d_lineno >= 0) ? 1 : -1;
3551 3572
3552 assert(d_bytecode >= 0); 3573 assert(d_bytecode >= 0);
3553 » assert(d_lineno >= 0); 3574 » assert(d_abs_lineno >= 0);
3554 3575
3555 » if(d_bytecode == 0 && d_lineno == 0) 3576 » if (d_bytecode == 0 && d_lineno == 0)
3556 return 1; 3577 return 1;
3557 3578
3558 » if (d_bytecode > 255) { 3579 » if (d_bytecode > MAX_BYTECODE) {
3559 » » int j, nbytes, ncodes = d_bytecode / 255; 3580 » » int j, nbytes, ncodes = d_bytecode / MAX_BYTECODE;
3560 nbytes = a->a_lnotab_off + 2 * ncodes; 3581 nbytes = a->a_lnotab_off + 2 * ncodes;
3561 len = PyString_GET_SIZE(a->a_lnotab); 3582 len = PyString_GET_SIZE(a->a_lnotab);
3562 if (nbytes >= len) { 3583 if (nbytes >= len) {
3563 if ((len <= INT_MAX / 2) && (len * 2 < nbytes)) 3584 if ((len <= INT_MAX / 2) && (len * 2 < nbytes))
3564 len = nbytes; 3585 len = nbytes;
3565 else if (len <= INT_MAX / 2) 3586 else if (len <= INT_MAX / 2)
3566 len *= 2; 3587 len *= 2;
3567 else { 3588 else {
3568 PyErr_NoMemory(); 3589 PyErr_NoMemory();
3569 return 0; 3590 return 0;
3570 } 3591 }
3571 if (_PyString_Resize(&a->a_lnotab, len) < 0) 3592 if (_PyString_Resize(&a->a_lnotab, len) < 0)
3572 return 0; 3593 return 0;
3573 } 3594 }
3574 lnotab = (unsigned char *) 3595 lnotab = (unsigned char *)
3575 PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off; 3596 PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off;
3576 for (j = 0; j < ncodes; j++) { 3597 for (j = 0; j < ncodes; j++) {
3577 » » » *lnotab++ = 255; 3598 » » » *lnotab++ = MAX_BYTECODE;
3578 *lnotab++ = 0; 3599 *lnotab++ = 0;
3579 } 3600 }
3580 » » d_bytecode -= ncodes * 255; 3601 » » d_bytecode -= ncodes * MAX_BYTECODE;
3581 a->a_lnotab_off += ncodes * 2; 3602 a->a_lnotab_off += ncodes * 2;
3582 } 3603 }
3583 » assert(d_bytecode <= 255); 3604 » assert(d_bytecode <= MAX_BYTECODE);
3584 » if (d_lineno > 255) { 3605 » if (d_abs_lineno > MAX_LINENO) {
3585 » » int j, nbytes, ncodes = d_lineno / 255; 3606 » » int j, nbytes, ncodes = d_abs_lineno / MAX_LINENO;
3586 nbytes = a->a_lnotab_off + 2 * ncodes; 3607 nbytes = a->a_lnotab_off + 2 * ncodes;
3587 len = PyString_GET_SIZE(a->a_lnotab); 3608 len = PyString_GET_SIZE(a->a_lnotab);
3588 if (nbytes >= len) { 3609 if (nbytes >= len) {
3589 if ((len <= INT_MAX / 2) && len * 2 < nbytes) 3610 if ((len <= INT_MAX / 2) && len * 2 < nbytes)
3590 len = nbytes; 3611 len = nbytes;
3591 else if (len <= INT_MAX / 2) 3612 else if (len <= INT_MAX / 2)
3592 len *= 2; 3613 len *= 2;
3593 else { 3614 else {
3594 PyErr_NoMemory(); 3615 PyErr_NoMemory();
3595 return 0; 3616 return 0;
3596 } 3617 }
3597 if (_PyString_Resize(&a->a_lnotab, len) < 0) 3618 if (_PyString_Resize(&a->a_lnotab, len) < 0)
3598 return 0; 3619 return 0;
3599 } 3620 }
3600 lnotab = (unsigned char *) 3621 lnotab = (unsigned char *)
3601 PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off; 3622 PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off;
3602 *lnotab++ = d_bytecode; 3623 *lnotab++ = d_bytecode;
3603 » » *lnotab++ = 255; 3624 » » *lnotab++ = MAX_LINENO * d_lineno_sign;
3604 d_bytecode = 0; 3625 d_bytecode = 0;
3605 for (j = 1; j < ncodes; j++) { 3626 for (j = 1; j < ncodes; j++) {
3606 *lnotab++ = 0; 3627 *lnotab++ = 0;
3607 » » » *lnotab++ = 255; 3628 » » » *lnotab++ = MAX_LINENO * d_lineno_sign;
3608 } 3629 }
3609 » » d_lineno -= ncodes * 255; 3630 » » d_abs_lineno -= ncodes * MAX_LINENO;
3610 a->a_lnotab_off += ncodes * 2; 3631 a->a_lnotab_off += ncodes * 2;
3611 } 3632 }
3612 3633
3613 len = PyString_GET_SIZE(a->a_lnotab); 3634 len = PyString_GET_SIZE(a->a_lnotab);
3614 if (a->a_lnotab_off + 2 >= len) { 3635 if (a->a_lnotab_off + 2 >= len) {
3615 if (_PyString_Resize(&a->a_lnotab, len * 2) < 0) 3636 if (_PyString_Resize(&a->a_lnotab, len * 2) < 0)
3616 return 0; 3637 return 0;
3617 } 3638 }
3618 lnotab = (unsigned char *) 3639 lnotab = (unsigned char *)
3619 PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off; 3640 PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off;
3620 3641
3621 a->a_lnotab_off += 2; 3642 a->a_lnotab_off += 2;
3622 if (d_bytecode) { 3643 if (d_bytecode) {
3623 *lnotab++ = d_bytecode; 3644 *lnotab++ = d_bytecode;
3624 » » *lnotab++ = d_lineno; 3645 » » *lnotab++ = d_abs_lineno * d_lineno_sign;
3625 } 3646 }
3626 else { /* First line of a block; def stmt, etc. */ 3647 else { /* First line of a block; def stmt, etc. */
3627 *lnotab++ = 0; 3648 *lnotab++ = 0;
3628 » » *lnotab++ = d_lineno; 3649 » » *lnotab++ = d_abs_lineno * d_lineno_sign;
3629 } 3650 }
3630 a->a_lineno = i->i_lineno; 3651 a->a_lineno = i->i_lineno;
3631 a->a_lineno_off = a->a_offset; 3652 a->a_lineno_off = a->a_offset;
3632 return 1; 3653 return 1;
3633 } 3654 }
3634 3655
3635 /* assemble_emit() 3656 /* assemble_emit()
3636 Extend the bytecode with a new instruction. 3657 Extend the bytecode with a new instruction.
3637 Update lnotab if necessary. 3658 Update lnotab if necessary.
3638 */ 3659 */
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
3953 if (_PyString_Resize(&a.a_lnotab, a.a_lnotab_off) < 0) 3974 if (_PyString_Resize(&a.a_lnotab, a.a_lnotab_off) < 0)
3954 goto error; 3975 goto error;
3955 if (_PyString_Resize(&a.a_bytecode, a.a_offset) < 0) 3976 if (_PyString_Resize(&a.a_bytecode, a.a_offset) < 0)
3956 goto error; 3977 goto error;
3957 3978
3958 co = makecode(c, &a); 3979 co = makecode(c, &a);
3959 error: 3980 error:
3960 assemble_free(&a); 3981 assemble_free(&a);
3961 return co; 3982 return co;
3962 } 3983 }
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld r497