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

Side by Side Diff: Lib/compiler/pycodegen.py

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 import imp 1 import imp
2 import os 2 import os
3 import marshal 3 import marshal
4 import struct 4 import struct
5 import sys 5 import sys
6 from cStringIO import StringIO 6 from cStringIO import StringIO
7 7
8 from compiler import ast, parse, walk, syntax 8 from compiler import ast, parse, walk, syntax
9 from compiler import pyassem, misc, future, symbols 9 from compiler import pyassem, misc, future, symbols
10 from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICT, \ 10 from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICT, \
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 self.emit('BUILD_CLASS') 406 self.emit('BUILD_CLASS')
407 self.storeName(node.name) 407 self.storeName(node.name)
408 408
409 # The rest are standard visitor methods 409 # The rest are standard visitor methods
410 410
411 # The next few implement control-flow statements 411 # The next few implement control-flow statements
412 412
413 def visitIf(self, node): 413 def visitIf(self, node):
414 end = self.newBlock() 414 end = self.newBlock()
415 numtests = len(node.tests) 415 numtests = len(node.tests)
416 for i in range(numtests): 416 for i in range(numtests - 1):
417 test, suite = node.tests[i] 417 test, suite = node.tests[i]
418 if is_constant_false(test): 418 if is_constant_false(test):
419 # XXX will need to check generator stuff here 419 # XXX will need to check generator stuff here
420 continue 420 continue
421 self.set_lineno(test) 421 self.set_lineno(test)
422 self.visit(test) 422 self.visit(test)
423 nextTest = self.newBlock() 423 nextTest = self.newBlock()
424 self.emit('POP_JUMP_IF_FALSE', nextTest) 424 self.emit('POP_JUMP_IF_FALSE', nextTest)
425 self.nextBlock() 425 self.nextBlock()
426 self.visit(suite) 426 self.visit(suite)
427 self.emit('JUMP_FORWARD', end) 427 self.emit('JUMP_FORWARD', end)
428 self.startBlock(nextTest) 428 self.startBlock(nextTest)
429 if node.else_: 429 # The last test can optimize a few things
430 self.visit(node.else_) 430 test, suite = node.tests[numtests - 1]
431 if is_constant_false(test):
432 if node.else_:
433 self.visit(node.else_)
434 else:
435 self.set_lineno(test)
436 self.visit(test)
437 else_block = self.newBlock() if node.else_ else end
438 self.emit('POP_JUMP_IF_FALSE', else_block)
439 self.nextBlock()
440 self.visit(suite)
441 if node.else_:
442 self.emit('JUMP_FORWARD', end)
443 self.startBlock(else_block)
444 self.visit(node.else_)
431 self.nextBlock(end) 445 self.nextBlock(end)
432 446
433 def visitWhile(self, node): 447 def visitWhile(self, node):
434 self.set_lineno(node) 448 self.set_lineno(node)
435 449
436 loop = self.newBlock() 450 loop = self.newBlock()
437 else_ = self.newBlock() 451 else_ = self.newBlock()
452 body = self.newBlock()
453 tail = self.newBlock()
454 after = self.newBlock()
438 455
439 after = self.newBlock()
440 self.emit('SETUP_LOOP', after) 456 self.emit('SETUP_LOOP', after)
441 457
442 self.nextBlock(loop) 458 self.nextBlock(loop)
443 self.setups.push((LOOP, loop)) 459 self.setups.push((LOOP, loop))
460 self.emit('JUMP_FORWARD', tail)
461 self.startBlock(body)
444 462
445 self.set_lineno(node, force=True) 463 self.set_lineno(node, force=True)
464
465 self.visit(node.body)
466
467 self.nextBlock(tail)
446 self.visit(node.test) 468 self.visit(node.test)
447 self.emit('POP_JUMP_IF_FALSE', else_ or after) 469 self.emit('POP_JUMP_IF_TRUE', body)
448 470
449 self.nextBlock() 471 self.nextBlock(else_) # or just the POPs if not else clause
450 self.visit(node.body)
451 self.emit('JUMP_ABSOLUTE', loop)
452
453 self.startBlock(else_) # or just the POPs if not else clause
454 self.emit('POP_BLOCK') 472 self.emit('POP_BLOCK')
455 self.setups.pop() 473 self.setups.pop()
456 if node.else_: 474 if node.else_:
457 self.visit(node.else_) 475 self.visit(node.else_)
458 self.nextBlock(after) 476 self.nextBlock(after)
459 477
460 def visitFor(self, node): 478 def visitFor(self, node):
461 start = self.newBlock() 479 start = self.newBlock()
480 body = self.newBlock()
481 tail = self.newBlock()
462 anchor = self.newBlock() 482 anchor = self.newBlock()
463 after = self.newBlock() 483 after = self.newBlock()
464 self.setups.push((LOOP, start)) 484 self.setups.push((LOOP, start))
465 485
466 self.set_lineno(node) 486 self.set_lineno(node)
467 self.emit('SETUP_LOOP', after) 487 self.emit('SETUP_LOOP', after)
468 self.visit(node.list) 488 self.visit(node.list)
469 self.emit('GET_ITER') 489 self.emit('GET_ITER')
470 490
471 self.nextBlock(start) 491 self.nextBlock(start)
472 self.set_lineno(node, force=1) 492 self.set_lineno(node, force=1)
473 self.emit('FOR_ITER', anchor) 493 self.emit('JUMP_FORWARD', tail)
494 self.startBlock(body)
474 self.visit(node.assign) 495 self.visit(node.assign)
475 self.visit(node.body) 496 self.visit(node.body)
476 self.emit('JUMP_ABSOLUTE', start) 497 self.nextBlock(tail)
498 self.emit('FOR_ITER', body)
477 self.nextBlock(anchor) 499 self.nextBlock(anchor)
478 self.emit('POP_BLOCK') 500 self.emit('POP_BLOCK')
479 self.setups.pop() 501 self.setups.pop()
480 if node.else_: 502 if node.else_:
481 self.visit(node.else_) 503 self.visit(node.else_)
482 self.nextBlock(after) 504 self.nextBlock(after)
483 505
484 def visitBreak(self, node): 506 def visitBreak(self, node):
485 if not self.setups: 507 if not self.setups:
486 raise SyntaxError, "'break' outside loop (%s, %d)" % \ 508 raise SyntaxError, "'break' outside loop (%s, %d)" % \
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 self.emit('POP_TOP') 586 self.emit('POP_TOP')
565 self.nextBlock(end) 587 self.nextBlock(end)
566 588
567 # list comprehensions 589 # list comprehensions
568 def visitListComp(self, node): 590 def visitListComp(self, node):
569 self.set_lineno(node) 591 self.set_lineno(node)
570 # setup list 592 # setup list
571 self.emit('BUILD_LIST', 0) 593 self.emit('BUILD_LIST', 0)
572 594
573 stack = [] 595 stack = []
574 for i, for_ in zip(range(len(node.quals)), node.quals): 596 for for_ in node.quals:
575 start, anchor = self.visit(for_) 597 body, tail = self.visit(for_)
576 cont = None
577 for if_ in for_.ifs: 598 for if_ in for_.ifs:
578 if cont is None: 599 self.visit(if_, tail)
579 cont = self.newBlock() 600 stack.insert(0, (for_, body, tail))
580 self.visit(if_, cont)
581 stack.insert(0, (start, cont, anchor))
582 601
583 self.visit(node.expr) 602 self.visit(node.expr)
584 self.emit('LIST_APPEND', len(node.quals) + 1) 603 self.emit('LIST_APPEND', len(node.quals) + 1)
585 604
586 for start, cont, anchor in stack: 605 for for_, body, tail in stack:
587 if cont: 606 self.nextBlock(tail)
588 self.nextBlock(cont) 607 self.set_lineno(for_, force=True)
589 self.emit('JUMP_ABSOLUTE', start) 608 self.emit('FOR_ITER', body)
590 self.startBlock(anchor) 609 self.nextBlock()
591 610
592 def visitListCompFor(self, node): 611 def visitListCompFor(self, node):
593 start = self.newBlock() 612 body = self.newBlock()
594 anchor = self.newBlock() 613 tail = self.newBlock()
595 614
596 self.visit(node.list) 615 self.visit(node.list)
597 self.emit('GET_ITER') 616 self.emit('GET_ITER')
598 self.nextBlock(start)
599 self.set_lineno(node, force=True)
600 self.emit('FOR_ITER', anchor)
601 self.nextBlock() 617 self.nextBlock()
618 self.emit('JUMP_FORWARD', tail)
619 self.nextBlock(body)
602 self.visit(node.assign) 620 self.visit(node.assign)
603 return start, anchor 621 return body, tail
604 622
605 def visitListCompIf(self, node, branch): 623 def visitListCompIf(self, node, branch):
606 self.set_lineno(node, force=True) 624 self.set_lineno(node, force=True)
607 self.visit(node.test) 625 self.visit(node.test)
608 self.emit('POP_JUMP_IF_FALSE', branch) 626 self.emit('POP_JUMP_IF_FALSE', branch)
609 self.newBlock()
610 627
611 def _makeClosure(self, gen, args): 628 def _makeClosure(self, gen, args):
612 frees = gen.scope.get_free_vars() 629 frees = gen.scope.get_free_vars()
613 if frees: 630 if frees:
614 for name in frees: 631 for name in frees:
615 self.emit('LOAD_CLOSURE', name) 632 self.emit('LOAD_CLOSURE', name)
616 self.emit('BUILD_TUPLE', len(frees)) 633 self.emit('BUILD_TUPLE', len(frees))
617 self.emit('LOAD_CONST', gen) 634 self.emit('LOAD_CONST', gen)
618 self.emit('MAKE_CLOSURE', args) 635 self.emit('MAKE_CLOSURE', args)
619 else: 636 else:
(...skipping 10 matching lines...) Expand all
630 # precomputation of outmost iterable 647 # precomputation of outmost iterable
631 self.visit(node.code.quals[0].iter) 648 self.visit(node.code.quals[0].iter)
632 self.emit('GET_ITER') 649 self.emit('GET_ITER')
633 self.emit('CALL_FUNCTION', 1) 650 self.emit('CALL_FUNCTION', 1)
634 651
635 def visitGenExprInner(self, node): 652 def visitGenExprInner(self, node):
636 self.set_lineno(node) 653 self.set_lineno(node)
637 # setup list 654 # setup list
638 655
639 stack = [] 656 stack = []
640 for i, for_ in zip(range(len(node.quals)), node.quals): 657 for for_ in node.quals:
641 start, anchor, end = self.visit(for_) 658 body, tail, end = self.visit(for_)
642 cont = None
643 for if_ in for_.ifs: 659 for if_ in for_.ifs:
644 if cont is None: 660 self.visit(if_, tail)
645 cont = self.newBlock() 661 stack.insert(0, (for_, body, tail, end))
646 self.visit(if_, cont)
647 stack.insert(0, (start, cont, anchor, end))
648 662
649 self.visit(node.expr) 663 self.visit(node.expr)
650 self.emit('YIELD_VALUE') 664 self.emit('YIELD_VALUE')
651 self.emit('POP_TOP') 665 self.emit('POP_TOP')
652 666
653 for start, cont, anchor, end in stack: 667 for for_, body, tail, end in stack:
654 if cont: 668 self.nextBlock(tail)
655 self.nextBlock(cont) 669 self.set_lineno(for_, force=True)
656 self.emit('JUMP_ABSOLUTE', start) 670 self.emit('FOR_ITER', body)
657 self.startBlock(anchor) 671 self.nextBlock()
658 self.emit('POP_BLOCK') 672 self.emit('POP_BLOCK')
659 self.setups.pop() 673 self.setups.pop()
660 self.nextBlock(end) 674 self.nextBlock(end)
661 675
662 self.emit('LOAD_CONST', None) 676 self.emit('LOAD_CONST', None)
663 677
664 def visitGenExprFor(self, node): 678 def visitGenExprFor(self, node):
665 start = self.newBlock() 679 start = self.newBlock()
666 anchor = self.newBlock() 680 body = self.newBlock()
681 tail = self.newBlock()
667 end = self.newBlock() 682 end = self.newBlock()
668 683
669 self.setups.push((LOOP, start)) 684 self.setups.push((LOOP, start))
670 self.emit('SETUP_LOOP', end) 685 self.emit('SETUP_LOOP', end)
671 686
672 if node.is_outmost: 687 if node.is_outmost:
673 self.loadName('.0') 688 self.loadName('.0')
674 else: 689 else:
675 self.visit(node.iter) 690 self.visit(node.iter)
676 self.emit('GET_ITER') 691 self.emit('GET_ITER')
677 692
678 self.nextBlock(start) 693 self.nextBlock(start)
679 self.set_lineno(node, force=True) 694 self.emit('JUMP_FORWARD', tail)
680 self.emit('FOR_ITER', anchor) 695 self.nextBlock(body)
681 self.nextBlock()
682 self.visit(node.assign) 696 self.visit(node.assign)
683 return start, anchor, end 697 return body, tail, end
684 698
685 def visitGenExprIf(self, node, branch): 699 def visitGenExprIf(self, node, branch):
686 self.set_lineno(node, force=True) 700 self.set_lineno(node, force=True)
687 self.visit(node.test) 701 self.visit(node.test)
688 self.emit('POP_JUMP_IF_FALSE', branch) 702 self.emit('POP_JUMP_IF_FALSE', branch)
689 self.newBlock() 703 self.newBlock()
690 704
691 # exception related 705 # exception related
692 706
693 def visitAssert(self, node): 707 def visitAssert(self, node):
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 ast.Slice: AugSlice, 1505 ast.Slice: AugSlice,
1492 ast.Subscript: AugSubscript, 1506 ast.Subscript: AugSubscript,
1493 } 1507 }
1494 1508
1495 def wrap_aug(node): 1509 def wrap_aug(node):
1496 return wrapper[node.__class__](node) 1510 return wrapper[node.__class__](node)
1497 1511
1498 if __name__ == "__main__": 1512 if __name__ == "__main__":
1499 for file in sys.argv[1:]: 1513 for file in sys.argv[1:]:
1500 compileFile(file) 1514 compileFile(file)
OLDNEW

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