+/* Mark OBJ if we can prove it's a Lisp_Object. */
+
+static INLINE void
+mark_maybe_object (obj)
+ Lisp_Object obj;
+{
+ void *po = (void *) XPNTR (obj);
+ struct mem_node *m = mem_find (po);
+
+ if (m != MEM_NIL)
+ {
+ int mark_p = 0;
+
+ switch (XGCTYPE (obj))
+ {
+ case Lisp_String:
+ mark_p = (live_string_p (m, po)
+ && !STRING_MARKED_P ((struct Lisp_String *) po));
+ break;
+
+ case Lisp_Cons:
+ mark_p = (live_cons_p (m, po)
+ && !XMARKBIT (XCONS (obj)->car));
+ break;
+
+ case Lisp_Symbol:
+ mark_p = (live_symbol_p (m, po)
+ && !XMARKBIT (XSYMBOL (obj)->plist));
+ break;
+
+ case Lisp_Float:
+ mark_p = (live_float_p (m, po)
+ && !XMARKBIT (XFLOAT (obj)->type));
+ break;
+
+ case Lisp_Vectorlike:
+ /* Note: can't check GC_BUFFERP before we know it's a
+ buffer because checking that dereferences the pointer
+ PO which might point anywhere. */
+ if (live_vector_p (m, po))
+ mark_p = (!GC_SUBRP (obj)
+ && !(XVECTOR (obj)->size & ARRAY_MARK_FLAG));
+ else if (live_buffer_p (m, po))
+ mark_p = GC_BUFFERP (obj) && !XMARKBIT (XBUFFER (obj)->name);
+ break;
+
+ case Lisp_Misc:
+ if (live_misc_p (m, po))
+ {
+ switch (XMISCTYPE (obj))
+ {
+ case Lisp_Misc_Marker:
+ mark_p = !XMARKBIT (XMARKER (obj)->chain);
+ break;
+
+ case Lisp_Misc_Buffer_Local_Value:
+ case Lisp_Misc_Some_Buffer_Local_Value:
+ mark_p = !XMARKBIT (XBUFFER_LOCAL_VALUE (obj)->realvalue);
+ break;
+
+ case Lisp_Misc_Overlay:
+ mark_p = !XMARKBIT (XOVERLAY (obj)->plist);
+ break;
+ }
+ }
+ break;
+
+ case Lisp_Int:
+ case Lisp_Type_Limit:
+ break;
+ }
+
+ if (mark_p)
+ {
+#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
+ if (nzombies < MAX_ZOMBIES)
+ zombies[nzombies] = *p;
+ ++nzombies;
+#endif
+ mark_object (&obj);
+ }
+ }
+}
+
+
+/* If P points to Lisp data, mark that as live if it isn't already
+ marked. */
+
+static INLINE void
+mark_maybe_pointer (p)
+ void *p;
+{
+ struct mem_node *m;
+
+ /* Quickly rule out some values which can't point to Lisp data. We
+ assume that Lisp data is aligned on even addresses. */
+ if ((EMACS_INT) p & 1)
+ return;
+
+ m = mem_find (p);
+ if (m != MEM_NIL)
+ {
+ Lisp_Object obj = Qnil;
+
+ switch (m->type)
+ {
+ case MEM_TYPE_NON_LISP:
+ /* Nothing to do; not a pointer to Lisp memory. */
+ break;
+
+ case MEM_TYPE_BUFFER:
+ if (live_buffer_p (m, p)
+ && !XMARKBIT (((struct buffer *) p)->name))
+ XSETVECTOR (obj, p);
+ break;
+
+ case MEM_TYPE_CONS:
+ if (live_cons_p (m, p)
+ && !XMARKBIT (((struct Lisp_Cons *) p)->car))
+ XSETCONS (obj, p);
+ break;
+
+ case MEM_TYPE_STRING:
+ if (live_string_p (m, p)
+ && !STRING_MARKED_P ((struct Lisp_String *) p))
+ XSETSTRING (obj, p);
+ break;
+
+ case MEM_TYPE_MISC:
+ if (live_misc_p (m, p))
+ {
+ Lisp_Object tem;
+ XSETMISC (tem, p);
+
+ switch (XMISCTYPE (tem))
+ {
+ case Lisp_Misc_Marker:
+ if (!XMARKBIT (XMARKER (tem)->chain))
+ obj = tem;
+ break;
+
+ case Lisp_Misc_Buffer_Local_Value:
+ case Lisp_Misc_Some_Buffer_Local_Value:
+ if (!XMARKBIT (XBUFFER_LOCAL_VALUE (tem)->realvalue))
+ obj = tem;
+ break;
+
+ case Lisp_Misc_Overlay:
+ if (!XMARKBIT (XOVERLAY (tem)->plist))
+ obj = tem;
+ break;
+ }
+ }
+ break;
+
+ case MEM_TYPE_SYMBOL:
+ if (live_symbol_p (m, p)
+ && !XMARKBIT (((struct Lisp_Symbol *) p)->plist))
+ XSETSYMBOL (obj, p);
+ break;
+
+ case MEM_TYPE_FLOAT:
+ if (live_float_p (m, p)
+ && !XMARKBIT (((struct Lisp_Float *) p)->type))
+ XSETFLOAT (obj, p);
+ break;
+
+ case MEM_TYPE_VECTOR:
+ case MEM_TYPE_PROCESS:
+ case MEM_TYPE_HASH_TABLE:
+ case MEM_TYPE_FRAME:
+ case MEM_TYPE_WINDOW:
+ if (live_vector_p (m, p))
+ {
+ Lisp_Object tem;
+ XSETVECTOR (tem, p);
+ if (!GC_SUBRP (tem)
+ && !(XVECTOR (tem)->size & ARRAY_MARK_FLAG))
+ obj = tem;
+ }
+ break;
+
+ default:
+ abort ();
+ }
+
+ if (!GC_NILP (obj))
+ mark_object (&obj);
+ }
+}
+
+
+/* Mark Lisp objects referenced from the address range START..END. */