Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
a0654d24
Commit
a0654d24
authored
Dec 01, 2008
by
Dag Sverre Seljebotn
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
More fixes for new temps
parent
98d56995
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
117 additions
and
21 deletions
+117
-21
Cython/Compiler/Code.py
Cython/Compiler/Code.py
+2
-1
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+86
-18
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+23
-0
Cython/Compiler/Optimize.py
Cython/Compiler/Optimize.py
+6
-2
No files found.
Cython/Compiler/Code.py
View file @
a0654d24
...
...
@@ -150,8 +150,9 @@ class FunctionState(object):
freelist
=
self
.
temps_free
.
get
((
type
,
manage_ref
))
if
freelist
is
None
:
freelist
=
[]
self
.
temps_free
[(
type
,
manage_ref
)]
=
freelist
if
name
in
freelist
:
raise
RuntimeError
(
"Temp %s freed twice!"
%
name
)
freelist
.
append
(
name
)
if
DebugFlags
.
debug_temp_code_comments
:
self
.
owner
.
putln
(
"/* %s released */"
%
name
)
...
...
Cython/Compiler/ExprNodes.py
View file @
a0654d24
...
...
@@ -439,6 +439,7 @@ class ExprNode(Node):
self
.
generate_result_code
(
code
)
if
self
.
is_temp
:
self
.
generate_subexpr_disposal_code
(
code
)
self
.
free_subexpr_temps
(
code
)
def
generate_subexpr_evaluation_code
(
self
,
code
):
for
node
in
self
.
subexpr_nodes
():
...
...
@@ -487,6 +488,10 @@ class ExprNode(Node):
def
free_temps
(
self
,
code
):
pass
def
free_subexpr_temps
(
self
,
code
):
for
sub
in
self
.
subexpr_nodes
():
sub
.
free_temps
(
code
)
# ---------------- Annotation ---------------------
def
annotate
(
self
,
code
):
...
...
@@ -582,6 +587,7 @@ class RemoveAllocateTemps(type):
class
NewTempExprNode
(
ExprNode
):
backwards_compatible_result
=
None
temp_code
=
None
# Do not enable this unless you are trying to make all ExprNodes
# NewTempExprNodes (child nodes reached via recursion may not have
...
...
@@ -617,6 +623,8 @@ class NewTempExprNode(ExprNode):
self
.
release_subexpr_temps
(
env
)
def
allocate_temp_result
(
self
,
code
):
if
self
.
temp_code
:
raise
RuntimeError
(
"Temp allocated multiple times"
)
type
=
self
.
type
if
not
type
.
is_void
:
if
type
.
is_pyobject
:
...
...
@@ -630,7 +638,11 @@ class NewTempExprNode(ExprNode):
self
.
temp_code
=
None
def
release_temp_result
(
self
,
code
):
if
not
self
.
temp_code
:
raise
RuntimeError
(
"No temp (perhaps released multiple times? See self.old_temp)"
)
code
.
funcstate
.
release_temp
(
self
.
temp_code
)
self
.
old_temp
=
self
.
temp_code
self
.
temp_code
=
None
def
generate_evaluation_code
(
self
,
code
):
code
.
mark_pos
(
self
.
pos
)
...
...
@@ -648,6 +660,7 @@ class NewTempExprNode(ExprNode):
# If we are temp we do not need to wait until this node is disposed
# before disposing children.
self
.
generate_subexpr_disposal_code
(
code
)
self
.
free_subexpr_temps
(
code
)
def
generate_disposal_code
(
self
,
code
):
if
self
.
is_temp
:
...
...
@@ -658,15 +671,17 @@ class NewTempExprNode(ExprNode):
self
.
generate_subexpr_disposal_code
(
code
)
def
generate_post_assignment_code
(
self
,
code
):
if
self
.
is_temp
and
self
.
type
.
is_pyobject
:
if
self
.
is_temp
:
if
self
.
type
.
is_pyobject
:
code
.
putln
(
"%s = 0;"
%
self
.
result
())
else
:
self
.
generate_subexpr_disposal_code
(
code
)
def
free_temps
(
self
,
code
):
if
self
.
is_temp
:
self
.
release_temp_result
()
for
sub
in
self
.
subexpr_nodes
()
:
s
ub
.
free
_temps
(
code
)
self
.
release_temp_result
(
code
)
else
:
s
elf
.
free_subexpr
_temps
(
code
)
# ExprNode = NewTempExprNode
...
...
@@ -1238,7 +1253,7 @@ class NameNode(AtomicExprNode):
print
(
"NameNode.generate_assignment_code:"
)
print
(
"...generating disposal code for %s"
%
rhs
)
rhs
.
generate_disposal_code
(
code
)
rhs
.
free_temps
(
code
)
else
:
if
self
.
type
.
is_buffer
:
# Generate code for doing the buffer release/acquisition.
...
...
@@ -1270,6 +1285,7 @@ class NameNode(AtomicExprNode):
print
(
"NameNode.generate_assignment_code:"
)
print
(
"...generating post-assignment code for %s"
%
rhs
)
rhs
.
generate_post_assignment_code
(
code
)
rhs
.
free_temps
(
code
)
def
generate_acquire_buffer
(
self
,
rhs
,
code
):
# rhstmp is only used in case the rhs is a complicated expression leading to
...
...
@@ -1708,6 +1724,14 @@ class IndexNode(ExprNode):
for
i
in
self
.
indices
:
i
.
generate_disposal_code
(
code
)
def
free_subexpr_temps
(
self
,
code
):
self
.
base
.
free_temps
(
code
)
if
not
self
.
indices
:
self
.
index
.
free_temps
(
code
)
else
:
for
i
in
self
.
indices
:
i
.
free_temps
(
code
)
def
generate_result_code
(
self
,
code
):
if
self
.
is_buffer_access
:
if
code
.
globalstate
.
directives
[
'nonecheck'
]:
...
...
@@ -1795,7 +1819,9 @@ class IndexNode(ExprNode):
"%s = %s;"
%
(
self
.
result
(),
rhs
.
result
()))
self
.
generate_subexpr_disposal_code
(
code
)
self
.
free_subexpr_temps
(
code
)
rhs
.
generate_disposal_code
(
code
)
rhs
.
free_temps
(
code
)
def
generate_deletion_code
(
self
,
code
):
self
.
generate_subexpr_evaluation_code
(
code
)
...
...
@@ -1935,6 +1961,7 @@ class SliceIndexNode(ExprNode):
rhs
.
result
(),
i
))
self
.
generate_subexpr_disposal_code
(
code
)
rhs
.
generate_disposal_code
(
code
)
rhs
.
free_temps
(
code
)
def
generate_deletion_code
(
self
,
code
):
if
not
self
.
type
.
is_pyobject
:
...
...
@@ -2722,6 +2749,7 @@ class AttributeNode(ExprNode):
self
.
interned_attr_cname
,
rhs
.
py_result
()))
rhs
.
generate_disposal_code
(
code
)
rhs
.
free_temps
(
code
)
else
:
if
(
self
.
obj
.
type
.
is_extension_type
and
self
.
needs_none_check
...
...
@@ -2738,7 +2766,9 @@ class AttributeNode(ExprNode):
rhs
.
result_as
(
self
.
ctype
())))
#rhs.result()))
rhs
.
generate_post_assignment_code
(
code
)
rhs
.
free_temps
(
code
)
self
.
obj
.
generate_disposal_code
(
code
)
self
.
obj
.
free_temps
(
code
)
def
generate_deletion_code
(
self
,
code
):
self
.
obj
.
generate_evaluation_code
(
code
)
...
...
@@ -2750,6 +2780,7 @@ class AttributeNode(ExprNode):
else
:
error
(
self
.
pos
,
"Cannot delete C attribute of extension type"
)
self
.
obj
.
generate_disposal_code
(
code
)
self
.
obj
.
free_temps
(
code
)
def
annotate
(
self
,
code
):
if
self
.
is_py_attr
:
...
...
@@ -2838,6 +2869,10 @@ class SequenceNode(NewTempExprNode):
self
.
generate_operation_code
(
code
)
def
generate_assignment_code
(
self
,
rhs
,
code
):
# Need to work around the fact that generate_evaluation_code
# allocates the temps in a rather hacky way -- the assignment
# is evaluated twice, within each if-block.
code
.
putln
(
"if (PyTuple_CheckExact(%s) && PyTuple_GET_SIZE(%s) == %s) {"
%
(
rhs
.
py_result
(),
...
...
@@ -2855,6 +2890,10 @@ class SequenceNode(NewTempExprNode):
value_node
.
generate_evaluation_code
(
code
)
rhs
.
generate_disposal_code
(
code
)
for
i
in
range
(
len
(
self
.
args
)):
self
.
args
[
i
].
generate_assignment_code
(
self
.
coerced_unpacked_items
[
i
],
code
)
code
.
putln
(
"} else {"
)
code
.
putln
(
...
...
@@ -2881,12 +2920,13 @@ class SequenceNode(NewTempExprNode):
print
(
"UnpackNode.generate_assignment_code:"
)
print
(
"...generating disposal code for %s"
%
self
.
iterator
)
self
.
iterator
.
generate_disposal_code
(
code
)
self
.
iterator
.
free_temps
(
code
)
code
.
putln
(
"}"
)
rhs
.
free_temps
()
for
i
in
range
(
len
(
self
.
args
)):
self
.
args
[
i
].
generate_assignment_code
(
self
.
coerced_unpacked_items
[
i
],
code
)
code
.
putln
(
"}"
)
rhs
.
free_temps
(
code
)
def
annotate
(
self
,
code
):
for
arg
in
self
.
args
:
...
...
@@ -2949,6 +2989,8 @@ class TupleNode(SequenceNode):
# in the tuple using a reference-stealing operation.
for
arg
in
self
.
args
:
arg
.
generate_post_assignment_code
(
code
)
# Should NOT call free_temps -- this is invoked by the default
# generate_evaluation_code which will do that.
class
ListNode
(
SequenceNode
):
...
...
@@ -3051,6 +3093,8 @@ class ListNode(SequenceNode):
# in the list using a reference-stealing operation.
for
arg
in
self
.
args
:
arg
.
generate_post_assignment_code
(
code
)
# Should NOT call free_temps -- this is invoked by the default
# generate_evaluation_code which will do that.
class
ListComprehensionNode
(
SequenceNode
):
...
...
@@ -3202,6 +3246,7 @@ class DictNode(ExprNode):
item
.
key
.
value
,
item
.
value
.
result
()))
item
.
generate_disposal_code
(
code
)
item
.
free_temps
(
code
)
def
annotate
(
self
,
code
):
for
item
in
self
.
key_value_pairs
:
...
...
@@ -3228,6 +3273,10 @@ class DictItemNode(ExprNode):
self
.
key
.
generate_disposal_code
(
code
)
self
.
value
.
generate_disposal_code
(
code
)
def
free_temps
(
self
,
code
):
self
.
key
.
free_temps
(
code
)
self
.
value
.
free_temps
(
code
)
def
__iter__
(
self
):
return
iter
([
self
.
key
,
self
.
value
])
...
...
@@ -4068,10 +4117,12 @@ class BoolBinopNode(NewTempExprNode):
self
.
operand2
.
generate_evaluation_code
(
code
)
self
.
allocate_temp_result
(
code
)
code
.
putln
(
"%s = %s;"
%
(
self
.
result
(),
self
.
operand2
.
result
()))
self
.
operand2
.
free_temps
()
self
.
operand2
.
generate_post_assignment_code
(
code
)
self
.
operand2
.
free_temps
(
code
)
code
.
putln
(
"} else {"
)
code
.
putln
(
"%s = %s;"
%
(
self
.
result
(),
self
.
operand1
.
result
()))
self
.
operand1
.
free_temps
()
self
.
operand1
.
generate_post_assignment_code
(
code
)
self
.
operand1
.
free_temps
(
code
)
code
.
putln
(
"}"
)
def
generate_operand1_test
(
self
,
code
):
...
...
@@ -4174,6 +4225,7 @@ class CondExprNode(ExprNode):
self
.
false_val
.
generate_evaluation_code
(
code
)
code
.
putln
(
"}"
)
self
.
test
.
generate_disposal_code
(
code
)
self
.
test
.
free_temps
(
code
)
richcmp_constants
=
{
"<"
:
"Py_LT"
,
...
...
@@ -4401,6 +4453,8 @@ class PrimaryCmpNode(NewTempExprNode, CmpNode):
self
.
result
(),
self
.
operand2
)
self
.
operand1
.
generate_disposal_code
(
code
)
self
.
operand2
.
generate_disposal_code
(
code
)
self
.
operand1
.
free_temps
(
code
)
self
.
operand2
.
free_temps
(
code
)
def
generate_subexpr_disposal_code
(
self
,
code
):
# If this is called, it is a non-cascaded cmp,
...
...
@@ -4408,6 +4462,12 @@ class PrimaryCmpNode(NewTempExprNode, CmpNode):
self
.
operand1
.
generate_disposal_code
(
code
)
self
.
operand2
.
generate_disposal_code
(
code
)
def
free_subexpr_temps
(
self
,
code
):
# If this is called, it is a non-cascaded cmp,
# so only need to dispose of the two main operands.
self
.
operand1
.
free_temps
(
code
)
self
.
operand2
.
free_temps
(
code
)
def
annotate
(
self
,
code
):
self
.
operand1
.
annotate
(
code
)
self
.
operand2
.
annotate
(
code
)
...
...
@@ -4484,6 +4544,7 @@ class CascadedCmpNode(Node, CmpNode):
code
,
result
,
self
.
operand2
)
# Cascaded cmp result is always temp
self
.
operand2
.
generate_disposal_code
(
code
)
self
.
operand2
.
free_temps
(
code
)
code
.
putln
(
"}"
)
def
annotate
(
self
,
code
):
...
...
@@ -4605,6 +4666,9 @@ class PyTypeTestNode(CoercionNode):
def
generate_post_assignment_code
(
self
,
code
):
self
.
arg
.
generate_post_assignment_code
(
code
)
def
free_temps
(
self
,
code
):
self
.
arg
.
free_temps
(
code
)
class
CoerceToPyTypeNode
(
CoercionNode
):
# This node is used to convert a C data type
...
...
@@ -4776,7 +4840,11 @@ class CloneNode(CoercionNode):
def
release_temp
(
self
,
env
):
pass
class
PersistentNode
(
ExprNode
):
def
free_temps
(
self
,
code
):
pass
class
DISABLED_PersistentNode
(
ExprNode
):
# A PersistentNode is like a CloneNode except it handles the temporary
# allocation itself by keeping track of the number of times it has been
# used.
...
...
Cython/Compiler/Nodes.py
View file @
a0654d24
...
...
@@ -2444,6 +2444,7 @@ class PyClassDefNode(ClassDefNode):
self
.
body
.
generate_execution_code
(
code
)
self
.
target
.
generate_assignment_code
(
self
.
classobj
,
code
)
self
.
dict
.
generate_disposal_code
(
code
)
self
.
dict
.
free_temps
(
code
)
class
CClassDefNode
(
ClassDefNode
):
...
...
@@ -2659,6 +2660,7 @@ class ExprStatNode(StatNode):
if
not
self
.
expr
.
is_temp
and
self
.
expr
.
result
():
code
.
putln
(
"%s;"
%
self
.
expr
.
result
())
self
.
expr
.
generate_disposal_code
(
code
)
self
.
expr
.
free_temps
(
code
)
def
annotate
(
self
,
code
):
self
.
expr
.
annotate
(
code
)
...
...
@@ -2884,6 +2886,7 @@ class CascadedAssignmentNode(AssignmentNode):
lhs
.
generate_assignment_code
(
rhs
,
code
)
# Assignment has disposed of the cloned RHS
self
.
rhs
.
generate_disposal_code
(
code
)
self
.
rhs
.
free_temps
(
code
)
def
annotate
(
self
,
code
):
for
i
in
range
(
len
(
self
.
lhs_list
)):
...
...
@@ -3016,7 +3019,9 @@ class InPlaceAssignmentNode(AssignmentNode):
code
.
error_goto_if_null
(
self
.
result_value
.
py_result
(),
self
.
pos
)))
self
.
result_value
.
generate_evaluation_code
(
code
)
# May be a type check...
self
.
rhs
.
generate_disposal_code
(
code
)
self
.
rhs
.
free_temps
(
code
)
self
.
dup
.
generate_disposal_code
(
code
)
self
.
dup
.
free_temps
(
code
)
self
.
lhs
.
generate_assignment_code
(
self
.
result_value
,
code
)
else
:
c_op
=
self
.
operator
...
...
@@ -3034,8 +3039,10 @@ class InPlaceAssignmentNode(AssignmentNode):
self
.
dup
.
generate_result_code
(
code
)
code
.
putln
(
"%s %s= %s;"
%
(
self
.
lhs
.
result
(),
c_op
,
self
.
rhs
.
result
())
)
self
.
rhs
.
generate_disposal_code
(
code
)
self
.
rhs
.
free_temps
(
code
)
if
self
.
dup
.
is_temp
:
self
.
dup
.
generate_subexpr_disposal_code
(
code
)
self
.
dup
.
free_subexpr_temps
(
code
)
def
create_dup_node
(
self
,
env
):
import
ExprNodes
...
...
@@ -3065,6 +3072,8 @@ class InPlaceAssignmentNode(AssignmentNode):
index
=
index
,
indices
=
indices
,
is_temp
=
self
.
dup
.
is_temp
)
else
:
assert
False
self
.
lhs
=
target_lhs
return
self
.
dup
...
...
@@ -3117,6 +3126,7 @@ class PrintStatNode(StatNode):
self
.
append_newline
,
code
.
error_goto
(
self
.
pos
)))
self
.
arg_tuple
.
generate_disposal_code
(
code
)
self
.
arg_tuple
.
free_temps
(
code
)
def
annotate
(
self
,
code
):
self
.
arg_tuple
.
annotate
(
code
)
...
...
@@ -3152,6 +3162,7 @@ class ExecStatNode(StatNode):
(
self
.
temp_result
,)
+
args
))
for
arg
in
self
.
args
:
arg
.
generate_disposal_code
(
code
)
arg
.
free_temps
(
code
)
code
.
putln
(
code
.
error_goto_if_null
(
self
.
temp_result
,
self
.
pos
))
code
.
put_decref_clear
(
self
.
temp_result
,
py_object_type
)
...
...
@@ -3287,6 +3298,7 @@ class ReturnStatNode(StatNode):
Naming
.
retval_cname
,
self
.
value
.
result_as
(
self
.
return_type
)))
self
.
value
.
generate_post_assignment_code
(
code
)
self
.
value
.
free_temps
(
code
)
else
:
if
self
.
return_type
.
is_pyobject
:
code
.
put_init_to_py_none
(
Naming
.
retval_cname
,
self
.
return_type
)
...
...
@@ -3372,10 +3384,13 @@ class RaiseStatNode(StatNode):
"__Pyx_ReRaise();"
)
if
self
.
exc_type
:
self
.
exc_type
.
generate_disposal_code
(
code
)
self
.
exc_type
.
free_temps
(
code
)
if
self
.
exc_value
:
self
.
exc_value
.
generate_disposal_code
(
code
)
self
.
exc_value
.
free_temps
(
code
)
if
self
.
exc_tb
:
self
.
exc_tb
.
generate_disposal_code
(
code
)
self
.
exc_tb
.
free_temps
(
code
)
code
.
putln
(
code
.
error_goto
(
self
.
pos
))
...
...
@@ -3442,6 +3457,7 @@ class AssertStatNode(StatNode):
"PyErr_SetObject(PyExc_AssertionError, %s);"
%
self
.
value
.
py_result
())
self
.
value
.
generate_disposal_code
(
code
)
self
.
value
.
free_temps
(
code
)
else
:
code
.
putln
(
"PyErr_SetNone(PyExc_AssertionError);"
)
...
...
@@ -3450,6 +3466,7 @@ class AssertStatNode(StatNode):
code
.
putln
(
"}"
)
self
.
cond
.
generate_disposal_code
(
code
)
self
.
cond
.
free_temps
(
code
)
code
.
putln
(
"#endif"
)
def
annotate
(
self
,
code
):
...
...
@@ -3756,6 +3773,7 @@ class ForInStatNode(LoopNode, StatNode):
code
.
put_label
(
break_label
)
self
.
iterator
.
release_counter_temp
(
code
)
self
.
iterator
.
generate_disposal_code
(
code
)
self
.
iterator
.
free_temps
(
code
)
def
annotate
(
self
,
code
):
self
.
target
.
annotate
(
code
)
...
...
@@ -3878,9 +3896,12 @@ class ForFromStatNode(LoopNode, StatNode):
code
.
putln
(
"}"
)
code
.
put_label
(
break_label
)
self
.
bound1
.
generate_disposal_code
(
code
)
self
.
bound1
.
free_temps
(
code
)
self
.
bound2
.
generate_disposal_code
(
code
)
self
.
bound2
.
free_temps
(
code
)
if
self
.
step
is
not
None
:
self
.
step
.
generate_disposal_code
(
code
)
self
.
step
.
free_temps
(
code
)
relation_table
=
{
# {relop : (initial offset, increment op)}
...
...
@@ -4103,6 +4124,7 @@ class ExceptClauseNode(Node):
self
.
match_flag
,
self
.
pattern
.
py_result
()))
self
.
pattern
.
generate_disposal_code
(
code
)
self
.
pattern
.
free_temps
(
code
)
code
.
putln
(
"if (%s) {"
%
self
.
match_flag
)
...
...
@@ -4539,6 +4561,7 @@ class FromImportStatNode(StatNode):
code
.
error_goto_if_null
(
self
.
item
.
result
(),
self
.
pos
)))
target
.
generate_assignment_code
(
self
.
item
,
code
)
self
.
module
.
generate_disposal_code
(
code
)
self
.
module
.
free_temps
(
code
)
...
...
Cython/Compiler/Optimize.py
View file @
a0654d24
...
...
@@ -8,9 +8,13 @@ import TypeSlots
import
Symtab
from
StringEncoding
import
EncodedString
#def unwrap_node(node):
# while isinstance(node, ExprNodes.PersistentNode):
# node = node.arg
# return node
# Temporary hack while PersistentNode is out of order
def
unwrap_node
(
node
):
while
isinstance
(
node
,
ExprNodes
.
PersistentNode
):
node
=
node
.
arg
return
node
def
is_common_value
(
a
,
b
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment