def test_methodcontext_s_home(): w_context = methodcontext() s_context = w_context.as_methodcontext_get_shadow(space) w_closure = space.newClosure(w_context, 3, 0, []) s_closure_context = wrapper.BlockClosureWrapper(space, w_closure).create_frame() assert s_closure_context.s_home() is s_context
def test_bc_pushClosureCopyCopied0ValuesBytecode(bytecode = pushClosureCopyCopiedValuesBytecode): for i in (0, 0xF0, 0x0FF0, 0xFFF0): w_frame, s_frame = new_frame(bytecode + chr(2) + chr(i >> 8) + chr(i & 0xFF)) pc = s_frame.pc() # create/find a method with an appropriate blockClosure step_in_interp(s_frame) assert s_frame.pc() == pc + 4 + i closure = wrapper.BlockClosureWrapper(space, s_frame.top()) assert closure.startpc() == pc + 4 + 4 + 1 # pc + offset + headerword + smalltalk 1-indexing assert closure.outerContext() is s_frame._w_self
def test_primitive_closure_copyClosure(): w_frame, s_frame = new_frame("<never called, but used for method generation>") w_outer_frame, s_initial_context = new_frame("<never called, but used for method generation>") w_block = prim(primitives.CLOSURE_COPY_WITH_COPIED_VALUES, map(wrap, [w_outer_frame, 2, [wrap(1), wrap(2)]]), w_frame) assert not w_block.is_nil(space) w_w_block = wrapper.BlockClosureWrapper(space, w_block) assert w_w_block.startpc() is 5 assert w_w_block.at0(0) == wrap(1) assert w_w_block.at0(1) == wrap(2) assert w_w_block.numArgs() is 2
def test_bc_pushClosureCopyCopied2ValuesBytecode(bytecode = pushClosureCopyCopiedValuesBytecode): w_frame, s_frame = new_frame(bytecode + chr(0x23) + chr(0) + chr(0)) s_frame.push(w("english")) s_frame.push(w("bar")) pc = s_frame.pc() step_in_interp(s_frame) assert s_frame.pc() == pc + 4 closure = wrapper.BlockClosureWrapper(space, s_frame.top()) assert closure.startpc() == pc + 4 + 5 assert closure.outerContext() is s_frame._w_self assert closure.at0(0).as_string() == "english" assert closure.at0(1).as_string() == "bar"
def newClosure(self, w_outer_ctxt, pc, numArgs, copiedValues): assert isinstance(w_outer_ctxt, model.W_PointersObject) pc_with_bytecodeoffset = pc + w_outer_ctxt.as_context_get_shadow(self).w_method().bytecodeoffset() + 1 BlockClosureShadow = self.w_BlockClosure.as_class_get_shadow(self) numCopied = len(copiedValues) w_closure = BlockClosureShadow.new(numCopied) closure = wrapper.BlockClosureWrapper(self, w_closure) closure.store_outerContext(w_outer_ctxt) closure.store_startpc(pc_with_bytecodeoffset) closure.store_numArgs(numArgs) for i0 in range(numCopied): closure.atput0(i0, copiedValues[i0]) return w_closure
def __init__(self, space, w_self, size, is_block_context=False, w_method=None, closure=None): old_shadow = None if w_self: old_shadow = w_self.shadow self = fresh_virtualizable(self) self.is_block_context = is_block_context self._s_sender = None AbstractRedirectingShadow.__init__(self, space, w_self, size) self.instances_w = {} self.state = InactiveContext self.store_pc(0) # From BlockContext self._w_home = None self._initialip = 0 self._eargc = 0 # From MethodContext self.closure = None self._w_method = None self._w_receiver = None self._is_BlockClosure_ensure = False if old_shadow and not is_block_context: if not closure: w_closure = old_shadow.fetch(constants.MTHDCTX_CLOSURE_OR_NIL) if w_closure is not space.w_nil: closure = wrapper.BlockClosureWrapper(space, w_closure) if not w_method and not closure: w_method = old_shadow.fetch(constants.MTHDCTX_METHOD) # Let's create the stack array if is_block_context or closure: self.closure = closure stacksize = self.stacksize() + self.tempsize() elif w_method: self.store_w_method(w_method) # Magic numbers... Takes care of cases where reflective # code writes more than actual stack size assert isinstance(w_method, model.W_CompiledMethod) stacksize = w_method.compute_frame_size() else: assert False self._temps_and_stack = [space.w_nil] * stacksize
def store_method_context(self, n0, w_value): if n0 == constants.MTHDCTX_METHOD: return self.store_w_method(w_value) if n0 == constants.MTHDCTX_CLOSURE_OR_NIL: if w_value.is_nil(self.space): self.closure = None else: self.closure = wrapper.BlockClosureWrapper(self.space, w_value) return if n0 == constants.MTHDCTX_RECEIVER: self.store_w_receiver(w_value) return temp_i = n0 - constants.MTHDCTX_TEMP_FRAME_START if (0 <= temp_i < self.tempsize()): return self.settemp(temp_i, w_value) else: return self.store_context_part(n0, w_value)
def tempsize(self): if not self.is_closure_context(): return self.s_method().tempsize() else: return wrapper.BlockClosureWrapper( self.space, self.w_closure_or_nil).tempsize()