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