micropython

Change of rsvp.py

450:5382a26943ca
rsvp.py
     1.1 --- a/rsvp.py	Sun Aug 07 23:01:35 2011 +0200
     1.2 +++ b/rsvp.py	Sun Aug 21 14:24:28 2011 +0200
     1.3 @@ -44,12 +44,11 @@
     1.4  
     1.5    * Exception handler PC stack      refers to the state of the PC stack
     1.6  
     1.7 -  * Registers: current context/value,
     1.8 -               source context/value,
     1.9 +  * Registers: working context/value,
    1.10 +               assignment source context/value,
    1.11                 current result context/value,
    1.12                 current exception value,
    1.13 -               boolean status value,
    1.14 -               current callable
    1.15 +               boolean status value
    1.16  """
    1.17  
    1.18  from micropython.program import DataValue, ReplaceableContext, PlaceholderContext, FragmentObject
    1.19 @@ -121,22 +120,26 @@
    1.20  
    1.21          # Registers.
    1.22  
    1.23 -        self.value = None
    1.24 -        self.context = None
    1.25 +        self.register_names = (
    1.26 +            "working",
    1.27 +            "working_context",
    1.28 +            "source",
    1.29 +            "source_context",
    1.30 +            "result",
    1.31 +            "result_context",
    1.32 +            "exception",
    1.33 +            "status"
    1.34 +            )
    1.35 +        self.registers = {}
    1.36  
    1.37 -        self.source_value = None
    1.38 -        self.source_context = None
    1.39 -
    1.40 -        self.result_value = None
    1.41 -        self.result_context = None
    1.42 -
    1.43 -        self.exception = None
    1.44 +        for name in self.register_names:
    1.45 +            self.registers[name] = None
    1.46  
    1.47          self.instruction = None
    1.48 -        self.status = None
    1.49 -        self.callable = None
    1.50  
    1.51          # Constants.
    1.52 +        # NOTE: These should eventually be removed once the code using them has
    1.53 +        # NOTE: been migrated to the native code library.
    1.54  
    1.55          cls = self._get_class("__builtins__", "AttributeError")
    1.56          self.attr_error = cls.location
    1.57 @@ -179,20 +182,12 @@
    1.58          print "Handler frame stack", self.handler_local_sp_stack
    1.59          print "Handler PC stack", self.handler_pc_stack
    1.60          print
    1.61 -        print "Value", self.value
    1.62 -        print "Context", self.context
    1.63 +        print "Registers:"
    1.64          print
    1.65 -        print "Source value", self.source_value
    1.66 -        print "Source context", self.source_context
    1.67 -        print
    1.68 -        print "Result value", self.result_value
    1.69 -        print "Result context", self.result_context
    1.70 -        print
    1.71 -        print "Exception", self.exception
    1.72 +        for name in self.register_names:
    1.73 +            print "%s: %s" % (name, self.registers[name])
    1.74          print
    1.75          print "Instruction", self.instruction
    1.76 -        print "Status", self.status
    1.77 -        print "Callable", self.callable
    1.78  
    1.79      def show(self, start=None, end=None):
    1.80          self.show_memory(self.memory[start:end], self.coverage[start:end], start or 0)
    1.81 @@ -294,14 +289,14 @@
    1.82              breakpoint = 1
    1.83  
    1.84          print "Execution terminated",
    1.85 -        if self.exception is not None:
    1.86 -            ref = self.exception
    1.87 +        if breakpoint:
    1.88 +            print "with breakpoint."
    1.89 +            print "At address", self.pc
    1.90 +        elif self.registers["exception"] is not None:
    1.91 +            ref = self.registers["exception"]
    1.92              addr = self.load(ref + Library.instance_data_offset)
    1.93              print "with exception:", self.load(ref)
    1.94              print "At address %d: %r" % (addr, self.load(addr))
    1.95 -        elif breakpoint:
    1.96 -            print "with breakpoint."
    1.97 -            print "At address", self.pc
    1.98          else:
    1.99              print "successfully."
   1.100          print "After", self.counter, "instructions at cost", self.cost, "units."
   1.101 @@ -316,15 +311,15 @@
   1.102          self.run()
   1.103          success = 1
   1.104  
   1.105 -        if self.exception is None:
   1.106 +        if self.registers["exception"] is None:
   1.107              for name in module.keys():
   1.108                  if name.startswith("result"):
   1.109                      label, expected = name.split("_")
   1.110                      attr = module[name]
   1.111  
   1.112 -                    # NOTE: Assumptions about headers and content made.
   1.113 +                    # Need to skip the header to get at the members.
   1.114  
   1.115 -                    attr_location = module.location + 1 + attr.position
   1.116 +                    attr_location = module.location + Library.instance_data_offset + attr.position
   1.117                      value = self.load(attr_location)
   1.118  
   1.119                      if value is not None:
   1.120 @@ -349,10 +344,6 @@
   1.121  
   1.122          self.instruction = self.load(self.pc)
   1.123  
   1.124 -        # Process any inputs of the instruction.
   1.125 -
   1.126 -        self.process_inputs()
   1.127 -
   1.128          # Perform the instruction itself.
   1.129  
   1.130          next_pc = self.perform(self.instruction)
   1.131 @@ -380,32 +371,15 @@
   1.132              raise IllegalInstruction, (self.pc, instruction_name)
   1.133          return method
   1.134  
   1.135 -    def perform(self, instruction, is_input=0):
   1.136 +    def perform(self, instruction):
   1.137  
   1.138          "Perform the 'instruction', returning the next PC value or None."
   1.139  
   1.140 -        if not is_input:
   1.141 -            self.counter += 1
   1.142 -            self.cost += instruction.cost
   1.143 +        self.counter += 1
   1.144 +        self.cost += instruction.cost
   1.145          operand = instruction.get_operand()
   1.146          method = self.get_method(instruction)
   1.147 -        return method(operand)
   1.148 -
   1.149 -    def process_inputs(self):
   1.150 -
   1.151 -        """
   1.152 -        Process any inputs of the current instruction. This permits any directly
   1.153 -        connected sub-instructions to produce the effects that separate
   1.154 -        instructions would otherwise have.
   1.155 -        """
   1.156 -
   1.157 -        value, context = self.value, self.context
   1.158 -        if self.instruction.source is not None:
   1.159 -            self.perform(self.instruction.source, 1)
   1.160 -            self.source_value, self.source_context = self.value, self.context
   1.161 -        self.value, self.context = value, context
   1.162 -        if self.instruction.input is not None:
   1.163 -            self.perform(self.instruction.input, 1)
   1.164 +        return method(operand, instruction)
   1.165  
   1.166      def jump(self, addr, next):
   1.167  
   1.168 @@ -428,104 +402,123 @@
   1.169              self.push_pc(self.pc + 1)
   1.170              return addr
   1.171  
   1.172 +    # Helper methods.
   1.173 +
   1.174 +    def context_of(self, register):
   1.175 +        return "%s_context" % register
   1.176 +
   1.177 +    def load_from_frame(self, operand):
   1.178 +        frame = self.local_sp_stack[-1]
   1.179 +        return self.frame_stack[frame + operand]
   1.180 +
   1.181      # Low-level instructions.
   1.182  
   1.183 -    def LoadValue(self, operand):
   1.184 -        self.value = operand
   1.185 -
   1.186 -    def LoadContext(self, operand):
   1.187 -        self.context = operand
   1.188 +    def LoadImmediate(self, operand, target):
   1.189 +        self.registers[target] = operand
   1.190  
   1.191 -    def LoadSourceValue(self, operand):
   1.192 -        self.source_value = operand
   1.193 -
   1.194 -    def LoadSourceContext(self, operand):
   1.195 -        self.source_context = operand
   1.196 +    def LoadMemory(self, operand, target, source):
   1.197 +        self.registers[target] = self.load(
   1.198 +            self.registers[source] + (operand is not None and operand or 0)
   1.199 +            )
   1.200  
   1.201      # Instructions.
   1.202  
   1.203 -    def LoadConst(self, operand):
   1.204 -        self.LoadContext(operand)
   1.205 -        self.LoadValue(operand)
   1.206 +    def Transfer(self, operand, instruction):
   1.207 +        self.registers[instruction.target] = self.registers[instruction.source]
   1.208  
   1.209 -    def LoadClass(self, operand):
   1.210 -        self.LoadContext(PlaceholderContext)
   1.211 -        self.LoadValue(operand)
   1.212 +    def LoadConst(self, operand, instruction):
   1.213 +        self.LoadImmediate(operand, self.context_of(instruction.target))
   1.214 +        self.LoadImmediate(operand, instruction.target)
   1.215 +
   1.216 +    def LoadClass(self, operand, instruction):
   1.217 +        self.LoadImmediate(PlaceholderContext, self.context_of(instruction.target))
   1.218 +        self.LoadImmediate(operand, instruction.target)
   1.219  
   1.220 -    def LoadFunction(self, operand):
   1.221 -        self.LoadContext(ReplaceableContext)
   1.222 -        self.LoadValue(operand)
   1.223 +    def LoadFunction(self, operand, instruction):
   1.224 +        self.LoadImmediate(ReplaceableContext, self.context_of(instruction.target))
   1.225 +        self.LoadImmediate(operand, instruction.target)
   1.226  
   1.227 -    def LoadName(self, operand):
   1.228 +    def LoadName(self, operand, instruction):
   1.229 +        data = self.load_from_frame(operand)
   1.230 +        self.LoadImmediate(data.context, self.context_of(instruction.target))
   1.231 +        self.LoadImmediate(data.ref, instruction.target)
   1.232 +
   1.233 +    def StoreName(self, operand, instruction):
   1.234          frame = self.local_sp_stack[-1]
   1.235 -        data = self.frame_stack[frame + operand]
   1.236 -        self.LoadContext(data.context)
   1.237 -        self.LoadValue(data.ref)
   1.238 -
   1.239 -    def StoreName(self, operand):
   1.240 -        frame = self.local_sp_stack[-1]
   1.241 -        self.frame_stack[frame + operand] = DataValue(self.source_context, self.source_value)
   1.242 +        self.frame_stack[frame + operand] = DataValue(
   1.243 +            self.registers[self.context_of(instruction.source)],
   1.244 +            self.registers[instruction.source])
   1.245  
   1.246      LoadTemp = LoadName
   1.247  
   1.248 -    def StoreTemp(self, operand):
   1.249 +    def StoreTemp(self, operand, instruction):
   1.250          frame = self.local_sp_stack[-1]
   1.251 -        self.frame_stack[frame + operand] = DataValue(self.context, self.value)
   1.252 +        self.frame_stack[frame + operand] = DataValue(
   1.253 +            self.registers[self.context_of(instruction.working)],
   1.254 +            self.registers[instruction.working])
   1.255  
   1.256 -    def LoadAddress(self, operand):
   1.257 +    def LoadAddress(self, operand, instruction):
   1.258          # Preserve context (potentially null).
   1.259          data = self.load(operand)
   1.260 -        self.LoadContext(data.context)
   1.261 -        self.LoadValue(data.ref)
   1.262 +        self.LoadImmediate(data.context, self.context_of(instruction.target))
   1.263 +        self.LoadImmediate(data.ref, instruction.target)
   1.264  
   1.265 -    def LoadAddressContext(self, operand):
   1.266 +    def LoadAddressContext(self, operand, instruction):
   1.267          # Value becomes context.
   1.268          data = self.load(operand)
   1.269 -        self.LoadContext(self.value)
   1.270 -        self.LoadValue(data.ref)
   1.271 +        self.LoadImmediate(self.registers[instruction.working], self.context_of(instruction.target))
   1.272 +        self.LoadImmediate(data.ref, instruction.target)
   1.273  
   1.274 -    def LoadAddressContextCond(self, operand):
   1.275 +    def LoadAddressContextCond(self, operand, instruction):
   1.276          data = self.load(operand)
   1.277 -        data = self._LoadAddressContextCond(data.context, data.ref, self.value)
   1.278 -        self.LoadContext(data.context)
   1.279 -        self.LoadValue(data.ref)
   1.280 +        data = self._LoadAddressContextCond(data.context, data.ref, self.registers[instruction.working])
   1.281 +        self.LoadImmediate(data.context, self.context_of(instruction.target))
   1.282 +        self.LoadImmediate(data.ref, instruction.target)
   1.283  
   1.284 -    def StoreAddress(self, operand):
   1.285 +    def StoreAddress(self, operand, instruction):
   1.286          # Preserve context.
   1.287 -        self.save(operand, DataValue(self.source_context, self.source_value))
   1.288 +        self.save(operand, DataValue(
   1.289 +            self.registers[self.context_of(instruction.source)],
   1.290 +            self.registers[instruction.source]))
   1.291  
   1.292 -    def StoreAddressContext(self, operand):
   1.293 +    def StoreAddressContext(self, operand, instruction):
   1.294          # Overwrite context if null.
   1.295 -        self._StoreAddressContext(operand, self.context, self.value, self.source_context, self.source_value)
   1.296 +        self._StoreAddressContext(operand,
   1.297 +            self.registers[self.context_of(instruction.working)],
   1.298 +            self.registers[instruction.working],
   1.299 +            self.registers[self.context_of(instruction.source)],
   1.300 +            self.registers[instruction.source])
   1.301  
   1.302 -    def MakeInstance(self, size):
   1.303 +    def MakeInstance(self, size, instruction):
   1.304          # NOTE: Referencing the instance template.
   1.305 -        addr = self._MakeObject(size, self.value - Library.instance_template_size)
   1.306 +        addr = self._MakeObject(size, self.registers[instruction.working] - Library.instance_template_size)
   1.307          # Introduce object as context for the new object.
   1.308 -        self.LoadContext(addr)
   1.309 -        self.LoadValue(addr)
   1.310 +        self.LoadImmediate(addr, self.context_of(instruction.target))
   1.311 +        self.LoadImmediate(addr, instruction.target)
   1.312  
   1.313 -    def MakeFragment(self, size):
   1.314 +    def MakeFragment(self, size, instruction):
   1.315          # Reserve twice the amount of space.
   1.316          addr = self._MakeFragment(size, size * 2)
   1.317          # NOTE: Context is not relevant for fragments.
   1.318 -        self.LoadContext(None)
   1.319 -        self.LoadValue(addr)
   1.320 +        self.LoadImmediate(None, self.context_of(instruction.target))
   1.321 +        self.LoadImmediate(addr, instruction.target)
   1.322  
   1.323 -    def LoadAttr(self, pos):
   1.324 +    def LoadAttr(self, pos, instruction):
   1.325          # Retrieved context should already be appropriate for the instance.
   1.326 -        # NOTE: Adding 1 to skip any header.
   1.327 -        data = self.load(self.value + pos + 1)
   1.328 -        self.LoadContext(data.context)
   1.329 -        self.LoadValue(data.ref)
   1.330 +        # Skip any header.
   1.331 +        data = self.load(self.registers[instruction.working] + Library.instance_data_offset + pos)
   1.332 +        self.LoadImmediate(data.context, self.context_of(instruction.target))
   1.333 +        self.LoadImmediate(data.ref, instruction.target)
   1.334  
   1.335 -    def StoreAttr(self, pos):
   1.336 +    def StoreAttr(self, pos, instruction):
   1.337          # Target should already be an instance.
   1.338 -        # NOTE: Adding 1 to skip any header.
   1.339 -        self.save(self.value + pos + 1, DataValue(self.source_context, self.source_value))
   1.340 +        # Skip any header.
   1.341 +        self.save(self.registers[instruction.working] + Library.instance_data_offset + pos , DataValue(
   1.342 +            self.registers[self.context_of(instruction.source)],
   1.343 +            self.registers[instruction.source]))
   1.344  
   1.345 -    def LoadAttrIndex(self, index):
   1.346 -        data = self.load(self.value)
   1.347 +    def LoadAttrIndex(self, index, instruction):
   1.348 +        data = self.load(self.registers[instruction.working])
   1.349          element = self.objlist[data.classcode + index]
   1.350  
   1.351          if element is not None:
   1.352 @@ -534,18 +527,18 @@
   1.353                  if static_attr:
   1.354                      data = self.load(offset) # offset is address of class/module attribute
   1.355                  else:
   1.356 -                    data = self.load(self.value + offset)
   1.357 -                self.LoadContext(data.context)
   1.358 -                self.LoadValue(data.ref)
   1.359 +                    data = self.load(self.registers[instruction.working] + offset)
   1.360 +                self.LoadImmediate(data.context, self.context_of(instruction.target))
   1.361 +                self.LoadImmediate(data.ref, instruction.target)
   1.362                  return
   1.363  
   1.364 -        self.exception = self._MakeObject(Library.instance_size, self.attr_error_instance)
   1.365 +        self.registers["exception"] = self._MakeObject(Library.instance_size, self.attr_error_instance)
   1.366          return self.RaiseException()
   1.367  
   1.368      # LoadAttrIndexContext not defined.
   1.369  
   1.370 -    def LoadAttrIndexContextCond(self, index):
   1.371 -        data = self.load(self.value)
   1.372 +    def LoadAttrIndexContextCond(self, index, instruction):
   1.373 +        data = self.load(self.registers[instruction.working])
   1.374          element = self.objlist[data.classcode + index]
   1.375  
   1.376          if element is not None:
   1.377 @@ -555,95 +548,102 @@
   1.378                      loaded_data = self.load(offset) # offset is address of class/module attribute
   1.379                      # Absent attrcode == class/module.
   1.380                      if data.attrcode is not None:
   1.381 -                        loaded_data = self._LoadAddressContextCond(loaded_data.context, loaded_data.ref, self.value)
   1.382 +                        loaded_data = self._LoadAddressContextCond(
   1.383 +                            loaded_data.context, loaded_data.ref,
   1.384 +                            self.registers[instruction.working])
   1.385                  else:
   1.386 -                    loaded_data = self.load(self.value + offset)
   1.387 -                self.LoadContext(loaded_data.context)
   1.388 -                self.LoadValue(loaded_data.ref)
   1.389 +                    loaded_data = self.load(self.registers[instruction.working] + offset)
   1.390 +                self.LoadImmediate(loaded_data.context, self.context_of(instruction.target))
   1.391 +                self.LoadImmediate(loaded_data.ref, instruction.target)
   1.392                  return
   1.393  
   1.394 -        self.exception = self._MakeObject(Library.instance_size, self.attr_error_instance)
   1.395 +        self.registers["exception"] = self._MakeObject(Library.instance_size, self.attr_error_instance)
   1.396          return self.RaiseException()
   1.397  
   1.398 -    def StoreAttrIndex(self, index):
   1.399 -        data = self.load(self.value)
   1.400 +    def StoreAttrIndex(self, index, instruction):
   1.401 +        data = self.load(self.registers[instruction.working])
   1.402          element = self.objlist[data.classcode + index]
   1.403  
   1.404          if element is not None:
   1.405              attr_index, static_attr, offset = element
   1.406              if attr_index == index:
   1.407                  if static_attr:
   1.408 -                    self._StoreAddressContext(offset, self.context, self.value, self.source_context, self.source_value)
   1.409 +                    self._StoreAddressContext(offset,
   1.410 +                        self.registers[self.context_of(instruction.working)],
   1.411 +                        self.registers[instruction.working],
   1.412 +                        self.registers[self.context_of(instruction.source)],
   1.413 +                        self.registers[instruction.source])
   1.414                      return
   1.415                  else:
   1.416 -                    self.save(self.value + offset, DataValue(self.source_context, self.source_value))
   1.417 +                    self.save(self.registers[instruction.working] + offset, DataValue(
   1.418 +                        self.registers[self.context_of(instruction.source)],
   1.419 +                        self.registers[instruction.source]))
   1.420                      return
   1.421  
   1.422 -        self.exception = self._MakeObject(Library.instance_size, self.attr_error_instance)
   1.423 +        self.registers["exception"] = self._MakeObject(Library.instance_size, self.attr_error_instance)
   1.424          return self.RaiseException()
   1.425  
   1.426      # NOTE: LoadAttrIndexContext is a possibility if a particular attribute can always be overridden.
   1.427  
   1.428 -    def MakeFrame(self, size):
   1.429 +    def MakeFrame(self, size, instruction):
   1.430          self.invocation_sp_stack.append(len(self.frame_stack))
   1.431          self.frame_stack.extend([None] * size)
   1.432  
   1.433 -    def DropFrame(self, operand=None):
   1.434 +    def DropFrame(self, operand, instruction):
   1.435          self.local_sp_stack.pop()
   1.436          frame = self.invocation_sp_stack.pop()
   1.437          del self.frame_stack[frame:] # reset stack before call
   1.438  
   1.439 -    def StoreFrame(self, pos):
   1.440 +    def StoreFrame(self, pos, instruction):
   1.441          frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame
   1.442 -        self.frame_stack[frame + pos] = DataValue(self.context, self.value)
   1.443 +        self.frame_stack[frame + pos] = DataValue(
   1.444 +            self.registers[self.context_of(instruction.working)],
   1.445 +            self.registers[instruction.working])
   1.446  
   1.447 -    def StoreFrameIndex(self, index):
   1.448 +    def StoreFrameIndex(self, index, instruction):
   1.449          frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame
   1.450 -        data = self.load(self.value)
   1.451 +        data = self.load(self.registers[instruction.working])
   1.452          element = self.paramlist[data.funccode + index]
   1.453  
   1.454          if element is not None:
   1.455              # NOTE: Need to ensure correct positioning where a context has been generated.
   1.456              param_index, offset = element
   1.457              if param_index == index:
   1.458 -                self.frame_stack[frame + offset] = DataValue(self.source_context, self.source_value)
   1.459 +                self.frame_stack[frame + offset] = DataValue(
   1.460 +                    self.registers[self.context_of(instruction.source)],
   1.461 +                    self.registers[instruction.source])
   1.462                  return
   1.463  
   1.464 -        self.exception = self._MakeObject(Library.instance_size, self.type_error_instance)
   1.465 +        self.registers["exception"] = self._MakeObject(Library.instance_size, self.type_error_instance)
   1.466          return self.RaiseException()
   1.467  
   1.468 -    def LoadCallable(self, operand=None):
   1.469 -        data = self.load(self.value)
   1.470 -        self.callable = data.codeaddr
   1.471 -
   1.472 -    def StoreCallable(self, operand=None):
   1.473 -        # NOTE: Should improve the representation and permit direct saving.
   1.474 -        data = self.load(self.value)
   1.475 -        self.save(self.value, data.with_callable(self.callable))
   1.476 +    def LoadCallable(self, operand, instruction):
   1.477 +        data = self.load(self.registers[instruction.working])
   1.478 +        self.registers[instruction.target] = data.codeaddr
   1.479  
   1.480 -    def LoadContextIntoValue(self, operand=None):
   1.481 -        # NOTE: Omission of the context of the context would make things like
   1.482 -        # NOTE: self() inside methods impossible.
   1.483 -        self.LoadValue(self.context)
   1.484 +    def StoreCallable(self, operand, instruction):
   1.485 +        # NOTE: Should improve the representation and permit direct saving.
   1.486 +        data = self.load(self.registers[instruction.working])
   1.487 +        self.save(self.registers[instruction.working], data.with_callable(self.registers[instruction.source]))
   1.488  
   1.489 -    def CheckContext(self, operand=None):
   1.490 -        self.status = self.value is not ReplaceableContext
   1.491 +    def CheckContext(self, operand, instruction):
   1.492 +        self.registers[instruction.target] = self.registers[instruction.working] is not ReplaceableContext
   1.493  
   1.494 -    def CheckClass(self, operand=None):
   1.495 -        if self.value in (ReplaceableContext, PlaceholderContext):
   1.496 -            self.status = 0
   1.497 +    def CheckClass(self, operand, instruction):
   1.498 +        if self.registers[instruction.working] in (ReplaceableContext, PlaceholderContext):
   1.499 +            self.registers[instruction.target] = 0
   1.500              return
   1.501  
   1.502 -        data = self.load(self.value)
   1.503 +        data = self.load(self.registers[instruction.working])
   1.504  
   1.505          # Classes are not themselves usable as the self argument.
   1.506          # NOTE: This may change at some point.
   1.507          # However, where classes appear as the context, instance
   1.508          # compatibility is required in the first argument.
   1.509  
   1.510 -        self.status = data.attrcode is None # absent attrcode == class
   1.511 +        self.registers[instruction.target] = data.attrcode is None # absent attrcode == class
   1.512  
   1.513 -    def CheckFrame(self, operand):
   1.514 +    def CheckFrame(self, operand, instruction):
   1.515          (nargs, ndefaults) = operand
   1.516  
   1.517          # The frame is actually installed as the locals.
   1.518 @@ -654,10 +654,10 @@
   1.519  
   1.520          if not ((nargs - ndefaults) <= nlocals):
   1.521              raise Exception, "CheckFrame %r (%r <= %r <= %r)" % (operand, nargs - ndefaults, nlocals, nargs)
   1.522 -            self.exception = self._MakeObject(Library.instance_size, self.type_error_instance)
   1.523 +            self.registers["exception"] = self._MakeObject(Library.instance_size, self.type_error_instance)
   1.524              return self.RaiseException()
   1.525  
   1.526 -    def CheckExtra(self, nargs):
   1.527 +    def CheckExtra(self, nargs, instruction):
   1.528  
   1.529          # The frame is actually installed as the locals.
   1.530          # Retrieve the context from the first local.
   1.531 @@ -670,7 +670,7 @@
   1.532          if nlocals == nargs:
   1.533              self.frame_stack.extend([None]) # ExtendFrame(1)
   1.534  
   1.535 -    def FillDefaults(self, operand):
   1.536 +    def FillDefaults(self, operand, instruction):
   1.537          (nargs, ndefaults) = operand
   1.538  
   1.539          # The frame is actually installed as the locals.
   1.540 @@ -686,11 +686,14 @@
   1.541          pos = nlocals
   1.542  
   1.543          while pos < nargs:
   1.544 -            self.frame_stack[frame + pos] = self.load(self.value + default + 1) # skip header
   1.545 +
   1.546 +            # Skip any header.
   1.547 +
   1.548 +            self.frame_stack[frame + pos] = self.load(self.registers[instruction.working] + Library.instance_data_offset + default)
   1.549              default += 1
   1.550              pos += 1
   1.551  
   1.552 -    def CopyExtra(self, start):
   1.553 +    def CopyExtra(self, start, instruction):
   1.554  
   1.555          # The frame is the source of the extra arguments.
   1.556  
   1.557 @@ -705,84 +708,74 @@
   1.558          pos = start
   1.559  
   1.560          while pos < nlocals:
   1.561 -            self.save(ref + extra + 1, self.frame_stack[frame + pos]) # skip header when storing
   1.562 +
   1.563 +            # Skip any header.
   1.564 +
   1.565 +            self.save(ref + Library.instance_data_offset + extra, self.frame_stack[frame + pos])
   1.566              extra += 1
   1.567              pos += 1
   1.568  
   1.569 -        self.LoadContext(ref)
   1.570 -        self.LoadValue(ref)
   1.571 +        self.LoadImmediate(ref, self.context_of(instruction.working))
   1.572 +        self.LoadImmediate(ref, instruction.working)
   1.573  
   1.574 -    def CheckInstance(self, operand=None):
   1.575 +    def CheckInstance(self, operand, instruction):
   1.576          # For the 'self' parameter in an invoked function, the proposed context
   1.577          # ('self') is checked against the target's context.
   1.578 -        self.status = self._CheckInstance(self.value, self.source_value)
   1.579 +        self.registers[instruction.target] = self._CheckInstance(
   1.580 +            self.registers[instruction.working],
   1.581 +            self.registers[instruction.source])
   1.582  
   1.583 -    def JumpInFrame(self, operand=None):
   1.584 -        codeaddr = self.callable
   1.585 +    def JumpInFrame(self, operand, instruction):
   1.586 +        codeaddr = self.registers[instruction.working]
   1.587          return self.jump(codeaddr, self.pc + 1) # return to the instruction after this one
   1.588  
   1.589 -    def JumpWithFrame(self, operand=None):
   1.590 -        codeaddr = self.callable
   1.591 +    def JumpWithFrame(self, operand, instruction):
   1.592 +        codeaddr = self.registers[instruction.working]
   1.593          self.local_sp_stack.append(self.invocation_sp_stack[-1]) # adopt the invocation frame
   1.594          return self.jump(codeaddr, self.pc + 1) # return to the instruction after this one
   1.595  
   1.596 -    def JumpWithFrameDirect(self, addr):
   1.597 +    def JumpWithFrameDirect(self, addr, instruction):
   1.598          self.local_sp_stack.append(self.invocation_sp_stack[-1]) # adopt the invocation frame
   1.599          return self.jump(addr, self.pc + 1) # return to the instruction after this one
   1.600  
   1.601 -    def ExtendFrame(self, size):
   1.602 +    def ExtendFrame(self, size, instruction):
   1.603          self.frame_stack.extend([None] * size)
   1.604  
   1.605 -    def AdjustFrame(self, size):
   1.606 +    def AdjustFrame(self, size, instruction):
   1.607          self.invocation_sp_stack[-1] += size
   1.608  
   1.609 -    def Return(self, operand=None):
   1.610 +    def Return(self, operand, instruction):
   1.611          return self.pull_pc()
   1.612  
   1.613 -    def LoadResultIntoValue(self, operand=None):
   1.614 -        self.LoadContext(self.result_context)
   1.615 -        self.LoadValue(self.result_value)
   1.616 -
   1.617 -    def LoadValueIntoResult(self, operand=None):
   1.618 -        self.result_context = self.context
   1.619 -        self.result_value = self.value
   1.620 -
   1.621 -    def Jump(self, addr):
   1.622 +    def Jump(self, addr, instruction):
   1.623          return addr
   1.624  
   1.625 -    def JumpIfTrue(self, addr):
   1.626 -        if self.status:
   1.627 -            return addr
   1.628 -
   1.629 -    def JumpIfFalse(self, addr):
   1.630 -        if not self.status:
   1.631 +    def JumpIfTrue(self, addr, instruction):
   1.632 +        if self.registers[instruction.working]:
   1.633              return addr
   1.634  
   1.635 -    def LoadException(self, operand=None):
   1.636 -        self.LoadContext(self.exception)
   1.637 -        self.LoadValue(self.exception)
   1.638 -
   1.639 -    def StoreException(self, operand=None):
   1.640 -        self.exception = self.value
   1.641 +    def JumpIfFalse(self, addr, instruction):
   1.642 +        if not self.registers[instruction.working]:
   1.643 +            return addr
   1.644  
   1.645 -    def ClearException(self, operand=None):
   1.646 -        self.exception = None
   1.647 +    def ClearException(self, operand, instruction):
   1.648 +        self.LoadImmediate(None, instruction.target)
   1.649  
   1.650 -    def RaiseException(self, operand=None):
   1.651 +    def RaiseException(self, operand=None, instruction=None):
   1.652          # NOTE: Adding the program counter as the first attribute after __class__.
   1.653 -        self.save(self.exception + Library.instance_data_offset, self.pc)
   1.654 +        self.save(self.registers["exception"] + Library.instance_data_offset, self.pc)
   1.655          # Jumping to the current handler.
   1.656          if self.abort_upon_exception:
   1.657              raise Exception
   1.658          return self.handler_stack[-1]
   1.659  
   1.660 -    def PushHandler(self, addr):
   1.661 +    def PushHandler(self, addr, instruction):
   1.662          self.handler_stack.append(addr)
   1.663          self.handler_local_sp_stack.append(len(self.local_sp_stack))
   1.664          self.handler_invocation_sp_stack.append(len(self.invocation_sp_stack))
   1.665          self.handler_pc_stack.append(len(self.pc_stack))
   1.666  
   1.667 -    def PopHandler(self, nframes):
   1.668 +    def PopHandler(self, nframes, instruction):
   1.669          # Get the new local frame pointer and PC stack references.
   1.670          local_sp_top = self.handler_local_sp_stack[-nframes]
   1.671          invocation_sp_top = self.handler_invocation_sp_stack[-nframes]
   1.672 @@ -799,20 +792,18 @@
   1.673          del self.handler_invocation_sp_stack[-nframes:]
   1.674          del self.handler_stack[-nframes:]
   1.675  
   1.676 -    def CheckException(self, operand=None):
   1.677 -        self.status = self.exception is not None and self._CheckInstance(self.exception, self.value)
   1.678 -
   1.679 -    def TestIdentity(self, operand=None):
   1.680 -        self.status = self.value == self.source_value
   1.681 +    def CheckException(self, operand, instruction):
   1.682 +        self.registers[instruction.target] = self.registers["exception"] is not None and \
   1.683 +            self._CheckInstance(self.registers["exception"], self.registers[instruction.working])
   1.684  
   1.685 -    def TestIdentityAddress(self, addr):
   1.686 -        self.status = self.value == addr
   1.687 +    def TestIdentity(self, operand, instruction):
   1.688 +        self.registers[instruction.target] = self.registers[instruction.working] == self.registers[instruction.source]
   1.689  
   1.690 -    # LoadBoolean is implemented in the generated code.
   1.691 -    # StoreBoolean is implemented by testing against the True value.
   1.692 +    def TestIdentityAddress(self, addr, instruction):
   1.693 +        self.registers[instruction.target] = self.registers[instruction.working] == addr
   1.694  
   1.695 -    def InvertBoolean(self, operand=None):
   1.696 -        self.status = not self.status
   1.697 +    def InvertBoolean(self, operand, instruction):
   1.698 +        self.registers[instruction.target] = not self.registers[instruction.source]
   1.699  
   1.700      # Common implementation details.
   1.701