Commits

Armin Rigo committed 022708a

intermediate check-in

  • Participants
  • Parent commits f48a4df
  • Branches stm-gc-2

Comments (0)

Files changed (5)

rpython/memory/gc/stmshared.py

         self.objects_to_trace = self.AddressStack()
         #
         # The stacks...
-        self.collect_stack_roots_from_every_thread()
+        self.collect_roots_from_stacks()
+        #
+        # The raw structures...
+        self.collect_from_raw_structures()
+        #
+        # The tldicts...
+        self.collect_roots_from_tldicts()
+        #
+        self.visit_all_objects()
         #
         self.num_major_collects += 1
         debug_print("| used after collection:    ",
         debug_print("`----------------------------------------------")
         debug_stop("gc-collect")
 
-    def collect_stack_roots_from_every_thread(self):
-        self.gc.root_walker.walk_all_stack_roots(self._collect_stack_root,
-                                                 None)
+    def collect_roots_from_stacks(self):
+        self.gc.root_walker.walk_all_stack_roots(StmGCSharedArea._collect_stack_root,
+                                                 self)
 
-    def _collect_stack_root(self, ignored, root):
-        self.visit(root.address[0])
+    def collect_from_raw_structures(self):
+        self.gc.root_walker.walk_current_nongc_roots(
+            StmGCSharedArea._collect_stack_root, self)
+
+    def _collect_stack_root(self, root):
+        self.objects_to_trace.append(root.address[0])
+
+    def collect_roots_from_tldicts(self):
+        CALLBACK = self.gc.stm_operations.CALLBACK_ENUM
+        llop.nop(lltype.Void, llhelper(CALLBACK,
+                                       StmGCSharedArea._stm_enum_external_callback))
+        # The previous line causes the _stm_enum_external_callback() function to be
+        # generated in the C source with a specific signature, where it
+        # can be called by the C code.
+        stmtls = self.gc.linked_list_stmtls
+        while stmtls is not None:
+            self.visit_all_objects()   # empty the list first
+            # for every stmtls:
+            self.gc.stm_operations.tldict_enum_external(stmtls.thread_descriptor)
+            stmtls = stmtls.linked_list_next
+
+    @staticmethod
+    def _stm_enum_external_callback(globalobj, localobj):
+        localhdr = self.gc.header(localobj)
+        ll_assert(localhdr.tid & GCFLAG_VISITED != 0,
+                  "[shared] in a root: missing GCFLAG_VISITED")
+        localhdr.tid &= ~GCFLAG_VISITED
+        self.objects_to_trace.append(localobj)
+        self.objects_to_trace.append(globalobj)
+
+    def visit_all_objects(self):
+        pending = self.objects_to_trace
+        while pending.non_empty():
+            obj = pending.pop()
+            self.visit(obj)
 
     def visit(self, obj):
+        # 'obj' is a live object.  Check GCFLAG_VISITED to know if we
+        # have already seen it before.
         hdr = self.gc.header(obj)
-        XXX
+        if hdr.tid & GCFLAG_VISITED:
+            return
+        #
+        # It's the first time.  We set the flag.
+        hdr.tid |= GCFLAG_VISITED
+        #
+        # Trace the content of the object and put all objects it references
+        # into the 'objects_to_trace' list.
+        self.gc.trace(obj, self._collect_ref_rec, None)
+
+    def _collect_ref_rec(self, root, ignored):
+        self.objects_to_trace.append(root.address[0])
 
 
 # ------------------------------------------------------------

rpython/memory/gc/stmtls.py

             n = 10000 + len(StmGCTLS.nontranslated_dict)
             tlsaddr = rffi.cast(llmemory.Address, n)
             StmGCTLS.nontranslated_dict[n] = self
-        self.stm_operations.set_tls(tlsaddr)
+        self.thread_descriptor = self.stm_operations.set_tls(tlsaddr)
 
     def _unregister_with_C_code(self):
         ll_assert(self.gc.get_tls() is self,

rpython/translator/stm/src_stm/et.h

 
 extern void *pypy_g__stm_duplicate(void *);
 extern void pypy_g__stm_enum_callback(void *, void *);
-void stm_set_tls(void *newtls);
+void *stm_set_tls(void *newtls);
 void *stm_get_tls(void);
 void stm_del_tls(void);
 gcptr stm_tldict_lookup(gcptr);     /* for tests only */
 void stm_tldict_add(gcptr, gcptr);  /* for tests only */
 void stm_tldict_enum(void);
+void stm_tldict_enum_external(void *l_thread_descriptor);
 long stm_in_transaction(void);
 long stm_is_inevitable(void);
 void stm_add_atomic(long delta);

rpython/translator/stm/src_stm/rpyintf.c

 
 static __thread void *rpython_tls_object;
 
-void stm_set_tls(void *newtls)
+void *stm_set_tls(void *newtls)
 {
   rpython_tls_object = newtls;
+  return (void *)thread_descriptor;
 }
 
 void *stm_get_tls(void)
     } G2L_LOOP_END;
 }
 
+void stm_tldict_enum_external(void *l_thread_descriptor)
+{
+  struct tx_descriptor *d = (struct tx_descriptor *)l_thread_descriptor;
+  wlog_t *item;
+
+  G2L_LOOP_FORWARD(d->global_to_local, item)
+    {
+      gcptr R = item->addr;
+      gcptr L = item->val;
+      assert(L->h_revision == (revision_t)R);
+      pypy_g__stm_enum_external_callback(R, L);
+    } G2L_LOOP_END;
+}
+
 long stm_in_transaction(void)
 {
   struct tx_descriptor *d = thread_descriptor;

rpython/translator/stm/stmgcintf.py

                                      lltype.Void)
 
     # for the GC: store and read a thread-local-storage field
-    set_tls = smexternal('stm_set_tls', [llmemory.Address], lltype.Void)
+    set_tls = smexternal('stm_set_tls', [llmemory.Address], llmemory.Address)
     get_tls = smexternal('stm_get_tls', [], llmemory.Address)
     del_tls = smexternal('stm_del_tls', [], lltype.Void)
 
     # calls FindRootsForLocalCollect() and invokes for each such root
     # the callback set in CALLBACK_ENUM.
     tldict_enum = smexternal('stm_tldict_enum', [], lltype.Void)
+    tldict_enum_external = smexternal('stm_tldict_enum_external',
+                                      [llmemory.Address], lltype.Void)
 
     # sets the transaction length, after which should_break_transaction()
     # returns True