Esempio n. 1
0
 def setup_root_stack():
     # The gcmap table is a list of pairs of pointers:
     #     void *SafePointAddress;
     #     void *Shape;
     # Here, i.e. when the program starts, we sort it
     # in-place on the SafePointAddress to allow for more
     # efficient searches.
     gcmapstart = llop.llvm_gcmapstart(llmemory.Address)
     gcmapend   = llop.llvm_gcmapend(llmemory.Address)
     insertion_sort(gcmapstart, gcmapend)
Esempio n. 2
0
    def walk_to_parent_frame(self, callee, caller):
        """Starting from 'callee', walk the next older frame on the stack
        and fill 'caller' accordingly.  Also invokes the collect_stack_root()
        callback from the GC code for each GC root found in 'caller'.
        """
        #
        # The gcmap table is a list of entries, two machine words each:
        #     void *SafePointAddress;
        #     int Shape;
        #
        # A "safe point" is the return address of a call.
        # The "shape" of a safe point is a list of integers
        # that represent "locations".  A "location" can be
        # either in the stack or in a register.  See
        # getlocation() for the decoding of this integer.
        # The locations stored in a "shape" are as follows:
        #
        #   * The "location" of the return address.  This is just
        #     after the end of the frame of 'callee'; it is the
        #     first word of the frame of 'caller' (see picture
        #     below).
        #
        #   * Four "locations" that specify where the function saves
        #     each of the four callee-saved registers (%ebx, %esi,
        #     %edi, %ebp).
        #
        #   * The number of live GC roots around the call.
        #
        #   * For each GC root, an integer that specify where the
        #     GC pointer is stored.  This is a "location" too.
        #
        # XXX the details are completely specific to X86!!!
        # a picture of the stack may help:
        #                                           ^ ^ ^
        #     |     ...      |                 to older frames
        #     +--------------+
        #     |   ret addr   |  <------ caller_frame (addr of retaddr)
        #     |     ...      |
        #     | caller frame |
        #     |     ...      |
        #     +--------------+
        #     |   ret addr   |  <------ callee_frame (addr of retaddr)
        #     |     ...      |
        #     | callee frame |
        #     |     ...      |                 lower addresses
        #     +--------------+                      v v v
        #

        retaddr = callee.frame_address.address[0]
        #
        # try to locate the caller function based on retaddr.
        #
        gcmapstart = llop.llvm_gcmapstart(llmemory.Address)
        gcmapend   = llop.llvm_gcmapend(llmemory.Address)
        item = search_in_gcmap(gcmapstart, gcmapend, retaddr)
        if not item:
            # the item may have been not found because the array was
            # not sorted.  Sort it and try again.
            sort_gcmap(gcmapstart, gcmapend)
            item = search_in_gcmap(gcmapstart, gcmapend, retaddr)
            if not item:
                llop.debug_fatalerror(lltype.Void, "cannot find gc roots!")
                return False
        #
        # found!  Enumerate the GC roots in the caller frame
        #
        shape = item.signed[1]
        if shape < 0:
            shape = ~ shape     # can ignore this "range" marker here
        self._shape_decompressor.setpos(shape)
        collect_stack_root = self.gcdata._gc_collect_stack_root
        gc = self.gc
        while True:
            location = self._shape_decompressor.next()
            if location == 0:
                break
            addr = self.getlocation(callee, location)
            if addr.address[0] != llmemory.NULL:
                collect_stack_root(gc, addr)
        #
        # track where the caller_frame saved the registers from its own
        # caller
        #
        reg = CALLEE_SAVED_REGS - 1
        while reg >= 0:
            location = self._shape_decompressor.next()
            addr = self.getlocation(callee, location)
            caller.regs_stored_at[reg] = addr
            reg -= 1

        location = self._shape_decompressor.next()
        caller.frame_address = self.getlocation(callee, location)
        # we get a NULL marker to mean "I'm the frame
        # of the entry point, stop walking"
        return caller.frame_address != llmemory.NULL
Esempio n. 3
0
            def walk_to_parent_frame(self):
                #
                # The gcmap table is a list of pairs of pointers:
                #     void *SafePointAddress;
                #     void *Shape;
                #
                # A "safe point" is the return address of a call.
                # The "shape" of a safe point records the size of the
                # frame of the function containing it, as well as a
                # list of the variables that contain gc roots at that
                # time.  Each variable is described by its offset in
                # the frame.
                #
                callee_frame = self.stack_current
                if llmemory.cast_adr_to_int(callee_frame) & 1:
                    return False   # odd bit set here when the callee_frame
                                   # is the frame of main(), i.e. when there
                                   # is nothing more for us in the stack.
                #
                # XXX the details are completely specific to X86!!!
                # a picture of the stack may help:
                #                                           ^ ^ ^
                #     |     ...      |                 to older frames
                #     +--------------+
                #     |  first word  |  <------ caller_frame (addr of 1st word)
                #     +              +
                #     | caller frame |
                #     |     ...      |
                #     |  frame data  |  <------ frame_data_base
                #     +--------------+
                #     |   ret addr   |
                #     +--------------+
                #     |  first word  |  <------ callee_frame (addr of 1st word)
                #     +              +
                #     | callee frame |
                #     |     ...      |
                #     |  frame data  |                 lower addresses
                #     +--------------+                      v v v
                #
                retaddr = callee_frame.address[1]
                #
                # try to locate the caller function based on retaddr.
                #
                gcmapstart = llop.llvm_gcmapstart(llmemory.Address)
                gcmapend   = llop.llvm_gcmapend(llmemory.Address)
                item = binary_search(gcmapstart, gcmapend, retaddr)
                if item.address[0] == retaddr:
                    #
                    # found!  Setup pointers allowing us to
                    # parse the caller's frame structure...
                    #
                    shape = item.address[1]
                    # XXX assumes that .signed is 32-bit
                    framesize = shape.signed[0]   # odd if it's main()
                    livecount = shape.signed[1]
                    caller_frame = callee_frame + 4 + framesize
                    self.stack_current = caller_frame
                    self.frame_data_base = callee_frame + 8
                    self.remaining_roots_in_current_frame = livecount
                    self.liveoffsets = shape + 8
                    return True

                # retaddr not found!
                llop.debug_fatalerror(lltype.Void, "cannot find gc roots!")
                return False
Esempio n. 4
0
    def walk_to_parent_frame(self, callee, caller):
        """Starting from 'callee', walk the next older frame on the stack
        and fill 'caller' accordingly.  Also invokes the collect_stack_root()
        callback from the GC code for each GC root found in 'caller'.
        """
        #
        # The gcmap table is a list of entries, two machine words each:
        #     void *SafePointAddress;
        #     int Shape;
        #
        # A "safe point" is the return address of a call.
        # The "shape" of a safe point is a list of integers
        # that represent "locations".  A "location" can be
        # either in the stack or in a register.  See
        # getlocation() for the decoding of this integer.
        # The locations stored in a "shape" are as follows:
        #
        #   * The "location" of the return address.  This is just
        #     after the end of the frame of 'callee'; it is the
        #     first word of the frame of 'caller' (see picture
        #     below).
        #
        #   * Four "locations" that specify where the function saves
        #     each of the four callee-saved registers (%ebx, %esi,
        #     %edi, %ebp).
        #
        #   * The number of live GC roots around the call.
        #
        #   * For each GC root, an integer that specify where the
        #     GC pointer is stored.  This is a "location" too.
        #
        # XXX the details are completely specific to X86!!!
        # a picture of the stack may help:
        #                                           ^ ^ ^
        #     |     ...      |                 to older frames
        #     +--------------+
        #     |   ret addr   |  <------ caller_frame (addr of retaddr)
        #     |     ...      |
        #     | caller frame |
        #     |     ...      |
        #     +--------------+
        #     |   ret addr   |  <------ callee_frame (addr of retaddr)
        #     |     ...      |
        #     | callee frame |
        #     |     ...      |                 lower addresses
        #     +--------------+                      v v v
        #

        retaddr = callee.frame_address.address[0]
        #
        # try to locate the caller function based on retaddr.
        #
        gcmapstart = llop.llvm_gcmapstart(llmemory.Address)
        gcmapend = llop.llvm_gcmapend(llmemory.Address)
        item = search_in_gcmap(gcmapstart, gcmapend, retaddr)
        if not item:
            # the item may have been not found because the array was
            # not sorted.  Sort it and try again.
            sort_gcmap(gcmapstart, gcmapend)
            item = search_in_gcmap(gcmapstart, gcmapend, retaddr)
            if not item:
                llop.debug_fatalerror(lltype.Void, "cannot find gc roots!")
                return False
        #
        # found!  Enumerate the GC roots in the caller frame
        #
        shape = item.signed[1]
        if shape < 0:
            shape = ~shape  # can ignore this "range" marker here
        self._shape_decompressor.setpos(shape)
        collect_stack_root = self.gcdata._gc_collect_stack_root
        gc = self.gc
        while True:
            location = self._shape_decompressor.next()
            if location == 0:
                break
            addr = self.getlocation(callee, location)
            if addr.address[0] != llmemory.NULL:
                collect_stack_root(gc, addr)
        #
        # track where the caller_frame saved the registers from its own
        # caller
        #
        reg = CALLEE_SAVED_REGS - 1
        while reg >= 0:
            location = self._shape_decompressor.next()
            addr = self.getlocation(callee, location)
            caller.regs_stored_at[reg] = addr
            reg -= 1

        location = self._shape_decompressor.next()
        caller.frame_address = self.getlocation(callee, location)
        # we get a NULL marker to mean "I'm the frame
        # of the entry point, stop walking"
        return caller.frame_address != llmemory.NULL