# HG changeset patch # User Paul Boddie # Date 1314140746 -7200 # Node ID d6a0a0c10b1180013a907c98d69c339f023dd0aa # Parent 0437979b6a63668edbd59afa05f215c86b1d94f9 Removed the result registers. Attempted to fix the context test for cases where a first argument needs checking but where the target is known. Fixed various boolean test cases where the value-providing instruction can be removed in the optimisation step, corrupting the __bool__ access operation under certain conditions. diff -r 0437979b6a63 -r d6a0a0c10b11 micropython/ast.py --- a/micropython/ast.py Wed Aug 24 01:01:24 2011 +0200 +++ b/micropython/ast.py Wed Aug 24 01:05:46 2011 +0200 @@ -159,7 +159,7 @@ # Store the object as the result. - self.new_op(LoadTemp(0, target="result")) # load the context from the locals + self.new_op(LoadTemp(0)) # load the context from the locals self.new_op(Return()) self.unit.blocks = self.blocks @@ -222,6 +222,7 @@ self.dispatch(node.expr) temp = self.optimiser.optimise_temp_storage() + self.new_op(temp) self._generateTestBoolean(node.expr, temp) self.discard_temp(temp) @@ -775,6 +776,7 @@ self.dispatch(test) temp = self.optimiser.optimise_temp_storage() + self.new_op(temp) self._generateTestBoolean(node, temp) next_block = self.new_block() @@ -814,7 +816,7 @@ self.discard_temp(temp_arg) - self.set_target("exception") + self.new_op(Transfer(source="working", target="exception")) self.new_op(RaiseException()) @@ -824,8 +826,6 @@ else: self.dispatch(compiler.ast.Name("None")) - self.set_target("result") - if self.in_exception_handler: self.new_op(ClearException(target="exception")) @@ -932,6 +932,7 @@ self.dispatch(node.test) temp = self.optimiser.optimise_temp_storage() + self.new_op(temp) self._generateTestBoolean(node, temp) if node.else_ is not None: diff -r 0437979b6a63 -r d6a0a0c10b11 micropython/code.py --- a/micropython/code.py Wed Aug 24 01:01:24 2011 +0200 +++ b/micropython/code.py Wed Aug 24 01:05:46 2011 +0200 @@ -168,13 +168,6 @@ self.insert_op(-1, expr) self.last_op().source = "source" - def set_working(self, expr): - if expr is not None: - expr = expr.copy() - expr.target = "working" - self.insert_op(-1, expr) - self.last_op().source = "working" - def set_target(self, target): "Reset the target of the active instruction to 'target'." diff -r 0437979b6a63 -r d6a0a0c10b11 micropython/trans.py --- a/micropython/trans.py Wed Aug 24 01:01:24 2011 +0200 +++ b/micropython/trans.py Wed Aug 24 01:05:46 2011 +0200 @@ -562,7 +562,7 @@ # Adjust the invocation frame for unknown invocations. # Test the first argument if appropriate. - self._generateCallFuncContextTest(temp_target, target, temp_context, temp_first_argument, node) + self._generateCallFuncContextTest(target, temp_context, temp_first_argument, node) # Traverse the keyword arguments adding them at the appropriate frame # positions. @@ -735,13 +735,13 @@ self.new_op(LoadAddress(target.default_attrs[pos - nargs_min])) self.new_op(StoreFrame(pos)) - def _generateCallFuncContextTest(self, temp_target, target, temp_context, temp_first_argument, node): + def _generateCallFuncContextTest(self, target, temp_context, temp_first_argument, node): """ - Generate code to test for 'temp_target', representing the given - 'target', the context provided by 'temp_context' against - 'temp_first_argument', and to signal an exception (using 'node') if the - context is incompatible with the first frame argument. + Generate code involved in a call to the given 'target' to test the + context provided by 'temp_context' against 'temp_first_argument', and to + signal an exception (using 'node') if the context is incompatible with + the first frame argument. In addition, the invocation frame will be shifted if 'temp_context' indicates a function or a class. @@ -770,23 +770,28 @@ self.new_op(CheckClass(target="status")) self.new_op(JumpIfFalse(continue_block, working="status")) + # Test any explicit first argument against the context. + if temp_first_argument is not None: - self.new_op(temp_first_argument) # Check the current value (the argument) against the known context # (given as the source). - self.new_op(CheckInstance(target="status")) - self.set_working(temp_context) + temp_context = temp_context.copy() + temp_context.target = "source" + self.new_op(temp_context) + self.new_op(temp_first_argument) + self.new_op(CheckInstance(source="source", target="status")) - self.new_op(JumpIfTrue(adjust_block, working="status")) + if target is None: + self.new_op(JumpIfTrue(adjust_block, working="status")) + else: + self.new_op(JumpIfTrue(continue_block, working="status")) # Where the context is inappropriate, drop the incomplete frame and # raise an exception. self.new_op(DropFrame()) - self.new_op(Transfer(source="result", target="working")) - self.new_op(Transfer(source="result_context", target="working_context")) self.make_exception("TypeError") self.set_target("exception") @@ -824,9 +829,6 @@ "Finish the invocation and tidy up afterwards." self.new_op(DropFrame()) - if load_result: - self.new_op(Transfer(source="result", target="working")) - self.new_op(Transfer(source="result_context", target="working_context")) # Discard any temporary storage instructions. @@ -836,6 +838,10 @@ if temp_context is not None: self.discard_temp(temp_context) + # Reset the active values. + + self.optimiser.reset() + def _visitFunctionDeclaration(self, node): """ @@ -933,7 +939,6 @@ if not fn.is_lambda(): self.dispatch(compiler.ast.Name("None")) - self.set_target("result") self.new_op(Return()) # Make sure that enough frame space is reserved from the start. diff -r 0437979b6a63 -r d6a0a0c10b11 rsvp.py --- a/rsvp.py Wed Aug 24 01:01:24 2011 +0200 +++ b/rsvp.py Wed Aug 24 01:05:46 2011 +0200 @@ -46,7 +46,6 @@ * Registers: working context/value, assignment source context/value, - current result context/value, current exception value, boolean status value """ @@ -125,8 +124,6 @@ "working_context", "source", "source_context", - "result", - "result_context", "exception", "status" ) diff -r 0437979b6a63 -r d6a0a0c10b11 rsvplib.py --- a/rsvplib.py Wed Aug 24 01:01:24 2011 +0200 +++ b/rsvplib.py Wed Aug 24 01:05:46 2011 +0200 @@ -92,8 +92,8 @@ # Return the new object. # Introduce object as context for the new object. - self.machine.LoadImmediate(addr, "result_context") - self.machine.LoadImmediate(addr, "result") + self.machine.LoadImmediate(addr, "working_context") + self.machine.LoadImmediate(addr, "working") def native_logical_op(self, op): left = self.machine.load_from_frame(0) @@ -105,11 +105,11 @@ # NOTE: The data is considered ready to use. if op(self.machine.load(left_data), self.machine.load(right_data)): - self.machine.LoadImmediate(self.constants[True], "result_context") - self.machine.LoadImmediate(self.constants[True], "result") + self.machine.LoadImmediate(self.constants[True], "working_context") + self.machine.LoadImmediate(self.constants[True], "working") else: - self.machine.LoadImmediate(self.constants[False], "result_context") - self.machine.LoadImmediate(self.constants[False], "result") + self.machine.LoadImmediate(self.constants[False], "working_context") + self.machine.LoadImmediate(self.constants[False], "working") # Operators. # Although this takes a short-cut by using the operator module, testing is @@ -167,8 +167,8 @@ # Return the new object. # Introduce object as context for the new object. - self.machine.LoadImmediate(addr, "result_context") - self.machine.LoadImmediate(addr, "result") + self.machine.LoadImmediate(addr, "working_context") + self.machine.LoadImmediate(addr, "working") # Various built-in methods. @@ -212,8 +212,8 @@ # Get the item itself. data = self.machine.load(fragment.ref + self.fragment_data_offset + item_pos) - self.machine.LoadImmediate(data.context, "result_context") - self.machine.LoadImmediate(data.ref, "result") + self.machine.LoadImmediate(data.context, "working_context") + self.machine.LoadImmediate(data.ref, "working") def builtins_list_len(self): obj_value = self.machine.load_from_frame(0) @@ -240,8 +240,8 @@ # Return the new object. # Introduce object as context for the new object. - self.machine.LoadImmediate(addr, "result_context") - self.machine.LoadImmediate(addr, "result") + self.machine.LoadImmediate(addr, "working_context") + self.machine.LoadImmediate(addr, "working") def builtins_list_append(self): obj_value = self.machine.load_from_frame(0) @@ -302,8 +302,8 @@ fragment_member = obj_value.ref + self.instance_data_offset if self.machine._CheckInstance(obj_value.ref, self.tuple_class): - self.machine.LoadImmediate(obj_value.context, "result_context") - self.machine.LoadImmediate(obj_value.ref, "result") + self.machine.LoadImmediate(obj_value.context, "working_context") + self.machine.LoadImmediate(obj_value.ref, "working") return # Reject non-list, non-tuple types. @@ -334,8 +334,8 @@ # Return the new object. # Introduce object as context for the new object. - self.machine.LoadImmediate(addr, "result_context") - self.machine.LoadImmediate(addr, "result") + self.machine.LoadImmediate(addr, "working_context") + self.machine.LoadImmediate(addr, "working") def builtins_tuple_len(self): obj_value = self.machine.load_from_frame(0) @@ -357,8 +357,8 @@ # Return the new object. # Introduce object as context for the new object. - self.machine.LoadImmediate(addr, "result_context") - self.machine.LoadImmediate(addr, "result") + self.machine.LoadImmediate(addr, "working_context") + self.machine.LoadImmediate(addr, "working") def builtins_tuple_get_single_item(self): obj_value = self.machine.load_from_frame(0) @@ -382,8 +382,8 @@ # Get the item. data = self.machine.load(fragment_member + item_pos) - self.machine.LoadImmediate(data.context, "result_context") - self.machine.LoadImmediate(data.ref, "result") + self.machine.LoadImmediate(data.context, "working_context") + self.machine.LoadImmediate(data.ref, "working") def builtins_getattr(self): obj_value = self.machine.load_from_frame(0) @@ -412,8 +412,8 @@ loaded_data = self.machine._LoadAddressContextCond(loaded_data.context, loaded_data.ref, obj_value.ref) else: loaded_data = self.machine.load(obj_value.ref + offset) - self.machine.LoadImmediate(loaded_data.context, "result_context") - self.machine.LoadImmediate(loaded_data.ref, "result") + self.machine.LoadImmediate(loaded_data.context, "working_context") + self.machine.LoadImmediate(loaded_data.ref, "working") return self.machine.LoadImmediate(self.machine._MakeObject(self.instance_size, self.attr_error_instance), "exception") @@ -424,11 +424,11 @@ cls_value = self.machine.load_from_frame(1) if self.machine._CheckInstance(obj_value.ref, cls_value.ref): - self.machine.LoadImmediate(self.constants[True], "result_context") - self.machine.LoadImmediate(self.constants[True], "result") + self.machine.LoadImmediate(self.constants[True], "working_context") + self.machine.LoadImmediate(self.constants[True], "working") else: - self.machine.LoadImmediate(self.constants[False], "result_context") - self.machine.LoadImmediate(self.constants[False], "result") + self.machine.LoadImmediate(self.constants[False], "working_context") + self.machine.LoadImmediate(self.constants[False], "working") def builtins_print(self): # NOTE: Do nothing for now.