Commit 4d7dd100 authored by Stefan Behnel's avatar Stefan Behnel

merge

parents 324882b8 6a83f5ea
...@@ -14,6 +14,7 @@ try: ...@@ -14,6 +14,7 @@ try:
set set
except NameError: except NameError:
from sets import Set as set from sets import Set as set
import DebugFlags
class FunctionState(object): class FunctionState(object):
# return_label string function return point label # return_label string function return point label
...@@ -26,8 +27,9 @@ class FunctionState(object): ...@@ -26,8 +27,9 @@ class FunctionState(object):
# exc_vars (string * 3) exception variables for reraise, or None # exc_vars (string * 3) exception variables for reraise, or None
# Not used for now, perhaps later # Not used for now, perhaps later
def __init__(self, names_taken=set()): def __init__(self, owner, names_taken=set()):
self.names_taken = names_taken self.names_taken = names_taken
self.owner = owner
self.error_label = None self.error_label = None
self.label_counter = 0 self.label_counter = 0
...@@ -135,6 +137,8 @@ class FunctionState(object): ...@@ -135,6 +137,8 @@ class FunctionState(object):
if not result in self.names_taken: break if not result in self.names_taken: break
self.temps_allocated.append((result, type, manage_ref)) self.temps_allocated.append((result, type, manage_ref))
self.temps_used_type[result] = (type, manage_ref) self.temps_used_type[result] = (type, manage_ref)
if DebugFlags.debug_temp_code_comments:
self.owner.putln("/* %s allocated */" % result)
return result return result
def release_temp(self, name): def release_temp(self, name):
...@@ -149,6 +153,8 @@ class FunctionState(object): ...@@ -149,6 +153,8 @@ class FunctionState(object):
self.temps_free[(type, manage_ref)] = freelist self.temps_free[(type, manage_ref)] = freelist
freelist.append(name) freelist.append(name)
if DebugFlags.debug_temp_code_comments:
self.owner.putln("/* %s released */" % name)
def temps_in_use(self): def temps_in_use(self):
"""Return a list of (cname,type,manage_ref) tuples of temp names and their type """Return a list of (cname,type,manage_ref) tuples of temp names and their type
...@@ -567,7 +573,7 @@ class CCodeWriter(object): ...@@ -567,7 +573,7 @@ class CCodeWriter(object):
def enter_cfunc_scope(self): def enter_cfunc_scope(self):
self.funcstate = FunctionState() self.funcstate = FunctionState(self)
def exit_cfunc_scope(self): def exit_cfunc_scope(self):
self.funcstate = None self.funcstate = None
......
...@@ -2,3 +2,4 @@ debug_disposal_code = 0 ...@@ -2,3 +2,4 @@ debug_disposal_code = 0
debug_temp_alloc = 0 debug_temp_alloc = 0
debug_coercion = 0 debug_coercion = 0
debug_temp_code_comments = 1
...@@ -447,14 +447,17 @@ class ExprNode(Node): ...@@ -447,14 +447,17 @@ class ExprNode(Node):
def generate_result_code(self, code): def generate_result_code(self, code):
self.not_implemented("generate_result_code") self.not_implemented("generate_result_code")
def generate_disposal_code(self, code): def generate_disposal_code(self, code, free_temp=True, decref=True):
# If necessary, generate code to dispose of # If necessary, generate code to dispose of
# temporary Python reference. # temporary Python reference.
if self.is_temp: if not decref:
if self.type.is_pyobject: self.generate_post_assignment_code(code)
code.put_decref_clear(self.result(), self.ctype())
else: else:
self.generate_subexpr_disposal_code(code) if self.is_temp:
if self.type.is_pyobject:
code.put_decref_clear(self.result(), self.ctype())
else:
self.generate_subexpr_disposal_code(code)
def generate_subexpr_disposal_code(self, code): def generate_subexpr_disposal_code(self, code):
# Generate code to dispose of temporary results # Generate code to dispose of temporary results
...@@ -594,7 +597,9 @@ class NewTempExprNode(ExprNode): ...@@ -594,7 +597,9 @@ class NewTempExprNode(ExprNode):
def allocate_target_temps(self, env, rhs): def allocate_target_temps(self, env, rhs):
self.allocate_subexpr_temps(env) self.allocate_subexpr_temps(env)
rhs.release_temp(rhs) self.is_target = True
if rhs:
rhs.release_temp(env)
self.release_subexpr_temps(env) self.release_subexpr_temps(env)
def allocate_temps(self, env, result = None): def allocate_temps(self, env, result = None):
...@@ -645,23 +650,20 @@ class NewTempExprNode(ExprNode): ...@@ -645,23 +650,20 @@ class NewTempExprNode(ExprNode):
# before disposing children. # before disposing children.
self.generate_subexpr_disposal_code(code) self.generate_subexpr_disposal_code(code)
def generate_disposal_code(self, code): def generate_disposal_code(self, code, free_temp=True, decref=True):
if self.is_temp: if self.is_temp:
if self.type.is_pyobject: if self.type.is_pyobject:
code.put_decref_clear(self.result(), self.ctype()) if decref:
if not self.backwards_compatible_result: code.put_decref_clear(self.result(), self.ctype())
elif free_temp and not self.backwards_compatible_result:
code.putln("%s = 0;" % self.result())
if free_temp and not self.backwards_compatible_result:
self.release_temp_result(code) self.release_temp_result(code)
else: else:
self.generate_subexpr_disposal_code(code) self.generate_subexpr_disposal_code(code)
def generate_post_assignment_code(self, code): def generate_post_assignment_code(self, code):
if self.is_temp: self.generate_disposal_code(code, free_temp=True, decref=False)
if self.type.is_pyobject:
code.putln("%s = 0;" % self.temp_code)
if not self.backwards_compatible_result:
code.funcstate.release_temp(self.temp_code)
else:
self.generate_subexpr_disposal_code(code)
# ExprNode = NewTempExprNode # ExprNode = NewTempExprNode
...@@ -683,17 +685,10 @@ class AtomicNewTempExprNode(NewTempExprNode): ...@@ -683,17 +685,10 @@ class AtomicNewTempExprNode(NewTempExprNode):
subexprs = [] subexprs = []
# Override to optimize -- we know we have no children # Override to optimize -- we know we have no children
def generate_evaluation_code(self, code): def generate_subexpr_evaluation_code(self, code):
if self.is_temp: pass
self.allocate_temp_result(code) def generate_subexpr_disposal_code(self, code):
self.generate_result_code(code) pass
def generate_disposal_code(self, code):
if self.is_temp:
if self.type.is_pyobject:
code.put_decref_clear(self.result(), self.ctype())
if not self.backwards_compatible_result:
self.release_temp_result(code)
class PyConstNode(AtomicNewTempExprNode): class PyConstNode(AtomicNewTempExprNode):
# Abstract base class for constant Python values. # Abstract base class for constant Python values.
...@@ -3966,7 +3961,14 @@ class PowNode(NumBinopNode): ...@@ -3966,7 +3961,14 @@ class PowNode(NumBinopNode):
self.operand1.result(), self.operand2.result()) self.operand1.result(), self.operand2.result())
class BoolBinopNode(ExprNode): # Note: This class is temporary "shut down" into an ineffective mode temp
# allocation mode.
#
# More sophisticated temp reuse was going on before,
# one could have a look at adding this again after /all/ classes
# are converted to the new temp scheme. (The temp juggling cannot work
# otherwise).
class BoolBinopNode(NewTempExprNode):
# Short-circuiting boolean operation. # Short-circuiting boolean operation.
# #
# operator string # operator string
...@@ -4002,32 +4004,35 @@ class BoolBinopNode(ExprNode): ...@@ -4002,32 +4004,35 @@ class BoolBinopNode(ExprNode):
self.operand1 = self.operand1.coerce_to_boolean(env) self.operand1 = self.operand1.coerce_to_boolean(env)
self.operand2 = self.operand2.coerce_to_boolean(env) self.operand2 = self.operand2.coerce_to_boolean(env)
self.type = PyrexTypes.c_bint_type self.type = PyrexTypes.c_bint_type
# Below disabled for
# For what we're about to do, it's vital that # For what we're about to do, it's vital that
# both operands be temp nodes. # both operands be temp nodes.
self.operand1 = self.operand1.coerce_to_temp(env) #CTT # self.operand1 = self.operand1.coerce_to_temp(env) #CTT
self.operand2 = self.operand2.coerce_to_temp(env) # self.operand2 = self.operand2.coerce_to_temp(env)
self.is_temp = 1 self.is_temp = 1
gil_message = "Truth-testing Python object" gil_message = "Truth-testing Python object"
def allocate_temps(self, env, result_code = None): ## def allocate_temps(self, env, result_code = None):
# We don't need both operands at the same time, and ## # We don't need both operands at the same time, and
# one of the operands will also be our result. So we ## # one of the operands will also be our result. So we
# use an allocation strategy here which results in ## # use an allocation strategy here which results in
# this node and both its operands sharing the same ## # this node and both its operands sharing the same
# result variable. This allows us to avoid some ## # result variable. This allows us to avoid some
# assignments and increfs/decrefs that would otherwise ## # assignments and increfs/decrefs that would otherwise
# be necessary. ## # be necessary.
self.allocate_temp(env, result_code) ## self.allocate_temp(env, result_code)
self.operand1.allocate_temps(env, self.result()) ## self.operand1.allocate_temps(env, self.result())
self.operand2.allocate_temps(env, self.result()) ## self.operand2.allocate_temps(env, self.result())
# We haven't called release_temp on either operand, ## # We haven't called release_temp on either operand,
# because although they are temp nodes, they don't own ## # because although they are temp nodes, they don't own
# their result variable. And because they are temp ## # their result variable. And because they are temp
# nodes, any temps in their subnodes will have been ## # nodes, any temps in their subnodes will have been
# released before their allocate_temps returned. ## # released before their allocate_temps returned.
# Therefore, they contain no temp vars that need to ## # Therefore, they contain no temp vars that need to
# be released. ## # be released.
def check_const(self): def check_const(self):
self.operand1.check_const() self.operand1.check_const()
...@@ -4042,6 +4047,7 @@ class BoolBinopNode(ExprNode): ...@@ -4042,6 +4047,7 @@ class BoolBinopNode(ExprNode):
py_to_c_op = {'and': "&&", 'or': "||"} py_to_c_op = {'and': "&&", 'or': "||"}
def generate_evaluation_code(self, code): def generate_evaluation_code(self, code):
code.mark_pos(self.pos)
self.operand1.generate_evaluation_code(code) self.operand1.generate_evaluation_code(code)
test_result, uses_temp = self.generate_operand1_test(code) test_result, uses_temp = self.generate_operand1_test(code)
if self.operator == 'and': if self.operator == 'and':
...@@ -4054,10 +4060,17 @@ class BoolBinopNode(ExprNode): ...@@ -4054,10 +4060,17 @@ class BoolBinopNode(ExprNode):
test_result)) test_result))
if uses_temp: if uses_temp:
code.funcstate.release_temp(test_result) code.funcstate.release_temp(test_result)
self.operand1.generate_disposal_code(code) self.operand1.generate_disposal_code(code, free_temp=False)
self.operand2.generate_evaluation_code(code) self.operand2.generate_evaluation_code(code)
code.putln(
"}") self.allocate_temp_result(code)
code.putln("%s = %s;" % (self.result(), self.operand2.result()))
self.operand2.generate_disposal_code(code, decref=False)
code.putln("} else {")
code.putln("%s = %s;" % (self.result(), self.operand1.result()))
self.operand1.generate_disposal_code(code, decref=False)
code.putln("}")
def generate_operand1_test(self, code): def generate_operand1_test(self, code):
# Generate code to test the truth of the first operand. # Generate code to test the truth of the first operand.
......
...@@ -114,7 +114,7 @@ class Context: ...@@ -114,7 +114,7 @@ class Context:
_specific_post_parse, _specific_post_parse,
InterpretCompilerDirectives(self, self.pragma_overrides), InterpretCompilerDirectives(self, self.pragma_overrides),
_align_function_definitions, _align_function_definitions,
FlattenInListTransform(), # FlattenInListTransform(),
WithTransform(self), WithTransform(self),
DecoratorTransform(self), DecoratorTransform(self),
AnalyseDeclarationsTransform(self), AnalyseDeclarationsTransform(self),
......
...@@ -105,9 +105,7 @@ _ERRORS = u""" ...@@ -105,9 +105,7 @@ _ERRORS = u"""
39: 9: Constructing Python tuple not allowed without gil 39: 9: Constructing Python tuple not allowed without gil
40: 8: Constructing Python list not allowed without gil 40: 8: Constructing Python list not allowed without gil
41: 8: Constructing Python dict not allowed without gil 41: 8: Constructing Python dict not allowed without gil
42:12: Creating temporary Python reference not allowed without gil
42:12: Truth-testing Python object not allowed without gil 42:12: Truth-testing Python object not allowed without gil
42:17: Creating temporary Python reference not allowed without gil
43:13: Python type test not allowed without gil 43:13: Python type test not allowed without gil
#44: 4: Converting to Python object not allowed without gil #44: 4: Converting to Python object not allowed without gil
45:10: Operation not allowed without gil 45:10: Operation not allowed without gil
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment