def get_result_suspstack(h): # Now we are in the target, after the switch() or the new(). # Note that this whole module was carefully written in such a way as # not to invoke pushing/popping things off the shadowstack at # unexpected moments... oldsuspstack = gcrootfinder.oldsuspstack newsuspstack = gcrootfinder.newsuspstack gcrootfinder.oldsuspstack = NULL_SUSPSTACK gcrootfinder.newsuspstack = NULL_SUSPSTACK if not h: raise MemoryError # We still have the old shadowstack active at this point; save it # away, and restore the new one if oldsuspstack: ll_assert(not _c.is_empty_handle(h),"unexpected empty stacklet handle") h = llmemory.cast_ptr_to_adr(h) llop.gc_save_current_state_away(lltype.Void, oldsuspstack, h) else: ll_assert(_c.is_empty_handle(h),"unexpected non-empty stacklet handle") llop.gc_forget_current_state(lltype.Void) # llop.gc_restore_state_from(lltype.Void, newsuspstack) # # From this point on, 'newsuspstack' is consumed and done, its # shadow stack installed as the current one. It should not be # used any more. For performance, we avoid it being deallocated # by letting it be reused on the next switch. gcrootfinder.oldsuspstack = newsuspstack # Return. return oldsuspstack
def get_result_suspstack(self, h): # # Return from a new() or a switch(): 'h' is a handle, possibly # an empty one, that says from where we switched to. if not h: raise MemoryError elif _c.is_empty_handle(h): return NULL_SUSPSTACK else: # This is a return that gave us a real handle. Store it. return self.attach_handle_on_suspstack(h)
def attach_handle_on_stacklet(stacklet, h): if not h: raise MemoryError elif _c.is_empty_handle(h): ll_assert(gcrootfinder.sscopy == llmemory.NULL, "empty_handle but sscopy != NULL") return NULL_STACKLET else: # This is a return that gave us a real handle. Store it. stacklet.s_handle = h stacklet.s_sscopy = gcrootfinder.sscopy ll_assert(gcrootfinder.sscopy != llmemory.NULL, "!empty_handle but sscopy == NULL") gcrootfinder.sscopy = llmemory.NULL llop.gc_writebarrier(lltype.Void, llmemory.cast_ptr_to_adr(stacklet)) return stacklet
def attach_handle_on_stacklet(stacklet, h): ll_assert(stacklet.s_handle == _c.null_handle, "attach stacklet 1: garbage") ll_assert(stacklet.s_sscopy == llmemory.NULL, "attach stacklet 2: garbage") if not h: raise MemoryError elif _c.is_empty_handle(h): ll_assert(gcrootfinder.sscopy == llmemory.NULL, "empty_handle but sscopy != NULL") return NULL_STACKLET else: # This is a return that gave us a real handle. Store it. stacklet.s_handle = h stacklet.s_sscopy = gcrootfinder.sscopy ll_assert(gcrootfinder.sscopy != llmemory.NULL, "!empty_handle but sscopy == NULL") gcrootfinder.sscopy = llmemory.NULL llop.gc_writebarrier(lltype.Void, llmemory.cast_ptr_to_adr(stacklet)) return stacklet