1/******************************** -*- C -*- ****************************
2 *
3 *	Object table module Inlines.
4 *
5 *
6 ***********************************************************************/
7
8/***********************************************************************
9 *
10 * Copyright 2000, 2001, 2002, 2006, 2009 Free Software Foundation, Inc.
11 * Written by Steve Byrne.
12 *
13 * This file is part of GNU Smalltalk.
14 *
15 * GNU Smalltalk is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the Free
17 * Software Foundation; either version 2, or (at your option) any later
18 * version.
19 *
20 * Linking GNU Smalltalk statically or dynamically with other modules is
21 * making a combined work based on GNU Smalltalk.  Thus, the terms and
22 * conditions of the GNU General Public License cover the whole
23 * combination.
24 *
25 * In addition, as a special exception, the Free Software Foundation
26 * give you permission to combine GNU Smalltalk with free software
27 * programs or libraries that are released under the GNU LGPL and with
28 * independent programs running under the GNU Smalltalk virtual machine.
29 *
30 * You may copy and distribute such a system following the terms of the
31 * GNU GPL for GNU Smalltalk and the licenses of the other code
32 * concerned, provided that you include the source code of that other
33 * code when and as the GNU GPL requires distribution of source code.
34 *
35 * Note that people who make modified versions of GNU Smalltalk are not
36 * obligated to grant this special exception for their modified
37 * versions; it is their choice whether to do so.  The GNU General
38 * Public License gives permission to release a modified version without
39 * this exception; this exception also makes it possible to release a
40 * modified version which carries forward this exception.
41 *
42 * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
43 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
44 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
45 * more details.
46 *
47 * You should have received a copy of the GNU General Public License along with
48 * GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
49 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
50 *
51 ***********************************************************************/
52
53static inline OOP alloc_oop (PTR obj, intptr_t flags);
54
55/* Copy the OOP object because it is part of the root set.  Integers
56   and already-copied OOPs are not processed silently.  */
57#define MAYBE_COPY_OOP(oop) do {			  \
58  if (!IS_OOP_COPIED(oop)) {				  \
59    _gst_copy_an_oop(oop);				  \
60  }							  \
61} while(0)
62
63/* Mark the OOP object because it is part of the root set.  Integers
64   and already-marked OOPs are not processed silently.  */
65#define MAYBE_MARK_OOP(oop) do {			  \
66  if (IS_OOP(oop) && !IS_OOP_MARKED(oop)) {		  \
67    _gst_mark_an_oop_internal((oop));			  \
68  }							  \
69} while(0)
70
71#define IS_OOP_COPIED(oop) \
72  (IS_INT(oop) || IS_OOP_VALID_GC (oop))
73
74#define IS_OOP_NEW(oop) \
75  (((oop)->flags & F_SPACES) != 0)
76
77/* This can only be used at the start or the end of an incremental
78   GC cycle.  */
79#define IS_OOP_VALID_GC(oop) \
80  (((oop)->flags & _gst_mem.live_flags) != 0)
81
82/* After a global GC, the live_flags say that an object is live
83   if it is marked reachable.  Old objects that have already survived
84   the incremental sweep pass, however, are not marked as reachable.  */
85#define IS_OOP_VALID(oop) \
86  ((oop)->flags & _gst_mem.live_flags \
87   || (((oop)->flags & F_OLD) \
88       && ((oop) <= _gst_mem.last_swept_oop \
89	   || (oop) > _gst_mem.next_oop_to_sweep)))
90
91#define IS_OOP_MARKED(oop) \
92  (((oop)->flags & F_REACHABLE) != 0)
93
94#define IS_OOP_FREE(oop) \
95  ((oop)->flags == 0)
96
97/* Checks to see if INDEX (a long index into the OOP table, 1 based
98   due to being called from Smalltalk via a primitive) represents a
99   valid OOP.  Returns true if so.  */
100#define OOP_INDEX_VALID(index) \
101  ((index) >= FIRST_OOP_INDEX && (index) < _gst_mem.ot_size)
102
103/* Answer the INDEX-th OOP in the table.  */
104#define OOP_AT(index) \
105  ( &_gst_mem.ot[index] )
106
107/* Answer the index of OOP in the table.  */
108#define OOP_INDEX(oop) \
109  ( (OOP)(oop) - _gst_mem.ot )
110
111/* Answer whether OOP is a builtin OOP (a Character, true, false, nil).  */
112#define IS_BUILTIN_OOP(oop) \
113  ( (OOP)(oop) - _gst_mem.ot < 0 )
114
115/* Set the indirect object pointer OOP to point to OBJ.  */
116#define SET_OOP_OBJECT(oop, obj) do {				\
117  (oop)->object = (gst_object) (obj);				\
118} while(0)
119
120/* Answer whether ADDR is part of the OOP table.  */
121#define IS_OOP_ADDR(addr)					\
122  ((OOP)(addr) >= _gst_mem.ot_base 	 			\
123    && (OOP)(addr) <= _gst_mem.last_allocated_oop		\
124    && (((intptr_t)addr & (sizeof (struct oop_s) - 1)) == 0))
125
126/* Answer whether ADDR is part of newspace.  */
127#define IS_EDEN_ADDR(addr)					\
128  ((OOP *)(addr) >= _gst_mem.eden.minPtr && 			\
129   (OOP *)(addr) < _gst_mem.eden.maxPtr)
130
131/* Answer whether ADDR is part of survivor space N.  */
132#define IS_SURVIVOR_ADDR(addr, n)				\
133  ((OOP *)(addr) >= _gst_mem.surv[(n)].minPtr && 		\
134   (OOP *)(addr) < _gst_mem.surv[(n)].maxPtr)
135
136#define INC_ADD_OOP(oop)					\
137  ((_gst_mem.inc_ptr >= _gst_mem.inc_end ?			\
138    _gst_inc_grow_registry() : (void)0),			\
139    *_gst_mem.inc_ptr++ = (oop))
140
141#define INC_SAVE_POINTER()					\
142  (_gst_mem.inc_ptr - _gst_mem.inc_base)
143
144#define INC_RESTORE_POINTER(ptr)				\
145  _gst_mem.inc_ptr = (ptr) + _gst_mem.inc_base;
146
147
148
149
150static inline void
151maybe_release_xlat (OOP oop)
152{
153#if defined(ENABLE_JIT_TRANSLATION)
154  if (oop->flags & F_XLAT)
155    {
156      if (oop->flags & F_XLAT_REACHABLE)
157	/* Reachable, and referenced by active contexts.  Keep it
158    	   around.  */
159       	oop->flags &= ~F_XLAT_2NDCHANCE;
160      else
161	{
162    	  /* Reachable, but not referenced by active contexts.  We
163    	     give it a second chance...  */
164	  if (oop->flags & F_XLAT_2NDCHANCE)
165    	    _gst_release_native_code (oop);
166
167	  oop->flags ^= F_XLAT_2NDCHANCE;
168      	}
169    }
170#endif
171}
172
173/* Given an object OBJ, allocate an OOP table slot for it and returns
174   it.  It marks the OOP so that it indicates the object is in new
175   space, and that the oop has been referenced on this pass (to keep
176   the OOP table reaper from reclaiming this OOP).  */
177static inline OOP
178alloc_oop (PTR objData, intptr_t flags)
179{
180  REGISTER (1, OOP oop);
181  REGISTER (2, OOP lastOOP);
182  oop = _gst_mem.last_swept_oop + 1;
183  lastOOP = _gst_mem.next_oop_to_sweep;
184  if (COMMON (oop <= lastOOP))
185    {
186      while (IS_OOP_VALID_GC (oop))
187	{
188	  maybe_release_xlat (oop);
189	  oop->flags &= ~F_REACHABLE;
190	  if (oop >= lastOOP)
191	    {
192	      _gst_finished_incremental_gc ();
193	      goto fast;
194	    }
195	  oop++;
196	}
197      _gst_sweep_oop (oop);
198      if (oop >= lastOOP)
199	_gst_finished_incremental_gc ();
200    }
201  else
202    while (IS_OOP_VALID_GC (oop))
203      {
204       fast:
205	oop++;
206      }
207
208  _gst_mem.last_swept_oop = oop;
209  PREFETCH_LOOP (oop, PREF_READ);
210
211  /* Force a GC as soon as possible if we're low on OOPs.  */
212  if UNCOMMON (_gst_mem.num_free_oops-- < LOW_WATER_OOP_THRESHOLD)
213    _gst_mem.eden.maxPtr = _gst_mem.eden.allocPtr;
214  if (oop > _gst_mem.last_allocated_oop)
215    _gst_mem.last_allocated_oop = oop;
216
217  oop->object = (gst_object) objData;
218  oop->flags = flags;
219  return (oop);
220}
221