[Python-checkins] r64916 - python/branches/tlee-ast-optimize/Python/optimize.c

thomas.lee python-checkins at python.org
Sun Jul 13 17:11:55 CEST 2008


Author: thomas.lee
Date: Sun Jul 13 17:11:54 2008
New Revision: 64916
Log:
Include a hack for jump injection that doesn't break quite so many tests. Need to fix lnotab breakage due to if/else swappage (and possibly other optimizations).
Modified:
 python/branches/tlee-ast-optimize/Python/optimize.c
Modified: python/branches/tlee-ast-optimize/Python/optimize.c
==============================================================================
--- python/branches/tlee-ast-optimize/Python/optimize.c	(original)
+++ python/branches/tlee-ast-optimize/Python/optimize.c	Sun Jul 13 17:11:54 2008
@@ -6,6 +6,8 @@
 #include "node.h"
 #include "ast.h"
 
+#define NEXTLINE(lineno) (lineno+1)
+
 typedef struct _optimizer_block {
 struct _optimizer_block* b_next; /* next block on the stack */
 PySTEntryObject* b_ste; /* symtable entry */
@@ -258,7 +260,7 @@
 asdl_seq* seq = *seq_ptr;
 stmt_ty stmt = asdl_seq_GET(seq, n);
 
- /* eliminate unreachable branches in an "if" statement? */
+ /* eliminate unreachable branches in an "if" statement */
 if (stmt->kind == If_kind) {
 PyObject* test = _expr_constant_value(stmt->v.If.test);
 if (test != NULL) {
@@ -376,13 +378,14 @@
 if (retseq == NULL)
 return NULL;
 last = asdl_seq_GET(seq, asdl_seq_LEN(seq)-1);
- ret = Return(value, last->lineno, last->col_offset, arena);
+ ret = Return(value, NEXTLINE(last->lineno), last->col_offset, arena);
 if (ret == NULL)
 return NULL;
 asdl_seq_SET(retseq, 0, ret);
 return _asdl_seq_append(seq, 0, retseq, 0, arena);
 }
 
+#if 0
 static void
 _expr_incref(expr_ty expr)
 {
@@ -395,19 +398,21 @@
 Py_INCREF(expr->v.Const.value);
 }
 }
+#endif
 
 static int
 _inject_compound_stmt_return(stmt_ty stmt, stmt_ty next, PyArena* arena)
 {
-#if 0
+ expr_ty value = NULL;
+ if (next != NULL)
+ value = next->v.Return.value;
+
 /* if the else body is not present, there will be no jump anyway */
 if (stmt->kind == If_kind && stmt->v.If.orelse != NULL) {
 stmt_ty inner = asdl_seq_GET(stmt->v.If.body,
 LAST_IN_SEQ(stmt->v.If.body));
 
 if (inner->kind != Return_kind) {
- expr_ty value = next->v.Return.value;
- _expr_incref(value);
 stmt->v.If.body =
 _asdl_seq_append_return(stmt->v.If.body, value, arena);
 
@@ -422,8 +427,6 @@
 stmt_ty inner = asdl_seq_GET(stmt->v.TryExcept.body,
 LAST_IN_SEQ(stmt->v.TryExcept.body));
 if (inner->kind != Return_kind && inner->kind != Raise_kind) {
- expr_ty value = next->v.Return.value;
- _expr_incref(value);
 /* if we inject a return into the "try" body of a
 * "try..except..else", we will miss the "else"!
 * We need to take a different path if the "else" is
@@ -449,15 +452,12 @@
 stmt_ty inner = asdl_seq_GET(stmt->v.TryFinally.body,
 LAST_IN_SEQ(stmt->v.TryFinally.body));
 if (inner->kind != Return_kind && inner->kind != Raise_kind) {
- expr_ty value = next->v.Return.value;
- _expr_incref(value);
 stmt->v.TryFinally.body =
 _asdl_seq_append_return(stmt->v.TryFinally.body, value, arena);
 if (stmt->v.TryFinally.body == NULL)
 return 0;
 }
 }
-#endif
 
 return 1;
 }
@@ -467,32 +467,19 @@
 * they immediately return rather than jump.
 */
 static int
-_simplify_jumps(optimizer* opt, asdl_seq* seq)
+_simplify_jumps(optimizer* opt, asdl_seq* seq, int top)
 {
 int n, len;
 
 len = asdl_seq_LEN(seq);
 
 for (n = 0; n < len; n++) {
- stmt_ty stmt;
- stmt_ty next;
- 
- stmt = asdl_seq_GET(seq, n);
-
- /* on the last iteration, the target is an implicit `return None' */
- if (n == len-1) {
- /* if a "return" is already present, we have nothing left to do */
- if (stmt->kind == Return_kind)
- break;
-
- next = Return(NULL, stmt->lineno, stmt->col_offset, opt->opt_arena);
- if (next == NULL)
- return 0;
- }
- else
+ stmt_ty stmt = asdl_seq_GET(seq, n);
+ stmt_ty next = NULL;
+ if (n < len-1)
 next = asdl_seq_GET(seq, n+1);
- 
- if (next->kind == Return_kind)
+ /* XXX: handle the implicit return only if top-level function seq */
+ if ((top && next == NULL) || (next && next->kind == Return_kind))
 if (!_inject_compound_stmt_return(stmt, next, opt->opt_arena))
 return 0;
 }
@@ -515,7 +502,7 @@
 if (!_eliminate_unreachable_code(opt, seq_ptr, n))
 return 0;
 if (opt->opt_current->b_ste->ste_type == FunctionBlock)
- if (!_simplify_jumps(opt, *seq_ptr))
+ if (!_simplify_jumps(opt, *seq_ptr, 0))
 return 0;
 }
 return 1;
@@ -1166,15 +1153,43 @@
 }
 
 static int
+_contains_return(asdl_seq* seq)
+{
+ int i;
+ int len = asdl_seq_LEN(seq);
+ for (i = 0; i < len; i++)
+ if (((stmt_ty)asdl_seq_GET(seq, i))->kind == Return_kind)
+ return 1;
+ return 0;
+}
+
+static int
 optimize_function_def(optimizer* opt, stmt_ty* stmt_ptr)
 {
 stmt_ty stmt = *stmt_ptr;
+ 
+ /* XXX: this breaks a bunch of tests. For now we use a second pass. */
+#if 0
+ /* Make any implicit returns explicit */
+ if (!_contains_return(stmt->v.FunctionDef.body)) {
+ stmt->v.FunctionDef.body =
+ _asdl_seq_append_return(stmt->v.FunctionDef.body, NULL,
+ opt->opt_arena);
+ if (stmt->v.FunctionDef.body == NULL)
+ return 0;
+ }
+#endif
+
 if (!optimize_arguments(opt, &stmt->v.FunctionDef.args))
 return 0;
 if (!optimize_expr_seq(opt, &stmt->v.FunctionDef.decorator_list))
 return 0;
 if (!optimize_stmt_seq(opt, &stmt->v.FunctionDef.body))
 return 0;
+ /* XXX: shallow second pass for implicit returns */
+ if (!_contains_return(stmt->v.FunctionDef.body))
+ if (!_simplify_jumps(opt, stmt->v.FunctionDef.body, 1))
+ return 0;
 return 1;
 }
 


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /