The R Project SVN R

Rev

Rev 28254 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 r 1
/*
1160 maechler 2
 *  R : A Computer Language for Statistical Data Analysis
2 r 3
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
24516 ripley 4
 *  Copyright (C) 1998--2003  The R Development Core Team.
2 r 5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
5458 ripley 18
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
10172 luke 19
 */
11116 ripley 20
 
10172 luke 21
/*
11197 ripley 22
 *	This code implements a non-moving generational collector
11116 ripley 23
 *      with two or three generations.
1820 ihaka 24
 *
10172 luke 25
 *	Memory allocated by R_alloc is maintained in a stack.  Code
26
 *	that R_allocs memory must use vmaxget and vmaxset to obtain
27
 *	and reset the stack pointer.
28
 */
239 ihaka 29
 
10172 luke 30
#define USE_RINTERNALS
31
 
5187 hornik 32
#ifdef HAVE_CONFIG_H
7701 hornik 33
#include <config.h>
5187 hornik 34
#endif
35
 
26879 ripley 36
#if defined(Win32) && defined(LEA_MALLOC)
37
#include <stddef.h>
38
extern void *Rm_malloc(size_t n);
39
extern void *Rm_calloc(size_t n_elements, size_t element_size);
40
extern void Rm_free(void * p);
41
extern void *Rm_realloc(void * p, size_t n);
42
#define calloc Rm_calloc
43
#define malloc Rm_malloc
44
#define realloc Rm_realloc
45
#define free Rm_free
46
#endif
47
 
11510 ripley 48
#include <Defn.h>
49
#include <Graphics.h> /* display lists */
12778 pd 50
#include <Rdevices.h> /* GetDevice */
1820 ihaka 51
 
20094 ripley 52
/* malloc uses size_t.  We are assuming here that size_t is at least
53
   as large as unsigned long.  Changed from int at 1.6.0 to (i) allow
54
   2-4Gb objects on 32-bit system and (ii) objects limited only by
55
   length on a 64-bit system.
56
*/
57
 
2 r 58
static int gc_reporting = 0;
1858 ihaka 59
static int gc_count = 0;
1160 maechler 60
 
2512 pd 61
#define GC_TORTURE
2100 pd 62
 
63
#ifdef GC_TORTURE
11116 ripley 64
# define FORCE_GC !gc_inhibit_torture
2437 maechler 65
#else
11116 ripley 66
# define FORCE_GC 0
2100 pd 67
#endif
68
 
2754 pd 69
extern SEXP framenames;
2100 pd 70
 
71
#define GC_PROT(X) {int __t = gc_inhibit_torture; \
72
	gc_inhibit_torture = 1 ; X ; gc_inhibit_torture = __t;}
73
 
20094 ripley 74
static void R_gc_internal(R_size_t size_needed);
75
static void mem_err_heap(R_size_t size);
2 r 76
 
10172 luke 77
static SEXPREC UnmarkedNodeTemplate;
78
#define NODE_IS_MARKED(s) (MARK(s)==1)
79
#define MARK_NODE(s) (MARK(s)=1)
80
#define UNMARK_NODE(s) (MARK(s)=0)
1820 ihaka 81
 
10172 luke 82
 
83
/* Tuning Constants. Most of these could be made settable from R,
84
   within some reasonable constraints at least.  Since there are quite
85
   a lot of constants it would probably make sense to put together
86
   several "packages" representing different space/speed tradeoffs
87
   (e.g. very aggressive freeing and small increments to conserve
88
   memory; much less frequent releasing and larger increments to
89
   increase speed). */
90
 
91
/* There are three levels of collections.  Level 0 collects only the
92
   youngest generation, level 1 collects the two youngest generations,
93
   and level 2 collects all generations.  Higher level collections
94
   occur at least after specified numbers of lower level ones.  After
95
   LEVEL_0_FREQ level zero collections a level 1 collection is done;
96
   after every LEVEL_1_FREQ level 1 collections a level 2 collection
97
   occurs.  Thus, roughly, every LEVEL_0_FREQ-th collection is a level
98
   1 collection and every (LEVEL_0_FREQ * LEVEL_1_FREQ)-th collection
99
   is a level 2 collection.  */
100
#define LEVEL_0_FREQ 20
101
#define LEVEL_1_FREQ 5
102
static int collect_counts_max[] = { LEVEL_0_FREQ, LEVEL_1_FREQ };
103
 
104
/* When a level N collection fails to produce at least MinFreeFrac *
11135 luke 105
   R_NSize free nodes and MinFreeFrac * R_VSize free vector space, the
106
   next collection will be a level N + 1 collection.
107
 
108
   This constant is also used in heap size adjustment as a minimal
109
   fraction of the minimal heap size levels that should be available
110
   for allocation. */
10172 luke 111
static double R_MinFreeFrac = 0.2;
112
 
113
/* When pages are released, a number of free nodes equal to
114
   R_MaxKeepFrac times the number of allocated nodes for each class is
115
   retained.  Pages not needed to meet this requirement are released.
116
   An attempt to release pages is made every R_PageReleaseFreq level 1
117
   or level 2 collections. */
118
static double R_MaxKeepFrac = 0.5;
119
static int R_PageReleaseFreq = 1;
120
 
121
/* The heap size constants R_NSize and R_VSize are used for triggering
122
   collections.  The initial values set by defaults or command line
123
   arguments are used as minimal values.  After full collections these
11135 luke 124
   levels are adjusted up or down, though not below the minimal values
125
   or above the maximum values, towards maintain heap occupancy within
126
   a specified range.  When the number of nodes in use reaches
127
   R_NGrowFrac * R_NSize, the value of R_NSize is incremented by
128
   R_NGrowIncrMin + R_NGrowIncrFrac * R_NSize.  When the number of
129
   nodes in use falls below R_NShrinkFrac, R_NSize is decremented by
130
   R_NShrinkIncrMin * R_NShrinkFrac * R_NSize.  Analogous adjustments
11197 ripley 131
   are made to R_VSize.
11135 luke 132
 
133
   This mechanism for adjusting the heap size constants is very
134
   primitive but hopefully adequate for now.  Some modeling and
135
   experimentation would be useful.  We want the heap sizes to get set
136
   at levels adequate for the current computations.  The present
137
   mechanism uses only the size of the current live heap to provide
138
   information about the current needs; since the current live heap
139
   size can be very volatile, the adjustment mechanism only makes
140
   gradual adjustments.  A more sophisticated strategy would use more
141
   of the live heap history. */
10172 luke 142
static double R_NGrowFrac = 0.70;
143
static double R_NShrinkFrac = 0.30;
144
 
145
static double R_VGrowFrac = 0.70;
146
static double R_VShrinkFrac = 0.30;
147
 
11135 luke 148
#ifdef SMALL_MEMORY
149
/* On machines with only 32M of memory (or on a classic Mac OS port)
150
   it might be a good idea to use settings like these that are more
151
   aggressive at keeping memory usage down. */
152
static double R_NGrowIncrFrac = 0.0, R_NShrinkIncrFrac = 0.2;
153
static int R_NGrowIncrMin = 50000, R_NShrinkIncrMin = 0;
154
static double R_VGrowIncrFrac = 0.0, R_VShrinkIncrFrac = 0.2;
155
static int R_VGrowIncrMin = 100000, R_VShrinkIncrMin = 0;
156
#else
157
static double R_NGrowIncrFrac = 0.05, R_NShrinkIncrFrac = 0.2;
158
static int R_NGrowIncrMin = 40000, R_NShrinkIncrMin = 0;
159
static double R_VGrowIncrFrac = 0.05, R_VShrinkIncrFrac = 0.2;
160
static int R_VGrowIncrMin = 80000, R_VShrinkIncrMin = 0;
161
#endif
162
 
10172 luke 163
/* Maximal Heap Limits.  These variables contain upper limits on the
164
   heap sizes.  They could be made adjustable from the R level,
20094 ripley 165
   perhaps by a handler for a recoverable error.
11135 luke 166
 
167
   Access to these values is provided with reader and writer
168
   functions; the writer function insures that the maximal values are
169
   never set below the current ones. */
20094 ripley 170
static R_size_t R_MaxVSize = R_SIZE_T_MAX;
171
static R_size_t R_MaxNSize = R_SIZE_T_MAX;
11197 ripley 172
static int vsfac = 1; /* current units for vsize: changes at initialization */
10172 luke 173
 
20094 ripley 174
R_size_t R_GetMaxVSize(void) 
11197 ripley 175
{
20094 ripley 176
    if (R_MaxVSize == R_SIZE_T_MAX) return R_SIZE_T_MAX;
11197 ripley 177
    return R_MaxVSize*vsfac;
178
}
11135 luke 179
 
20094 ripley 180
void R_SetMaxVSize(R_size_t size)
11197 ripley 181
{
20094 ripley 182
    if (size == R_SIZE_T_MAX) return;
11297 luke 183
    if (size / vsfac >= R_VSize) R_MaxVSize = (size+1)/sizeof(VECREC);
11197 ripley 184
}
11135 luke 185
 
20094 ripley 186
R_size_t R_GetMaxNSize(void) 
11197 ripley 187
{ 
188
    return R_MaxNSize;
189
}
11135 luke 190
 
20094 ripley 191
void R_SetMaxNSize(R_size_t size)
11197 ripley 192
{
193
    if (size >= R_NSize) R_MaxNSize = size;
194
}
195
 
27067 ripley 196
void R_SetPPSize(unsigned long size)
197
{
198
    R_PPStackSize = size;
199
}
11197 ripley 200
 
10172 luke 201
/* Miscellaneous Globals. */
202
 
203
static SEXP R_VStack = NULL;		/* R_alloc stack pointer */
20094 ripley 204
static R_size_t R_LargeVallocSize = 0;
205
static R_size_t R_SmallVallocSize = 0;
206
static R_size_t orig_R_NSize;
207
static R_size_t orig_R_VSize;
10172 luke 208
 
209
 
210
/* Node Classes.  Non-vector nodes are of class zero. Small vector
211
   nodes are in classes 1, ..., NUM_SMALL_NODE_CLASSES, and large
212
   vector nodes are in class LARGE_NODE_CLASS.  For vector nodes the
213
   node header is followed in memory by the vector data, offset from
214
   the header by SEXPREC_ALIGN. */
215
 
216
#define NUM_NODE_CLASSES 8
217
 
218
/* sxpinfo allocates 3 bits for the node class, so at most 8 are allowed */
219
#if NUM_NODE_CLASSES > 8
11116 ripley 220
# error NUM_NODE_CLASSES must be at most 8
10172 luke 221
#endif
222
 
223
#define LARGE_NODE_CLASS (NUM_NODE_CLASSES - 1)
224
#define NUM_SMALL_NODE_CLASSES (NUM_NODE_CLASSES - 1)
225
 
226
/* the number of VECREC's in nodes of the small node classes */
227
static int NodeClassSize[NUM_SMALL_NODE_CLASSES] = { 0, 1, 2, 4, 6, 8, 16 };
228
 
229
#define NODE_CLASS(s) ((s)->sxpinfo.gccls)
230
#define SET_NODE_CLASS(s,v) (((s)->sxpinfo.gccls) = (v))
231
 
232
 
233
/* Node Generations. */
234
 
235
#define NUM_OLD_GENERATIONS 2
236
 
237
/* sxpinfo allocates one bit for the old generation count, so only 1
238
   or 2 is allowed */
239
#if NUM_OLD_GENERATIONS > 2 || NUM_OLD_GENERATIONS < 1
11116 ripley 240
# error number of old generations must be 1 or 2
10172 luke 241
#endif
242
 
243
#define NODE_GENERATION(s) ((s)->sxpinfo.gcgen)
244
#define SET_NODE_GENERATION(s,g) ((s)->sxpinfo.gcgen=(g))
245
 
246
#define NODE_GEN_IS_YOUNGER(s,g) \
247
  (! NODE_IS_MARKED(s) || NODE_GENERATION(s) < (g))
248
#define NODE_IS_OLDER(x, y) \
249
  (NODE_IS_MARKED(x) && \
250
   (! NODE_IS_MARKED(y) || NODE_GENERATION(x) > NODE_GENERATION(y)))
251
 
252
static int num_old_gens_to_collect = 0;
253
static int gen_gc_counts[NUM_OLD_GENERATIONS + 1];
254
static int collect_counts[NUM_OLD_GENERATIONS];
255
 
256
 
257
/* Node Pages.  Non-vector nodes and small vector nodes are allocated
258
   from fixed size pages.  The pages for each node class are kept in a
259
   linked list. */
260
 
261
typedef union PAGE_HEADER {
262
  union PAGE_HEADER *next;
263
  double align;
264
} PAGE_HEADER;
265
 
266
#define BASE_PAGE_SIZE 2000
10286 luke 267
#define R_PAGE_SIZE \
10172 luke 268
  (((BASE_PAGE_SIZE - sizeof(PAGE_HEADER)) / sizeof(SEXPREC)) \
269
   * sizeof(SEXPREC) \
270
   + sizeof(PAGE_HEADER))
271
#define NODE_SIZE(c) \
272
  ((c) == 0 ? sizeof(SEXPREC) : \
273
   sizeof(SEXPREC_ALIGN) + NodeClassSize[c] * sizeof(VECREC))
274
 
275
#define PAGE_DATA(p) ((void *) (p + 1))
276
#define VHEAP_FREE() (R_VSize - R_LargeVallocSize - R_SmallVallocSize)
277
 
278
 
279
/* The Heap Structure.  Nodes for each class/generation combination
280
   are arranged in circular doubly-linked lists.  The double linking
281
   allows nodes to be removed in constant time; this is used by the
282
   collector to move reachable nodes out of free space and into the
283
   appropriate generation.  The circularity eliminates the need for
284
   end checks.  In addition, each link is anchored at an artificial
285
   node, the Peg SEXPREC's in the structure below, which simplifies
286
   pointer maintenance.  The circular doubly-linked arrangement is
287
   taken from Baker's in-place incremental collector design; see
288
   ftp://ftp.netcom.com/pub/hb/hbaker/NoMotionGC.html or the Jones and
289
   Lins GC book.  The linked lists are implemented by adding two
290
   pointer fields to the SEXPREC structure, which increases its size
291
   from 5 to 7 words. Other approaches are possible but don't seem
292
   worth pursuing for R.
293
 
294
   There are two options for dealing with old-to-new pointers.  The
295
   first option is to make sure they never occur by transferring all
296
   referenced younger objects to the generation of the referrer when a
297
   reference to a newer object is assigned to an older one.  This is
298
   enabled by defining EXPEL_OLD_TO_NEW.  The second alternative is to
299
   keep track of all nodes that may contain references to newer nodes
300
   and to "age" the nodes they refer to at the beginning of each
301
   collection.  This is the default.  The first option is simpler in
302
   some ways, but will create more floating garbage and add a bit to
303
   the execution time, though the difference is probably marginal on
304
   both counts.*/
305
/*#define EXPEL_OLD_TO_NEW*/
306
static struct {
11116 ripley 307
    SEXP Old[NUM_OLD_GENERATIONS], New, Free;
308
    SEXPREC OldPeg[NUM_OLD_GENERATIONS], NewPeg;
10172 luke 309
#ifndef EXPEL_OLD_TO_NEW
11116 ripley 310
    SEXP OldToNew[NUM_OLD_GENERATIONS];
311
    SEXPREC OldToNewPeg[NUM_OLD_GENERATIONS];
10172 luke 312
#endif
11116 ripley 313
    int OldCount[NUM_OLD_GENERATIONS], AllocCount, PageCount;
314
    PAGE_HEADER *pages;
10172 luke 315
} R_GenHeap[NUM_NODE_CLASSES];
316
 
20094 ripley 317
static R_size_t R_NodesInUse = 0;
10172 luke 318
 
319
#define NEXT_NODE(s) (s)->gengc_next_node
320
#define PREV_NODE(s) (s)->gengc_prev_node
321
#define SET_NEXT_NODE(s,t) (NEXT_NODE(s) = (t))
322
#define SET_PREV_NODE(s,t) (PREV_NODE(s) = (t))
323
 
324
 
325
/* Node List Manipulation */
326
 
327
/* unsnap node s from its list */
328
#define UNSNAP_NODE(s) do { \
329
  SEXP un__n__ = (s); \
330
  SEXP next = NEXT_NODE(un__n__); \
331
  SEXP prev = PREV_NODE(un__n__); \
332
  SET_NEXT_NODE(prev, next); \
333
  SET_PREV_NODE(next, prev); \
334
} while(0)
335
 
336
/* snap in node s before node t */
337
#define SNAP_NODE(s,t) do { \
338
  SEXP sn__n__ = (s); \
339
  SEXP next = (t); \
340
  SEXP prev = PREV_NODE(next); \
341
  SET_NEXT_NODE(sn__n__, next); \
342
  SET_PREV_NODE(next, sn__n__); \
343
  SET_NEXT_NODE(prev, sn__n__); \
344
  SET_PREV_NODE(sn__n__, prev); \
345
} while (0)
346
 
347
/* move all nodes on from_peg to to_peg */
348
#define BULK_MOVE(from_peg,to_peg) do { \
349
  SEXP __from__ = (from_peg); \
350
  SEXP __to__ = (to_peg); \
351
  SEXP first_old = NEXT_NODE(__from__); \
352
  SEXP last_old = PREV_NODE(__from__); \
353
  SEXP first_new = NEXT_NODE(__to__); \
354
  SET_PREV_NODE(first_old, __to__); \
355
  SET_NEXT_NODE(__to__, first_old); \
356
  SET_PREV_NODE(first_new, last_old); \
357
  SET_NEXT_NODE(last_old, first_new); \
358
  SET_NEXT_NODE(__from__, __from__); \
359
  SET_PREV_NODE(__from__, __from__); \
360
} while (0);
361
 
362
 
363
/* Processing Node Children */
364
 
365
/* This macro calls dc__action__ for each child of __n__, passing
366
   dc__extra__ as a second argument for each call. */
367
#define DO_CHILDREN(__n__,dc__action__,dc__extra__) do { \
368
  if (ATTRIB(__n__) != R_NilValue) \
369
    dc__action__(ATTRIB(__n__), dc__extra__); \
370
  switch (TYPEOF(__n__)) { \
371
  case NILSXP: \
372
  case BUILTINSXP: \
373
  case SPECIALSXP: \
374
  case CHARSXP: \
375
  case LGLSXP: \
376
  case INTSXP: \
377
  case REALSXP: \
378
  case CPLXSXP: \
15928 luke 379
  case WEAKREFSXP: \
10172 luke 380
    break; \
381
  case STRSXP: \
382
  case EXPRSXP: \
383
  case VECSXP: \
384
    { \
385
      int i; \
386
      for (i = 0; i < LENGTH(__n__); i++) \
387
        dc__action__(STRING_ELT(__n__, i), dc__extra__); \
388
    } \
389
    break; \
390
  case ENVSXP: \
391
    dc__action__(FRAME(__n__), dc__extra__); \
392
    dc__action__(ENCLOS(__n__), dc__extra__); \
393
    dc__action__(HASHTAB(__n__), dc__extra__); \
394
    break; \
395
  case CLOSXP: \
396
  case PROMSXP: \
397
  case LISTSXP: \
398
  case LANGSXP: \
399
  case DOTSXP: \
400
  case SYMSXP: \
26045 luke 401
  case BCODESXP: \
10172 luke 402
    dc__action__(TAG(__n__), dc__extra__); \
403
    dc__action__(CAR(__n__), dc__extra__); \
404
    dc__action__(CDR(__n__), dc__extra__); \
405
    break; \
11390 luke 406
  case EXTPTRSXP: \
407
    dc__action__(EXTPTR_PROT(__n__), dc__extra__); \
408
    dc__action__(EXTPTR_TAG(__n__), dc__extra__); \
409
    break; \
10172 luke 410
  default: \
411
    abort(); \
412
  } \
413
} while(0)
414
 
415
 
416
/* Forwarding Nodes.  These macros mark nodes or chindren of nodes and
417
   place them on the forwarding list.  The forwarding list is assumed
418
   to be in a local variable of the caller named named
419
   forwarded_nodes. */
420
 
421
#define FORWARD_NODE(s) do { \
422
  SEXP fn__n__ = (s); \
423
  if (fn__n__ && ! NODE_IS_MARKED(fn__n__)) { \
424
    MARK_NODE(fn__n__); \
425
    UNSNAP_NODE(fn__n__); \
426
    SET_NEXT_NODE(fn__n__, forwarded_nodes); \
427
    forwarded_nodes = fn__n__; \
428
  } \
429
} while (0)
430
 
431
#define FC_FORWARD_NODE(__n__,__dummy__) FORWARD_NODE(__n__)
432
#define FORWARD_CHILDREN(__n__) DO_CHILDREN(__n__,FC_FORWARD_NODE, 0)
433
 
434
 
435
/* Node Allocation. */
436
 
437
#define CLASS_GET_FREE_NODE(c,s) do { \
438
  SEXP __n__ = R_GenHeap[c].Free; \
439
  if (__n__ == R_GenHeap[c].New) { \
440
    GetNewPage(c); \
441
    __n__ = R_GenHeap[c].Free; \
442
  } \
443
  R_GenHeap[c].Free = NEXT_NODE(__n__); \
444
  R_NodesInUse++; \
445
  (s) = __n__; \
446
} while (0)
447
 
448
#define NO_FREE_NODES() (R_NodesInUse >= R_NSize)
449
#define GET_FREE_NODE(s) CLASS_GET_FREE_NODE(0,s)
450
 
451
 
452
/* Debugging Routines. */
453
 
454
#ifdef DEBUG_GC
455
static void CheckNodeGeneration(SEXP x, int g)
456
{
11116 ripley 457
    if (NODE_GENERATION(x) < g) {
458
	REprintf("untraced old-to-new reference\n");
459
    }
10172 luke 460
}
461
 
462
static void DEBUG_CHECK_NODE_COUNTS(char *where)
463
{
11116 ripley 464
    int i, OldCount, NewCount, OldToNewCount, gen;
465
    SEXP s;
10172 luke 466
 
11116 ripley 467
    REprintf("Node counts %s:\n", where);
468
    for (i = 0; i < NUM_NODE_CLASSES; i++) {
469
	for (s = NEXT_NODE(R_GenHeap[i].New), NewCount = 0;
470
	     s != R_GenHeap[i].New;
471
	     s = NEXT_NODE(s)) {
472
	    NewCount++;
473
	    if (i != NODE_CLASS(s))
474
		REprintf("Inconsistent class assignment for node!\n");
475
	}
476
	for (gen = 0, OldCount = 0, OldToNewCount = 0;
477
	     gen < NUM_OLD_GENERATIONS;
478
	     gen++) {
479
	    for (s = NEXT_NODE(R_GenHeap[i].Old[gen]);
480
		 s != R_GenHeap[i].Old[gen];
481
		 s = NEXT_NODE(s)) {
482
		OldCount++;
483
		if (i != NODE_CLASS(s))
484
		    REprintf("Inconsistent class assignment for node!\n");
485
		if (gen != NODE_GENERATION(s))
486
		    REprintf("Inconsistent node generation\n");
487
		DO_CHILDREN(s, CheckNodeGeneration, gen);
488
	    }
489
	    for (s = NEXT_NODE(R_GenHeap[i].OldToNew[gen]);
490
		 s != R_GenHeap[i].OldToNew[gen];
491
		 s = NEXT_NODE(s)) {
492
		OldToNewCount++;
493
		if (i != NODE_CLASS(s))
494
		    REprintf("Inconsistent class assignment for node!\n");
495
		if (gen != NODE_GENERATION(s))
496
		    REprintf("Inconsistent node generation\n");
497
	    }
498
	}
499
	REprintf("Class: %d, New = %d, Old = %d, OldToNew = %d, Total = %d\n",
500
		 i,
501
		 NewCount, OldCount, OldToNewCount,
502
		 NewCount + OldCount + OldToNewCount);
10172 luke 503
    }
504
}
505
 
506
static void DEBUG_GC_SUMMARY(int full_gc)
507
{
11116 ripley 508
    int i, gen, OldCount;
20094 ripley 509
    REprintf("\n%s, VSize = %lu", full_gc ? "Full" : "Minor",
11116 ripley 510
	     R_SmallVallocSize + R_LargeVallocSize);
511
    for (i = 1; i < NUM_NODE_CLASSES; i++) {
512
	for (gen = 0, OldCount = 0; gen < NUM_OLD_GENERATIONS; gen++)
513
	    OldCount += R_GenHeap[i].OldCount[gen];
514
	REprintf(", class %d: %d", i, OldCount);
515
    }
10172 luke 516
}
517
#else
518
#define DEBUG_CHECK_NODE_COUNTS(s)
519
#define DEBUG_GC_SUMMARY(x)
11116 ripley 520
#endif /* DEBUG_GC */
10172 luke 521
 
522
#ifdef DEBUG_ADJUST_HEAP
523
static void DEBUG_ADJUST_HEAP_PRINT(double node_occup, double vect_occup)
524
{
11116 ripley 525
    int i;
20094 ripley 526
    R_size_t alloc;
11116 ripley 527
    REprintf("Node occupancy: %.0f%%\nVector occupancy: %.0f%%\n",
528
	     100.0 * node_occup, 100.0 * vect_occup);
529
    alloc = R_LargeVallocSize +
530
	sizeof(SEXPREC_ALIGN) * R_GenHeap[LARGE_NODE_CLASS].AllocCount;
531
    for (i = 0; i < NUM_SMALL_NODE_CLASSES; i++)
532
	alloc += R_PAGE_SIZE * R_GenHeap[i].PageCount;
20094 ripley 533
    REprintf("Total allocation: %lu\n", alloc);
534
    REprintf("Ncells %lu\nVcells %lu\n", R_NSize, R_VSize);
10172 luke 535
}
536
#else
537
#define DEBUG_ADJUST_HEAP_PRINT(node_occup, vect_occup)
11116 ripley 538
#endif /* DEBUG_ADJUST_HEAP */
10172 luke 539
 
11116 ripley 540
#ifdef DEBUG_RELEASE_MEM
10172 luke 541
static void DEBUG_RELEASE_PRINT(int rel_pages, int maxrel_pages, int i)
542
{
11116 ripley 543
    if (maxrel_pages > 0) {
544
	int gen, n;
545
	REprintf("Class: %d, pages = %d, maxrel = %d, released = %d\n", i,
546
		 R_GenHeap[i].PageCount, maxrel_pages, rel_pages);
547
	for (gen = 0, n = 0; gen < NUM_OLD_GENERATIONS; gen++)
548
	    n += R_GenHeap[i].OldCount[gen];
549
	REprintf("Allocated = %d, in use = %d\n", R_GenHeap[i].AllocCount, n);
550
    }
10172 luke 551
}
552
#else
553
#define DEBUG_RELEASE_PRINT(rel_pages, maxrel_pages, i)
11116 ripley 554
#endif /* DEBUG_RELEASE_MEM */
10172 luke 555
 
556
 
557
/* Page Allocation and Release. */
558
 
559
static void GetNewPage(int node_class)
560
{
11116 ripley 561
    SEXP s, base;
562
    char *data;
563
    PAGE_HEADER *page;
564
    int node_size, page_count, i;
10172 luke 565
 
11116 ripley 566
    node_size = NODE_SIZE(node_class);
567
    page_count = (R_PAGE_SIZE - sizeof(PAGE_HEADER)) / node_size;
10407 maechler 568
 
11116 ripley 569
    page = malloc(R_PAGE_SIZE);
570
    if (page == NULL)
20094 ripley 571
	mem_err_heap((R_size_t) NodeClassSize[node_class]);
11116 ripley 572
    page->next = R_GenHeap[node_class].pages;
573
    R_GenHeap[node_class].pages = page;
574
    R_GenHeap[node_class].PageCount++;
10172 luke 575
 
11116 ripley 576
    data = PAGE_DATA(page);
577
    base = R_GenHeap[node_class].New;
578
    for (i = 0; i < page_count; i++, data += node_size) {
579
	s = (SEXP) data;
580
	R_GenHeap[node_class].AllocCount++;
581
	SNAP_NODE(s, base);
582
	s->sxpinfo = UnmarkedNodeTemplate.sxpinfo;
583
	SET_NODE_CLASS(s, node_class);
584
	base = s;
585
	R_GenHeap[node_class].Free = s;
586
    }
10172 luke 587
}
588
 
589
static void ReleasePage(PAGE_HEADER *page, int node_class)
590
{
11116 ripley 591
    SEXP s;
592
    char *data;
593
    int node_size, page_count, i;
10172 luke 594
 
11116 ripley 595
    node_size = NODE_SIZE(node_class);
596
    page_count = (R_PAGE_SIZE - sizeof(PAGE_HEADER)) / node_size;
597
    data = PAGE_DATA(page);
10172 luke 598
 
11116 ripley 599
    for (i = 0; i < page_count; i++, data += node_size) {
600
	s = (SEXP) data;
601
	UNSNAP_NODE(s);
602
	R_GenHeap[node_class].AllocCount--;
603
    }
604
    R_GenHeap[node_class].PageCount--;
605
    free(page);
10172 luke 606
}
607
 
608
static void TryToReleasePages(void)
609
{
11116 ripley 610
    SEXP s;
611
    int i;
612
    static int release_count = 0;
10172 luke 613
 
11116 ripley 614
    if (release_count == 0) {
615
	release_count = R_PageReleaseFreq;
616
	for (i = 0; i < NUM_SMALL_NODE_CLASSES; i++) {
617
	    int pages_free = 0;
618
	    PAGE_HEADER *page, *last, *next;
619
	    int node_size = NODE_SIZE(i);
620
	    int page_count = (R_PAGE_SIZE - sizeof(PAGE_HEADER)) / node_size;
621
	    int maxrel, maxrel_pages, rel_pages, gen;
10172 luke 622
 
11116 ripley 623
	    maxrel = R_GenHeap[i].AllocCount;
624
	    for (gen = 0; gen < NUM_OLD_GENERATIONS; gen++)
625
		maxrel -= (1.0 + R_MaxKeepFrac) * R_GenHeap[i].OldCount[gen];
626
	    maxrel_pages = maxrel > 0 ? maxrel / page_count : 0;
10407 maechler 627
 
11116 ripley 628
	    /* all nodes in New space should be both free and unmarked */
629
	    for (page = R_GenHeap[i].pages, rel_pages = 0, last = NULL;
630
		 rel_pages < maxrel_pages && page != NULL;) {
631
		int j, in_use;
632
		char *data = PAGE_DATA(page);
10172 luke 633
 
11116 ripley 634
		next = page->next;
11197 ripley 635
		for (in_use = 0, j = 0; j < page_count;
11116 ripley 636
		     j++, data += node_size) {
637
		    s = (SEXP) data;
638
		    if (NODE_IS_MARKED(s)) {
639
			in_use = 1;
640
			break;
641
		    }
642
		}
643
		if (! in_use) {
644
		    ReleasePage(page, i);
645
		    if (last == NULL)
646
			R_GenHeap[i].pages = next;
647
		    else
648
			last->next = next;
649
		    pages_free++;
650
		    rel_pages++;
651
		}
652
		else last = page;
653
		page = next;
654
	    }
655
	    DEBUG_RELEASE_PRINT(rel_pages, maxrel_pages, i);
656
	    R_GenHeap[i].Free = NEXT_NODE(R_GenHeap[i].New);
10172 luke 657
	}
658
    }
11116 ripley 659
    else release_count--;
10172 luke 660
}
661
 
662
static void ReleaseLargeFreeVectors(void)
663
{
11116 ripley 664
    SEXP s = NEXT_NODE(R_GenHeap[LARGE_NODE_CLASS].New);
665
    while (s != R_GenHeap[LARGE_NODE_CLASS].New) {
666
	SEXP next = NEXT_NODE(s);
667
	if (CHAR(s) != NULL) {
20094 ripley 668
	    R_size_t size;
11116 ripley 669
	    switch (TYPEOF(s)) {	/* get size in bytes */
670
	    case CHARSXP:
671
		size = LENGTH(s) + 1;
672
		break;
673
	    case LGLSXP:
674
	    case INTSXP:
675
		size = LENGTH(s) * sizeof(int);
676
		break;
677
	    case REALSXP:
678
		size = LENGTH(s) * sizeof(double);
679
		break;
680
	    case CPLXSXP:
681
		size = LENGTH(s) * sizeof(Rcomplex);
682
		break;
683
	    case STRSXP:
684
	    case EXPRSXP:
685
	    case VECSXP:
686
		size = LENGTH(s) * sizeof(SEXP);
687
		break;
688
	    default:
689
		abort();
690
	    }
691
	    size = BYTE2VEC(size);
692
	    UNSNAP_NODE(s);
693
	    R_LargeVallocSize -= size;
694
	    R_GenHeap[LARGE_NODE_CLASS].AllocCount--;
695
	    free(s);
696
	}
697
	s = next;
10172 luke 698
    }
699
}
700
 
701
 
702
/* Heap Size Adjustment. */
703
 
20094 ripley 704
static void AdjustHeapSize(R_size_t size_needed)
10172 luke 705
{
20094 ripley 706
    R_size_t R_MinNFree = orig_R_NSize * R_MinFreeFrac;
707
    R_size_t R_MinVFree = orig_R_VSize * R_MinFreeFrac;
708
    R_size_t NNeeded = R_NodesInUse + R_MinNFree;
709
    R_size_t VNeeded = R_SmallVallocSize + R_LargeVallocSize
11135 luke 710
	+ size_needed + R_MinVFree;
711
    double node_occup = ((double) NNeeded) / R_NSize;
712
    double vect_occup =	((double) VNeeded) / R_VSize;
10172 luke 713
 
11116 ripley 714
    if (node_occup > R_NGrowFrac) {
20094 ripley 715
	R_size_t change = R_NGrowIncrMin + R_NGrowIncrFrac * R_NSize;
716
	if (R_MaxNSize >= R_NSize + change)
11135 luke 717
	    R_NSize += change;
11116 ripley 718
    }
719
    else if (node_occup < R_NShrinkFrac) {
20094 ripley 720
	R_NSize -= (R_NShrinkIncrMin + R_NShrinkIncrFrac * R_NSize);
11135 luke 721
	if (R_NSize < NNeeded)
11197 ripley 722
	    R_NSize = (NNeeded < R_MaxNSize) ? NNeeded: R_MaxNSize;
11116 ripley 723
	if (R_NSize < orig_R_NSize)
724
	    R_NSize = orig_R_NSize;
725
    }
10172 luke 726
 
11297 luke 727
    if (vect_occup > 1.0 && VNeeded < R_MaxVSize)
728
	R_VSize = VNeeded;
11135 luke 729
    if (vect_occup > R_VGrowFrac) {
20094 ripley 730
	R_size_t change = R_VGrowIncrMin + R_VGrowIncrFrac * R_NSize;
11135 luke 731
	if (R_MaxVSize - R_VSize >= change)
732
	    R_VSize += change;
11116 ripley 733
    }
734
    else if (vect_occup < R_VShrinkFrac) {
11135 luke 735
	R_VSize -= R_VShrinkIncrMin + R_VShrinkIncrFrac * R_VSize;
736
	if (R_VSize < VNeeded)
737
	    R_VSize = VNeeded;
11116 ripley 738
	if (R_VSize < orig_R_VSize)
739
	    R_VSize = orig_R_VSize;
740
    }
10172 luke 741
 
11116 ripley 742
    DEBUG_ADJUST_HEAP_PRINT(node_occup, vect_occup);
10172 luke 743
}
744
 
745
 
746
/* Managing Old-to-New References. */
747
 
748
#define AGE_NODE(s,g) do { \
749
  SEXP an__n__ = (s); \
750
  int an__g__ = (g); \
751
  if (an__n__ && NODE_GEN_IS_YOUNGER(an__n__, an__g__)) { \
752
    if (NODE_IS_MARKED(an__n__)) \
753
       R_GenHeap[NODE_CLASS(an__n__)].OldCount[NODE_GENERATION(an__n__)]--; \
754
    else \
755
      MARK_NODE(an__n__); \
756
    SET_NODE_GENERATION(an__n__, an__g__); \
757
    UNSNAP_NODE(an__n__); \
758
    SET_NEXT_NODE(an__n__, forwarded_nodes); \
759
    forwarded_nodes = an__n__; \
760
  } \
761
} while (0)
762
 
763
static void AgeNodeAndChildren(SEXP s, int gen)
764
{
11116 ripley 765
    SEXP forwarded_nodes = NULL;
766
    AGE_NODE(s, gen);
767
    while (forwarded_nodes != NULL) {
13600 maechler 768
	s = forwarded_nodes;
11116 ripley 769
	forwarded_nodes = NEXT_NODE(forwarded_nodes);
770
	if (NODE_GENERATION(s) != gen)
771
	    REprintf("****snapping into wrong generation\n");
772
	SNAP_NODE(s, R_GenHeap[NODE_CLASS(s)].Old[gen]);
773
	R_GenHeap[NODE_CLASS(s)].OldCount[gen]++;
774
	DO_CHILDREN(s, AGE_NODE, gen);
775
    }
10172 luke 776
}
777
 
778
static void old_to_new(SEXP x, SEXP y)
779
{
780
#ifdef EXPEL_OLD_TO_NEW
11116 ripley 781
    AgeNodeAndChildren(y, NODE_GENERATION(x));
10172 luke 782
#else
11116 ripley 783
    UNSNAP_NODE(x);
784
    SNAP_NODE(x, R_GenHeap[NODE_CLASS(x)].OldToNew[NODE_GENERATION(x)]);
10172 luke 785
#endif
786
}
787
 
788
#define CHECK_OLD_TO_NEW(x,y) do { \
789
  if (NODE_IS_OLDER(x, y)) old_to_new(x,y);  } while (0)
790
 
791
 
10930 luke 792
/* Node Sorting.  SortNodes attempts to improve locality of reference
11116 ripley 793
   by rearranging the free list to place nodes on the same place page
794
   together and order nodes within pages.  This involves a sweep of the
795
   heap, so it should not be done too often, but doing it at least
796
   occasionally does seem essential.  Sorting on each full colllection is
11197 ripley 797
   probably sufficient.
11116 ripley 798
*/
799
 
10930 luke 800
#define SORT_NODES
10172 luke 801
#ifdef SORT_NODES
802
static void SortNodes(void)
803
{
11116 ripley 804
    SEXP s;
805
    int i;
10172 luke 806
 
11116 ripley 807
    for (i = 0; i < NUM_SMALL_NODE_CLASSES; i++) {
808
	PAGE_HEADER *page;
809
	int node_size = NODE_SIZE(i);
810
	int page_count = (R_PAGE_SIZE - sizeof(PAGE_HEADER)) / node_size;
10172 luke 811
 
11116 ripley 812
	SET_NEXT_NODE(R_GenHeap[i].New, R_GenHeap[i].New);
813
	SET_PREV_NODE(R_GenHeap[i].New, R_GenHeap[i].New);
814
	for (page = R_GenHeap[i].pages; page != NULL; page = page->next) {
815
	    int j;
816
	    char *data = PAGE_DATA(page);
10172 luke 817
 
11116 ripley 818
	    for (j = 0; j < page_count; j++, data += node_size) {
819
		s = (SEXP) data;
820
		if (! NODE_IS_MARKED(s))
821
		    SNAP_NODE(s, R_GenHeap[i].New);
822
	    }
823
	}
824
	R_GenHeap[i].Free = NEXT_NODE(R_GenHeap[i].New);
10172 luke 825
    }
826
}
827
#endif
828
 
829
 
15915 luke 830
/* Finalization and Weak References */
11390 luke 831
 
15929 luke 832
/* The design of this mechanism is very close to the one described in
833
   "Stretching the storage manager: weak pointers and stable names in
834
   Haskell" by Peyton Jones, Marlow, and Elliott (at
835
   www.research.microsoft.com/Users/simonpj/papers/weak.ps.gz). --LT */
836
 
15915 luke 837
static SEXP R_weak_refs = NULL;
11390 luke 838
 
15883 luke 839
#define READY_TO_FINALIZE_MASK 1
15882 luke 840
 
15883 luke 841
#define SET_READY_TO_FINALIZE(s) ((s)->sxpinfo.gp |= READY_TO_FINALIZE_MASK)
842
#define CLEAR_READY_TO_FINALIZE(s) ((s)->sxpinfo.gp &= ~READY_TO_FINALIZE_MASK)
843
#define IS_READY_TO_FINALIZE(s) ((s)->sxpinfo.gp & READY_TO_FINALIZE_MASK)
844
 
15884 luke 845
#define FINALIZE_ON_EXIT_MASK 2
846
 
847
#define SET_FINALIZE_ON_EXIT(s) ((s)->sxpinfo.gp |= FINALIZE_ON_EXIT_MASK)
848
#define CLEAR_FINALIZE_ON_EXIT(s) ((s)->sxpinfo.gp &= ~FINALIZE_ON_EXIT_MASK)
849
#define FINALIZE_ON_EXIT(s) ((s)->sxpinfo.gp & FINALIZE_ON_EXIT_MASK)
850
 
15928 luke 851
#define WEAKREF_SIZE 4
852
#define WEAKREF_KEY(w) VECTOR_ELT(w, 0)
853
#define SET_WEAKREF_KEY(w, k) SET_VECTOR_ELT(w, 0, k)
854
#define WEAKREF_VALUE(w) VECTOR_ELT(w, 1)
855
#define SET_WEAKREF_VALUE(w, v) SET_VECTOR_ELT(w, 1, v)
856
#define WEAKREF_FINALIZER(w) VECTOR_ELT(w, 2)
857
#define SET_WEAKREF_FINALIZER(w, f) SET_VECTOR_ELT(w, 2, f)
858
#define WEAKREF_NEXT(w) VECTOR_ELT(w, 3)
859
#define SET_WEAKREF_NEXT(w, n) SET_VECTOR_ELT(w, 3, n)
15915 luke 860
 
15928 luke 861
static SEXP MakeCFinalizer(R_CFinalizer_t cfun);
862
 
15915 luke 863
static SEXP NewWeakRef(SEXP key, SEXP val, SEXP fin, Rboolean onexit)
864
{
865
    SEXP w;
866
 
867
    switch (TYPEOF(key)) {
15928 luke 868
    case NILSXP:
15915 luke 869
    case ENVSXP:
870
    case EXTPTRSXP:
871
	break;
872
    default: error("can only weakly reference/finalize reference objects");
873
    }
874
 
15928 luke 875
    PROTECT(key);
876
    PROTECT(val = NAMED(val) ? duplicate(val) : val);
877
    PROTECT(fin);
878
    w = allocVector(VECSXP, WEAKREF_SIZE);
879
    SET_TYPEOF(w, WEAKREFSXP);
880
    if (key != R_NilValue) {
881
	/* If the key is R_NilValue we don't register the weak reference.
882
	   This is used in loading saved images. */
883
        SET_WEAKREF_KEY(w, key);
884
	SET_WEAKREF_VALUE(w, val);
885
	SET_WEAKREF_FINALIZER(w, fin);
886
	SET_WEAKREF_NEXT(w, R_weak_refs);
887
	CLEAR_READY_TO_FINALIZE(w);
888
	if (onexit)
889
	    SET_FINALIZE_ON_EXIT(w);
890
	else
891
	    CLEAR_FINALIZE_ON_EXIT(w);
892
	R_weak_refs = w;
893
    }
894
    UNPROTECT(3);
895
    return w;
896
}
897
 
898
SEXP R_MakeWeakRef(SEXP key, SEXP val, SEXP fin, Rboolean onexit)
899
{
900
    switch (TYPEOF(fin)) {
901
    case NILSXP:
902
    case CLOSXP:
903
    case BUILTINSXP:
904
    case SPECIALSXP:
905
	break;
906
    default: error("finalizer must be a function or NULL");
907
    }
908
    return NewWeakRef(key, val, fin, onexit);
909
}
910
 
911
SEXP R_MakeWeakRefC(SEXP key, SEXP val, R_CFinalizer_t fin, Rboolean onexit)
912
{
913
    SEXP w;
914
    PROTECT(key);
15915 luke 915
    PROTECT(val);
15928 luke 916
    w = NewWeakRef(key, val, MakeCFinalizer(fin), onexit);
15915 luke 917
    UNPROTECT(2);
918
    return w;
919
}
920
 
11390 luke 921
static void CheckFinalizers(void)
922
{
923
    SEXP s;
15915 luke 924
    for (s = R_weak_refs; s != R_NilValue; s = WEAKREF_NEXT(s))
15928 luke 925
	if (! NODE_IS_MARKED(WEAKREF_KEY(s)) && ! IS_READY_TO_FINALIZE(s))
15882 luke 926
	    SET_READY_TO_FINALIZE(s);
11390 luke 927
}
928
 
11834 luke 929
/* C finalizers are stored in a CHARSXP.  It would be nice if we could
930
   use EXTPTRSXP's but these only hold a void *, and function pointers
931
   are not guaranteed to be compatible with a void *.  There should be
15929 luke 932
   a cleaner way of doing this, but this will do for now. --LT */
11834 luke 933
static Rboolean isCFinalizer(SEXP fun)
934
{
935
    return TYPEOF(fun) == CHARSXP;
936
    /*return TYPEOF(fun) == EXTPTRSXP;*/
937
}
938
 
939
static SEXP MakeCFinalizer(R_CFinalizer_t cfun)
940
{
941
    SEXP s = allocString(sizeof(R_CFinalizer_t));
942
    *((R_CFinalizer_t *) CHAR(s)) = cfun;
943
    return s;
944
    /*return R_MakeExternalPtr((void *) cfun, R_NilValue, R_NilValue);*/
945
}
946
 
947
static R_CFinalizer_t GetCFinalizer(SEXP fun)
948
{
949
    return *((R_CFinalizer_t *) CHAR(fun));
950
    /*return (R_CFinalizer_t) R_ExternalPtrAddr(fun);*/
951
}
952
 
15928 luke 953
SEXP R_WeakRefKey(SEXP w)
954
{
955
    if (TYPEOF(w) != WEAKREFSXP)
956
	error("not a weak reference");
957
    return WEAKREF_KEY(w);
958
}
959
 
960
SEXP R_WeakRefValue(SEXP w)
961
{
962
    SEXP v;
963
    if (TYPEOF(w) != WEAKREFSXP)
964
	error("not a weak reference");
965
    v = WEAKREF_VALUE(w);
966
    if (v != R_NilValue && NAMED(v) != 2)
967
	SET_NAMED(v, 2);
968
    return v;
969
}
970
 
971
void R_RunWeakRefFinalizer(SEXP w)
972
{
973
    SEXP key, fun, e;
974
    if (TYPEOF(w) != WEAKREFSXP)
975
	error("not a weak reference");
976
    key = WEAKREF_KEY(w);
977
    fun = WEAKREF_FINALIZER(w);
978
    SET_WEAKREF_KEY(w, R_NilValue);
979
    SET_WEAKREF_VALUE(w, R_NilValue);
980
    SET_WEAKREF_FINALIZER(w, R_NilValue);
981
    if (! IS_READY_TO_FINALIZE(w))
982
	SET_READY_TO_FINALIZE(w); /* insures removal from list on next gc */
983
    PROTECT(key);
984
    PROTECT(fun);
985
    if (isCFinalizer(fun)) {
986
	/* Must be a C finalizer. */
987
	R_CFinalizer_t cfun = GetCFinalizer(fun);
988
	cfun(key);
989
    }
990
    else if (fun != R_NilValue) {
991
	/* An R finalizer. */
992
	PROTECT(e = LCONS(fun, LCONS(key, R_NilValue)));
993
	eval(e, R_GlobalEnv);
994
	UNPROTECT(1);
995
    }
996
    UNPROTECT(2);
997
}
998
 
11390 luke 999
static Rboolean RunFinalizers(void)
1000
{
1001
    volatile SEXP s, last;
1002
    volatile Rboolean finalizer_run = FALSE;
1003
 
15915 luke 1004
    for (s = R_weak_refs, last = R_NilValue; s != R_NilValue;) {
1005
	SEXP next = WEAKREF_NEXT(s);
15882 luke 1006
	if (IS_READY_TO_FINALIZE(s)) {
11390 luke 1007
	    RCNTXT thiscontext;
1008
	    RCNTXT * volatile saveToplevelContext;
1009
	    volatile int savestack;
1010
	    volatile SEXP topExp;
1011
 
1012
	    finalizer_run = TRUE;
1013
 
1014
	    /* A top level context is established for the finalizer to
1015
	       insure that any errors that might occur do not spill
1016
	       into the call that triggered the collection. */
1017
	    begincontext(&thiscontext, CTXT_TOPLEVEL, R_NilValue, R_GlobalEnv,
23463 luke 1018
			 R_NilValue, R_NilValue, R_NilValue);
11390 luke 1019
	    saveToplevelContext = R_ToplevelContext;
1020
	    PROTECT(topExp = R_CurrentExpr);
1021
	    savestack = R_PPStackTop;
1022
	    if (! SETJMP(thiscontext.cjmpbuf)) {
1023
		R_GlobalContext = R_ToplevelContext = &thiscontext;
1024
 
15928 luke 1025
		/* The entry in the weak reference list is removed
11390 luke 1026
		   before running the finalizer.  This insures that a
1027
		   finalizer is run only once, even if running it
1028
		   raises an error. */
1029
		if (last == R_NilValue)
15915 luke 1030
		    R_weak_refs = next;
11390 luke 1031
		else
15928 luke 1032
		    SET_WEAKREF_NEXT(last, next);
1033
		R_RunWeakRefFinalizer(s);
11390 luke 1034
	    }
1035
	    endcontext(&thiscontext);
1036
	    R_ToplevelContext = saveToplevelContext;
1037
	    R_PPStackTop = savestack;
1038
	    R_CurrentExpr = topExp;
1039
	    UNPROTECT(1);
1040
	}
1041
	else last = s;
1042
	s = next;
1043
    }
1044
    return finalizer_run;
1045
}
1046
 
15884 luke 1047
void R_RunExitFinalizers(void)
11390 luke 1048
{
15884 luke 1049
    SEXP s;
1050
 
15915 luke 1051
    for (s = R_weak_refs; s != R_NilValue; s = WEAKREF_NEXT(s))
15884 luke 1052
	if (FINALIZE_ON_EXIT(s))
1053
	    SET_READY_TO_FINALIZE(s);
1054
    RunFinalizers();
1055
}
1056
 
1057
void R_RegisterFinalizerEx(SEXP s, SEXP fun, Rboolean onexit)
1058
{
15928 luke 1059
    R_MakeWeakRef(s, R_NilValue, fun, onexit);
11390 luke 1060
}
1061
 
15884 luke 1062
void R_RegisterFinalizer(SEXP s, SEXP fun)
11390 luke 1063
{
15884 luke 1064
    R_RegisterFinalizerEx(s, fun, FALSE);
1065
}
1066
 
1067
void R_RegisterCFinalizerEx(SEXP s, R_CFinalizer_t fun, Rboolean onexit)
1068
{
15928 luke 1069
    R_MakeWeakRefC(s, R_NilValue, fun, onexit);
11390 luke 1070
}
1071
 
15884 luke 1072
void R_RegisterCFinalizer(SEXP s, R_CFinalizer_t fun)
1073
{
1074
    R_RegisterCFinalizerEx(s, fun, FALSE);
1075
}
1076
 
16557 pd 1077
/* R interface function */
15884 luke 1078
 
16557 pd 1079
SEXP do_regFinaliz(SEXP call, SEXP op, SEXP args, SEXP rho)
1080
{
1081
    checkArity(op, args);
1082
 
1083
    if (TYPEOF(CAR(args)) != ENVSXP && TYPEOF(CAR(args)) != EXTPTRSXP)
1084
	errorcall(call, "1st arg must be environment or external pointer");
1085
    if (TYPEOF(CADR(args)) != CLOSXP)
1086
	errorcall(call, "2nd arg must be a function");
1087
 
1088
    R_RegisterFinalizer(CAR(args), CADR(args));
1089
    return R_NilValue;
1090
}
1091
 
1092
 
10172 luke 1093
/* The Generational Collector. */
1094
 
11390 luke 1095
#define PROCESS_NODES() do { \
1096
    while (forwarded_nodes != NULL) { \
1097
	s = forwarded_nodes; \
1098
	forwarded_nodes = NEXT_NODE(forwarded_nodes); \
1099
	SNAP_NODE(s, R_GenHeap[NODE_CLASS(s)].Old[NODE_GENERATION(s)]); \
1100
	R_GenHeap[NODE_CLASS(s)].OldCount[NODE_GENERATION(s)]++; \
1101
	FORWARD_CHILDREN(s); \
1102
    } \
1103
} while (0)
1104
 
20094 ripley 1105
static void RunGenCollect(R_size_t size_needed)
10172 luke 1106
{
11116 ripley 1107
    int i, gen, gens_collected;
1108
    DevDesc *dd;
1109
    RCNTXT *ctxt;
1110
    SEXP s;
1111
    SEXP forwarded_nodes;
10172 luke 1112
 
11116 ripley 1113
    /* determine number of generations to collect */
1114
    while (num_old_gens_to_collect < NUM_OLD_GENERATIONS) {
1115
	if (collect_counts[num_old_gens_to_collect]-- <= 0) {
1116
	    collect_counts[num_old_gens_to_collect] =
1117
		collect_counts_max[num_old_gens_to_collect];
1118
	    num_old_gens_to_collect++;
1119
	}
1120
	else break;
10172 luke 1121
    }
1122
 
11116 ripley 1123
 again:
1124
    gens_collected = num_old_gens_to_collect;
10172 luke 1125
 
1126
#ifndef EXPEL_OLD_TO_NEW
11116 ripley 1127
    /* eliminate old-to-new references in generations to collect by
1128
       transferring referenced nodes to referring generation */
1129
    for (gen = 0; gen < num_old_gens_to_collect; gen++) {
1130
	for (i = 0; i < NUM_NODE_CLASSES; i++) {
1131
	    s = NEXT_NODE(R_GenHeap[i].OldToNew[gen]);
1132
	    while (s != R_GenHeap[i].OldToNew[gen]) {
1133
		SEXP next = NEXT_NODE(s);
1134
		DO_CHILDREN(s, AgeNodeAndChildren, gen);
1135
		UNSNAP_NODE(s);
1136
		if (NODE_GENERATION(s) != gen)
1137
		    REprintf("****snapping into wrong generation\n");
1138
		SNAP_NODE(s, R_GenHeap[i].Old[gen]);
1139
		s = next;
1140
	    }
1141
	}
10172 luke 1142
    }
1143
#endif
1144
 
11116 ripley 1145
    DEBUG_CHECK_NODE_COUNTS("at start");
10172 luke 1146
 
11116 ripley 1147
    /* unmark all marked nodes in old generations to be collected and
1148
       move to New space */
1149
    for (gen = 0; gen < num_old_gens_to_collect; gen++) {
1150
	for (i = 0; i < NUM_NODE_CLASSES; i++) {
1151
	    R_GenHeap[i].OldCount[gen] = 0;
1152
	    s = NEXT_NODE(R_GenHeap[i].Old[gen]);
1153
	    while (s != R_GenHeap[i].Old[gen]) {
1154
		SEXP next = NEXT_NODE(s);
1155
		if (gen < NUM_OLD_GENERATIONS - 1)
1156
		    SET_NODE_GENERATION(s, gen + 1);
1157
		UNMARK_NODE(s);
1158
		s = next;
1159
	    }
1160
	    if (NEXT_NODE(R_GenHeap[i].Old[gen]) != R_GenHeap[i].Old[gen])
1161
		BULK_MOVE(R_GenHeap[i].Old[gen], R_GenHeap[i].New);
1162
	}
10172 luke 1163
    }
1164
 
11116 ripley 1165
    forwarded_nodes = NULL;
10172 luke 1166
 
1167
#ifndef EXPEL_OLD_TO_NEW
11116 ripley 1168
    /* scan nodes in uncollected old generations with old-to-new pointers */
1169
    for (gen = num_old_gens_to_collect; gen < NUM_OLD_GENERATIONS; gen++)
1170
	for (i = 0; i < NUM_NODE_CLASSES; i++)
1171
	    for (s = NEXT_NODE(R_GenHeap[i].OldToNew[gen]);
1172
		 s != R_GenHeap[i].OldToNew[gen];
1173
		 s = NEXT_NODE(s))
1174
		FORWARD_CHILDREN(s);
10172 luke 1175
#endif
1176
 
11116 ripley 1177
    /* forward all roots */
1178
    FORWARD_NODE(R_NilValue);	           /* Builtin constants */
1179
    FORWARD_NODE(NA_STRING);
1180
    FORWARD_NODE(R_BlankString);
1181
    FORWARD_NODE(R_UnboundValue);
14906 luke 1182
    FORWARD_NODE(R_RestartToken);
11116 ripley 1183
    FORWARD_NODE(R_MissingArg);
1184
    FORWARD_NODE(R_CommentSxp);
10172 luke 1185
 
11116 ripley 1186
    FORWARD_NODE(R_GlobalEnv);	           /* Global environment */
1187
    FORWARD_NODE(R_Warnings);	           /* Warnings, if any */
10172 luke 1188
 
25523 luke 1189
#ifdef NEW_CONDITION_HANDLING
1190
    FORWARD_NODE(R_HandlerStack);          /* Condition handler stack */
1191
    FORWARD_NODE(R_RestartStack);          /* Available restarts stack */
1192
#endif
1193
 
11116 ripley 1194
    for (i = 0; i < HSIZE; i++)	           /* Symbol table */
1195
	FORWARD_NODE(R_SymbolTable[i]);
10172 luke 1196
 
11116 ripley 1197
    if (R_CurrentExpr != NULL)	           /* Current expression */
1198
	FORWARD_NODE(R_CurrentExpr);
10172 luke 1199
 
11116 ripley 1200
    for (i = 0; i < R_MaxDevices; i++) {   /* Device display lists */
1201
	dd = GetDevice(i);
16910 ripley 1202
	if (dd) {
18917 murrell 1203
	    if (dd->newDevStruct) {
16881 murrell 1204
		FORWARD_NODE(((GEDevDesc*) dd)->dev->displayList);
18917 murrell 1205
		FORWARD_NODE(((GEDevDesc*) dd)->dev->savedSnapshot);
1206
	    }
16881 murrell 1207
	    else
1208
		FORWARD_NODE(dd->displayList);
16910 ripley 1209
	}
11116 ripley 1210
    }
10172 luke 1211
 
23463 luke 1212
    for (ctxt = R_GlobalContext ; ctxt != NULL ; ctxt = ctxt->nextcontext) {
1213
	FORWARD_NODE(ctxt->conexit);       /* on.exit expressions */
1214
	FORWARD_NODE(ctxt->promargs);	   /* promises supplied to closure */
1215
	FORWARD_NODE(ctxt->callfun);       /* the closure called */
1216
        FORWARD_NODE(ctxt->sysparent);     /* calling environment */
1217
	FORWARD_NODE(ctxt->call);          /* the call */
1218
	FORWARD_NODE(ctxt->cloenv);        /* the closure environment */
25523 luke 1219
#ifdef NEW_CONDITION_HANDLING
1220
	FORWARD_NODE(ctxt->handlerstack);  /* the condition handler stack */
1221
	FORWARD_NODE(ctxt->restartstack);  /* the available restarts stack */
1222
#endif
23463 luke 1223
    }
10172 luke 1224
 
11116 ripley 1225
    FORWARD_NODE(framenames); 		   /* used for interprocedure
1226
					      communication in model.c */
10172 luke 1227
 
11116 ripley 1228
    FORWARD_NODE(R_PreciousList);
10172 luke 1229
 
11116 ripley 1230
    for (i = 0; i < R_PPStackTop; i++)	   /* Protected pointers */
1231
	FORWARD_NODE(R_PPStack[i]);
10172 luke 1232
 
11116 ripley 1233
    FORWARD_NODE(R_VStack);		   /* R_alloc stack */
10172 luke 1234
 
26045 luke 1235
#ifdef BYTECODE
1236
    {
1237
	SEXP *sp;
1238
	for (sp = R_BCNodeStackBase; sp < R_BCNodeStackTop; sp++)
1239
	    FORWARD_NODE(*sp);
1240
    }
1241
#endif
1242
 
11116 ripley 1243
    /* main processing loop */
11390 luke 1244
    PROCESS_NODES();
10172 luke 1245
 
15915 luke 1246
    /* identify weakly reachable nodes */
1247
    {
15928 luke 1248
	Rboolean recheck_weak_refs;
15915 luke 1249
	do {
15928 luke 1250
	    recheck_weak_refs = FALSE;
15915 luke 1251
	    for (s = R_weak_refs; s != R_NilValue; s = WEAKREF_NEXT(s)) {
1252
		if (NODE_IS_MARKED(WEAKREF_KEY(s))) {
1253
		    if (! NODE_IS_MARKED(WEAKREF_VALUE(s))) {
1254
			recheck_weak_refs = TRUE;
1255
			FORWARD_NODE(WEAKREF_VALUE(s));
1256
		    }
1257
		    if (! NODE_IS_MARKED(WEAKREF_FINALIZER(s))) {
1258
			recheck_weak_refs = TRUE;
1259
			FORWARD_NODE(WEAKREF_FINALIZER(s));
1260
		    }
1261
		}
1262
	    }
1263
	    PROCESS_NODES();
1264
	} while (recheck_weak_refs);
1265
    }
1266
 
11390 luke 1267
    /* mark nodes ready for finalizing */
1268
    CheckFinalizers();
1269
 
15915 luke 1270
    /* process the weak reference chain */
1271
    for (s = R_weak_refs; s != R_NilValue; s = WEAKREF_NEXT(s)) {
1272
	FORWARD_NODE(s);
1273
	FORWARD_NODE(WEAKREF_KEY(s));
1274
	FORWARD_NODE(WEAKREF_VALUE(s));
1275
	FORWARD_NODE(WEAKREF_FINALIZER(s));
1276
    }
11390 luke 1277
    PROCESS_NODES();
1278
 
11116 ripley 1279
    DEBUG_CHECK_NODE_COUNTS("after processing forwarded list");
10172 luke 1280
 
11116 ripley 1281
    /* release large vector allocations */
1282
    ReleaseLargeFreeVectors();
10172 luke 1283
 
11116 ripley 1284
    DEBUG_CHECK_NODE_COUNTS("after releasing large allocated nodes");
10172 luke 1285
 
11116 ripley 1286
    /* reset Free pointers */
10172 luke 1287
    for (i = 0; i < NUM_NODE_CLASSES; i++)
11116 ripley 1288
	R_GenHeap[i].Free = NEXT_NODE(R_GenHeap[i].New);
10172 luke 1289
 
11116 ripley 1290
    /* update heap statistics */
1291
    R_Collected = R_NSize;
1292
    R_SmallVallocSize = 0;
1293
    for (gen = 0; gen < NUM_OLD_GENERATIONS; gen++) {
1294
	for (i = 1; i < NUM_SMALL_NODE_CLASSES; i++)
1295
	    R_SmallVallocSize += R_GenHeap[i].OldCount[gen] * NodeClassSize[i];
1296
	for (i = 0; i < NUM_NODE_CLASSES; i++)
1297
	    R_Collected -= R_GenHeap[i].OldCount[gen];
10172 luke 1298
    }
11116 ripley 1299
    R_NodesInUse = R_NSize - R_Collected;
1300
 
1301
    if (num_old_gens_to_collect < NUM_OLD_GENERATIONS) {
1302
	if (R_Collected < R_MinFreeFrac * R_NSize ||
20094 ripley 1303
	    VHEAP_FREE() < size_needed + R_MinFreeFrac * R_VSize) {
11116 ripley 1304
	    num_old_gens_to_collect++;
1305
	    if (R_Collected <= 0 || VHEAP_FREE() < size_needed)
1306
		goto again;
1307
	}
1308
	else num_old_gens_to_collect = 0;
1309
    }
10172 luke 1310
    else num_old_gens_to_collect = 0;
1311
 
11116 ripley 1312
    gen_gc_counts[gens_collected]++;
10172 luke 1313
 
11116 ripley 1314
    if (gens_collected == NUM_OLD_GENERATIONS) {
1315
	/**** do some adjustment for intermediate collections? */
1316
	AdjustHeapSize(size_needed);
1317
	TryToReleasePages();
1318
	DEBUG_CHECK_NODE_COUNTS("after heap adjustment");
1319
    }
1320
    else if (gens_collected > 0) {
1321
	TryToReleasePages();
1322
	DEBUG_CHECK_NODE_COUNTS("after heap adjustment");
1323
    }
10172 luke 1324
#ifdef SORT_NODES
11116 ripley 1325
    if (gens_collected == NUM_OLD_GENERATIONS)
1326
	SortNodes();
10172 luke 1327
#endif
1328
 
11116 ripley 1329
    if (gc_reporting) {
1330
	REprintf("Garbage collection %d = %d", gc_count, gen_gc_counts[0]);
1331
	for (i = 0; i < NUM_OLD_GENERATIONS; i++)
1332
	    REprintf("+%d", gen_gc_counts[i + 1]);
1333
	REprintf(" (level %d) ... ", gens_collected);
1334
	DEBUG_GC_SUMMARY(gens_collected == NUM_OLD_GENERATIONS);
1335
    }
10172 luke 1336
}
1337
 
1338
 
2512 pd 1339
SEXP do_gctorture(SEXP call, SEXP op, SEXP args, SEXP rho)
1340
{
1341
    int i;
1342
    SEXP old = allocVector(LGLSXP, 1);
1343
 
1344
    checkArity(op, args);
1345
    i = asLogical(CAR(args));
11095 ripley 1346
    LOGICAL(old)[0] = !gc_inhibit_torture;
2512 pd 1347
    if (i != NA_LOGICAL)
1348
	gc_inhibit_torture = !i;
1349
    return old;
1350
}
1351
 
2 r 1352
SEXP do_gcinfo(SEXP call, SEXP op, SEXP args, SEXP rho)
1353
{
1820 ihaka 1354
    int i;
2437 maechler 1355
    SEXP old = allocVector(LGLSXP, 1);
1356
 
1820 ihaka 1357
    checkArity(op, args);
1358
    i = asLogical(CAR(args));
2437 maechler 1359
    LOGICAL(old)[0] = gc_reporting;
1820 ihaka 1360
    if (i != NA_LOGICAL)
1361
	gc_reporting = i;
2437 maechler 1362
    return old;
2 r 1363
}
1364
 
1365
SEXP do_gc(SEXP call, SEXP op, SEXP args, SEXP rho)
1366
{
2437 maechler 1367
    SEXP value;
20094 ripley 1368
    int ogc;
1369
    R_size_t onsize = R_NSize;
11092 ripley 1370
 
1820 ihaka 1371
    checkArity(op, args);
2437 maechler 1372
    ogc = gc_reporting;
1373
    gc_reporting = asLogical(CAR(args));
10172 luke 1374
    num_old_gens_to_collect = NUM_OLD_GENERATIONS;
7750 ripley 1375
    R_gc();
2437 maechler 1376
    gc_reporting = ogc;
11092 ripley 1377
    /*- now return the [used , gc trigger size] for cells and heap */
11197 ripley 1378
    PROTECT(value = allocVector(INTSXP, 10));
11092 ripley 1379
    INTEGER(value)[0] = onsize - R_Collected;
13180 luke 1380
    INTEGER(value)[1] = R_VSize - VHEAP_FREE();
20094 ripley 1381
    /* carefully here: we can't report large sizes in R's integer */
1382
    INTEGER(value)[4] = (R_NSize < INT_MAX) ? R_NSize : NA_INTEGER;
1383
    INTEGER(value)[5] = (R_VSize < INT_MAX) ? R_VSize : NA_INTEGER;
1384
    /* next four are in 0.1Mb, rounded up */
13600 maechler 1385
    INTEGER(value)[2] = 10. * (onsize - R_Collected)/Mega * sizeof(SEXPREC) + 0.999;
20094 ripley 1386
    INTEGER(value)[3] = 10. * (R_VSize - VHEAP_FREE())/Mega * vsfac + 0.999;
13600 maechler 1387
    INTEGER(value)[6] = 10. * R_NSize/Mega * sizeof(SEXPREC) + 0.999;
20094 ripley 1388
    INTEGER(value)[7] = 10. * R_VSize/Mega * vsfac + 0.999;
1389
    INTEGER(value)[8] = (R_MaxNSize < R_SIZE_T_MAX) ? 
13600 maechler 1390
	(10. * R_MaxNSize/Mega * sizeof(SEXPREC) + 0.999) : NA_INTEGER;
20094 ripley 1391
    INTEGER(value)[9] = (R_MaxVSize < R_SIZE_T_MAX) ? 
1392
	(10. * R_MaxVSize/Mega * vsfac + 0.999) : NA_INTEGER;
2437 maechler 1393
    UNPROTECT(1);
1394
    return value;
2 r 1395
}
1396
 
1820 ihaka 1397
 
20094 ripley 1398
static void mem_err_heap(R_size_t size)
1820 ihaka 1399
{
11197 ripley 1400
    errorcall(R_NilValue, "vector memory exhausted (limit reached?)");
1754 pd 1401
}
2 r 1402
 
1820 ihaka 1403
 
10172 luke 1404
static void mem_err_cons()
1820 ihaka 1405
{
11197 ripley 1406
    errorcall(R_NilValue, "cons memory exhausted (limit reached?)");
1754 pd 1407
}
1408
 
1839 ihaka 1409
/* InitMemory : Initialise the memory to be used in R. */
1410
/* This includes: stack space, node space and vector space */
2 r 1411
 
26646 luke 1412
#define PP_REDZONE_SIZE 1000L
1413
static R_size_t R_StandardPPStackSize, R_RealPPStackSize;
1414
 
2 r 1415
void InitMemory()
1416
{
1820 ihaka 1417
    int i;
10172 luke 1418
    int gen;
2 r 1419
 
2437 maechler 1420
    gc_reporting = R_Verbose;
26646 luke 1421
    R_StandardPPStackSize = R_PPStackSize;
1422
    R_RealPPStackSize = R_PPStackSize + PP_REDZONE_SIZE;
1423
    if (!(R_PPStack = (SEXP *) malloc(R_RealPPStackSize * sizeof(SEXP))))
1820 ihaka 1424
	R_Suicide("couldn't allocate memory for pointer stack");
1425
    R_PPStackTop = 0;
2 r 1426
 
11197 ripley 1427
    vsfac = sizeof(VECREC);
1428
    R_VSize = (((R_VSize + 1)/ vsfac));
2 r 1429
 
10172 luke 1430
    UNMARK_NODE(&UnmarkedNodeTemplate);
1160 maechler 1431
 
10172 luke 1432
    for (i = 0; i < NUM_NODE_CLASSES; i++) {
1433
      for (gen = 0; gen < NUM_OLD_GENERATIONS; gen++) {
1434
        R_GenHeap[i].Old[gen] = &R_GenHeap[i].OldPeg[gen];
1435
	SET_PREV_NODE(R_GenHeap[i].Old[gen], R_GenHeap[i].Old[gen]);
1436
	SET_NEXT_NODE(R_GenHeap[i].Old[gen], R_GenHeap[i].Old[gen]);
2 r 1437
 
10172 luke 1438
#ifndef EXPEL_OLD_TO_NEW
1439
	R_GenHeap[i].OldToNew[gen] = &R_GenHeap[i].OldToNewPeg[gen];
1440
	SET_PREV_NODE(R_GenHeap[i].OldToNew[gen], R_GenHeap[i].OldToNew[gen]);
1441
	SET_NEXT_NODE(R_GenHeap[i].OldToNew[gen], R_GenHeap[i].OldToNew[gen]);
1442
#endif
1443
 
1444
	R_GenHeap[i].OldCount[gen] = 0;
1445
      }
1446
      R_GenHeap[i].New = &R_GenHeap[i].NewPeg;
1447
      SET_PREV_NODE(R_GenHeap[i].New, R_GenHeap[i].New);
1448
      SET_NEXT_NODE(R_GenHeap[i].New, R_GenHeap[i].New);
1449
    }
1450
 
1451
    for (i = 0; i < NUM_NODE_CLASSES; i++)
1452
        R_GenHeap[i].Free = NEXT_NODE(R_GenHeap[i].New);
1453
 
1454
    SET_NODE_CLASS(&UnmarkedNodeTemplate, 0);
1455
    orig_R_NSize = R_NSize;
1456
    orig_R_VSize = R_VSize;
1457
 
1458
    /* R_NilValue */
1459
    /* THIS MUST BE THE FIRST CONS CELL ALLOCATED */
1460
    /* OR ARMAGEDDON HAPPENS. */
1461
    /* Field assignments for R_NilValue must not go through write barrier
1462
       since the write barrier prevents assignments to R_NilValue's fields.
1463
       because of checks for nil */
1464
    GET_FREE_NODE(R_NilValue);
1465
    R_NilValue->sxpinfo = UnmarkedNodeTemplate.sxpinfo;
1466
    TYPEOF(R_NilValue) = NILSXP;
1467
    CAR(R_NilValue) = R_NilValue;
1468
    CDR(R_NilValue) = R_NilValue;
1469
    TAG(R_NilValue) = R_NilValue;
1470
    ATTRIB(R_NilValue) = R_NilValue;
11390 luke 1471
 
26045 luke 1472
#ifdef BYTECODE
1473
    R_BCNodeStackBase = (SEXP *) malloc(R_BCNODESTACKSIZE * sizeof(SEXP));
1474
    if (R_BCNodeStackBase == NULL)
1475
	R_Suicide("couldn't allocate node stack");
1476
# ifdef BC_INT_STACK
1477
    R_BCIntStackBase =
1478
      (IStackval *) malloc(R_BCINTSTACKSIZE * sizeof(IStackval));
1479
    if (R_BCIntStackBase == NULL)
1480
	R_Suicide("couldn't allocate integer stack");
1481
# endif
1482
    R_BCNodeStackTop = R_BCNodeStackBase;
1483
    R_BCNodeStackEnd = R_BCNodeStackBase + R_BCNODESTACKSIZE;
1484
# ifdef BC_INT_STACK
1485
    R_BCIntStackTop = R_BCIntStackBase;
1486
    R_BCIntStackEnd = R_BCIntStackBase + R_BCINTSTACKSIZE;
1487
# endif
1488
#endif
15915 luke 1489
    R_weak_refs = R_NilValue;
25523 luke 1490
 
1491
#ifdef NEW_CONDITION_HANDLING
1492
    R_HandlerStack = R_RestartStack = R_NilValue;
1493
#endif
2 r 1494
}
1495
 
10172 luke 1496
/* Since memory allocated from the heap is non-moving, R_alloc just
1497
   allocates off the heap as CHARSXP's and maintains the stack of
1498
   allocations thorugh the ATTRIB pointer.  The stack pointer R_VStack
1499
   is traced by the collector. */
1500
char *vmaxget(void)
1501
{
1502
    return (char *) R_VStack;
1503
}
2 r 1504
 
10172 luke 1505
void vmaxset(char *ovmax)
1506
{
1507
  R_VStack = (SEXP) ovmax;
1508
}
1509
 
1510
char *R_alloc(long nelem, int eltsize)
1511
{
20094 ripley 1512
  R_size_t size = nelem * eltsize;
10172 luke 1513
  if (size > 0) {
1514
    SEXP s = allocString(size); /**** avoid extra null byte?? */
1515
    ATTRIB(s) = R_VStack;
1516
    R_VStack = s;
1517
    return CHAR(s);
1518
  }
1519
  else return NULL;
1520
}
2 r 1521
 
1522
/* S COMPATIBILITY */
1523
 
1524
char *S_alloc(long nelem, int eltsize)
1525
{
20094 ripley 1526
    R_size_t i, size  = nelem * eltsize;
1820 ihaka 1527
    char *p = R_alloc(nelem, eltsize);
11116 ripley 1528
    for(i = 0; i < size; i++)
1820 ihaka 1529
	p[i] = 0;
1530
    return p;
2 r 1531
}
1532
 
1533
 
1534
char *S_realloc(char *p, long new, long old, int size)
1535
{
1820 ihaka 1536
    int i, nold;
1537
    char *q;
1538
    /* shrinking is a no-op */
1539
    if(new <= old) return p;
1540
    q = R_alloc(new, size);
1541
    nold = old * size;
11116 ripley 1542
    for(i = 0; i < nold; i++)
1820 ihaka 1543
	q[i] = p[i];
11116 ripley 1544
    for(i = nold; i < new*size; i++)
7741 ripley 1545
	q[i] = 0;
1820 ihaka 1546
    return q;
2 r 1547
}
1548
 
10172 luke 1549
/* "allocSExp" allocate a SEXPREC */
1820 ihaka 1550
/* call gc if necessary */
2 r 1551
 
1552
SEXP allocSExp(SEXPTYPE t)
1553
{
1820 ihaka 1554
    SEXP s;
10172 luke 1555
    if (FORCE_GC || NO_FREE_NODES()) {
1556
	R_gc_internal(0);
1557
	if (NO_FREE_NODES())
1820 ihaka 1558
	    mem_err_cons();
1559
    }
10172 luke 1560
    GET_FREE_NODE(s);
1561
    s->sxpinfo = UnmarkedNodeTemplate.sxpinfo;
1562
    TYPEOF(s) = t;
1820 ihaka 1563
    CAR(s) = R_NilValue;
1564
    CDR(s) = R_NilValue;
1565
    TAG(s) = R_NilValue;
1566
    ATTRIB(s) = R_NilValue;
10172 luke 1567
    return s;
1568
}
1569
 
1570
static SEXP allocSExpNonCons(SEXPTYPE t)
1571
{
1572
    SEXP s;
1573
    if (FORCE_GC || NO_FREE_NODES()) {
1574
	R_gc_internal(0);
1575
	if (NO_FREE_NODES())
1576
	    mem_err_cons();
1577
    }
1578
    GET_FREE_NODE(s);
1579
    s->sxpinfo = UnmarkedNodeTemplate.sxpinfo;
1820 ihaka 1580
    TYPEOF(s) = t;
10172 luke 1581
    TAG(s) = R_NilValue;
1582
    ATTRIB(s) = R_NilValue;
1820 ihaka 1583
    return s;
2 r 1584
}
1585
 
10172 luke 1586
/* cons is defined directly do avoid the need to protect its arguments
1587
   unless a GC will actually occur. */
1588
SEXP cons(SEXP car, SEXP cdr)
1589
{
1590
    SEXP s;
1591
    if (FORCE_GC || NO_FREE_NODES()) {
1592
      PROTECT(car);
1593
      PROTECT(cdr);
1594
      R_gc_internal(0);
1595
      UNPROTECT(2);
1596
      if (NO_FREE_NODES())
1597
	mem_err_cons();
1598
    }
1599
    GET_FREE_NODE(s);
1600
    s->sxpinfo = UnmarkedNodeTemplate.sxpinfo;
1601
    TYPEOF(s) = LISTSXP;
1602
    CAR(s) = car;
1603
    CDR(s) = cdr;
1604
    TAG(s) = R_NilValue;
1605
    ATTRIB(s) = R_NilValue;
1606
    return s;
1607
}
1608
 
10318 luke 1609
/*----------------------------------------------------------------------
1610
 
1611
  NewEnvironment
1612
 
1613
  Create an environment by extending "rho" with a frame obtained by
1614
  pairing the variable names given by the tags on "namelist" with
1615
  the values given by the elements of "valuelist".
1616
 
16275 luke 1617
  NewEnvironment is defined directly to avoid the need to protect its
1618
  arguments unless a GC will actually occur.  This definition allows
1619
  the namelist argument to be shorter than the valuelist; in this
1620
  case the remaining values must be named already.  (This is useful
1621
  in cases where the entire valuelist is already named--namelist can
1622
  then be R_NilValue
1623
 
1624
  The valuelist is destructively modified and used as the
1625
  environment's frame.
10318 luke 1626
*/
10172 luke 1627
SEXP NewEnvironment(SEXP namelist, SEXP valuelist, SEXP rho)
1628
{
1629
    SEXP v, n, newrho;
1630
 
1631
    if (FORCE_GC || NO_FREE_NODES()) {
1632
      PROTECT(namelist);
1633
      PROTECT(valuelist);
1634
      PROTECT(rho);
1635
      R_gc_internal(0);
1636
      UNPROTECT(3);
1637
      if (NO_FREE_NODES())
1638
	mem_err_cons();
1639
    }
1640
    GET_FREE_NODE(newrho);
1641
    newrho->sxpinfo = UnmarkedNodeTemplate.sxpinfo;
1642
    TYPEOF(newrho) = ENVSXP;
1643
    FRAME(newrho) = valuelist;
1644
    ENCLOS(newrho) = rho;
1645
    HASHTAB(newrho) = R_NilValue;
1646
    ATTRIB(newrho) = R_NilValue;
1647
 
1648
    v = valuelist;
1649
    n = namelist;
10318 luke 1650
    while (v != R_NilValue && n != R_NilValue) {
10172 luke 1651
	SET_TAG(v, TAG(n));
1652
	v = CDR(v);
1653
	n = CDR(n);
1654
    }
1655
    return (newrho);
1656
}
1657
 
1658
/* mkPROMISE is defined directly do avoid the need to protect its arguments
1659
   unless a GC will actually occur. */
1660
SEXP mkPROMISE(SEXP expr, SEXP rho)
1661
{
1662
    SEXP s;
1663
    if (FORCE_GC || NO_FREE_NODES()) {
1664
      PROTECT(expr);
1665
      PROTECT(rho);
1666
      R_gc_internal(0);
1667
      UNPROTECT(2);
1668
      if (NO_FREE_NODES())
1669
	mem_err_cons();
1670
    }
1671
    GET_FREE_NODE(s);
1672
    s->sxpinfo = UnmarkedNodeTemplate.sxpinfo;
1673
    TYPEOF(s) = PROMSXP;
26020 luke 1674
    PRCODE(s) = expr;
10172 luke 1675
    PRENV(s) = rho;
1676
    PRVALUE(s) = R_UnboundValue;
1677
    PRSEEN(s) = 0;
1678
    ATTRIB(s) = R_NilValue;
1679
    return s;
1680
}
1681
 
1820 ihaka 1682
/* "allocString" allocate a string on the (vector) heap. */
1683
/* All vector objects  must be a multiple of sizeof(ALIGN) */
1684
/* bytes so that alignment is preserved for all objects */
2 r 1685
 
1686
SEXP allocString(int length)
1687
{
10172 luke 1688
    return allocVector(CHARSXP, length);
2 r 1689
}
1690
 
1691
 
1820 ihaka 1692
/* Allocate a vector object on the heap */
2 r 1693
 
28362 murdoch 1694
SEXP allocVector(SEXPTYPE type, R_len_t length)
2 r 1695
{
10910 luke 1696
    SEXP s;     /* For the generational collector it would be safer to
1697
		   work in terms of a VECSEXP here, but that would
1698
		   require several casts below... */
28362 murdoch 1699
    R_len_t i;
20094 ripley 1700
    R_size_t size = 0, alloc_size, old_R_VSize;
10172 luke 1701
    int node_class;
1702
 
1820 ihaka 1703
    if (length < 0 )
1704
	errorcall(R_GlobalContext->call,
5731 ripley 1705
		  "negative length vectors are not allowed");
1820 ihaka 1706
    /* number of vector cells to allocate */
1707
    switch (type) {
1708
    case NILSXP:
1709
	return R_NilValue;
1710
    case CHARSXP:
10172 luke 1711
	size = BYTE2VEC(length + 1);
1820 ihaka 1712
	break;
1713
    case LGLSXP:
1714
    case INTSXP:
1715
	if (length <= 0)
1716
	    size = 0;
16410 luke 1717
	else {
20094 ripley 1718
	    if (length > R_SIZE_T_MAX / sizeof(int))
16410 luke 1719
		errorcall(R_GlobalContext->call,
1720
			  "cannot allocate vector of length %d", length);
10172 luke 1721
	    size = INT2VEC(length);
16410 luke 1722
	}
1820 ihaka 1723
	break;
1724
    case REALSXP:
1725
	if (length <= 0)
1726
	    size = 0;
16410 luke 1727
	else {
20094 ripley 1728
	    if (length > R_SIZE_T_MAX / sizeof(double))
16410 luke 1729
		errorcall(R_GlobalContext->call,
1730
			  "cannot allocate vector of length %d", length);
10172 luke 1731
	    size = FLOAT2VEC(length);
16410 luke 1732
	}
1820 ihaka 1733
	break;
1734
    case CPLXSXP:
1735
	if (length <= 0)
1736
	    size = 0;
16410 luke 1737
	else {
20094 ripley 1738
	    if (length > R_SIZE_T_MAX / sizeof(Rcomplex))
16410 luke 1739
		errorcall(R_GlobalContext->call,
1740
			  "cannot allocate vector of length %d", length);
10172 luke 1741
	    size = COMPLEX2VEC(length);
16410 luke 1742
	}
1820 ihaka 1743
	break;
1744
    case STRSXP:
1745
    case EXPRSXP:
1746
    case VECSXP:
1747
	if (length <= 0)
1748
	    size = 0;
16410 luke 1749
	else {
20094 ripley 1750
	    if (length > R_SIZE_T_MAX / sizeof(SEXP))
16410 luke 1751
		errorcall(R_GlobalContext->call,
1752
			  "cannot allocate vector of length %d", length);
10172 luke 1753
	    size = PTR2VEC(length);
16410 luke 1754
	}
1820 ihaka 1755
	break;
1756
    case LANGSXP:
1757
	if(length == 0) return R_NilValue;
1758
	s = allocList(length);
1759
	TYPEOF(s) = LANGSXP;
1760
	return s;
1761
    case LISTSXP:
1762
	return allocList(length);
1763
    default:
5731 ripley 1764
	error("invalid type/length (%d/%d) in vector allocation", type, length);
1820 ihaka 1765
    }
10172 luke 1766
 
1767
    if (size <= NodeClassSize[1]) {
1768
      node_class = 1;
1769
      alloc_size = NodeClassSize[1];
1770
    }
1771
    else {
1772
      node_class = LARGE_NODE_CLASS;
1773
      alloc_size = size;
1774
      for (i = 2; i < NUM_SMALL_NODE_CLASSES; i++) {
1775
	if (size <= NodeClassSize[i]) {
1776
	  node_class = i;
1777
	  alloc_size = NodeClassSize[i];
1778
	  break;
1779
	}
1780
      }
1781
    }
1782
 
1783
    /* save current R_VSize to roll back adjustment if malloc fails */
1784
    old_R_VSize = R_VSize;
1785
 
1820 ihaka 1786
    /* we need to do the gc here so allocSExp doesn't! */
20094 ripley 1787
    if (FORCE_GC || NO_FREE_NODES() || VHEAP_FREE() < alloc_size) {
10172 luke 1788
	R_gc_internal(alloc_size);
1789
	if (NO_FREE_NODES())
1820 ihaka 1790
	    mem_err_cons();
10172 luke 1791
	if (VHEAP_FREE() < alloc_size)
2437 maechler 1792
	    mem_err_heap(size);
1820 ihaka 1793
    }
2100 pd 1794
 
1820 ihaka 1795
    if (size > 0) {
11116 ripley 1796
	if (node_class < NUM_SMALL_NODE_CLASSES) {
1797
	    CLASS_GET_FREE_NODE(node_class, s);
1798
	    s->sxpinfo = UnmarkedNodeTemplate.sxpinfo;
1799
	    SET_NODE_CLASS(s, node_class);
1800
	    R_SmallVallocSize += alloc_size;
10172 luke 1801
	}
11116 ripley 1802
	else {
1803
	    s = NULL; /* initialize to suppress warning */
1804
	    if (size >= (LONG_MAX / sizeof(VECREC)) - sizeof(SEXPREC_ALIGN) ||
1805
		(s = malloc(sizeof(SEXPREC_ALIGN) + size * sizeof(VECREC)))
1806
		== NULL) {
1807
		/* reset the vector heap limit */
1808
		R_VSize = old_R_VSize;
20094 ripley 1809
		errorcall(R_NilValue, "cannot allocate vector of size %lu Kb",
11116 ripley 1810
			  (size * sizeof(VECREC))/1024);
1811
	    }
1812
	    s->sxpinfo = UnmarkedNodeTemplate.sxpinfo;
1813
	    SET_NODE_CLASS(s, LARGE_NODE_CLASS);
20094 ripley 1814
	    R_LargeVallocSize += size;
11116 ripley 1815
	    R_GenHeap[LARGE_NODE_CLASS].AllocCount++;
20713 luke 1816
	    R_NodesInUse++;
11116 ripley 1817
	    SNAP_NODE(s, R_GenHeap[LARGE_NODE_CLASS].New);
1818
	}
1819
	ATTRIB(s) = R_NilValue;
1820
	TYPEOF(s) = type;
1820 ihaka 1821
    }
10172 luke 1822
    else {
1823
	GC_PROT(s = allocSExpNonCons(type));
1824
    }
1825
    LENGTH(s) = length;
1826
    NAMED(s) = 0;
1827
 
1820 ihaka 1828
    /* The following prevents disaster in the case */
1829
    /* that an uninitialised string vector is marked */
10910 luke 1830
    /* Direct assignment is OK since the node was just allocated and */
1831
    /* so is at least as new as R_NilValue and R_BlankString */
4849 ihaka 1832
    if (type == EXPRSXP || type == VECSXP) {
10910 luke 1833
	SEXP *data = STRING_PTR(s);
1820 ihaka 1834
	for (i = 0; i < length; i++)
10910 luke 1835
	    data[i] = R_NilValue;
1820 ihaka 1836
    }
4849 ihaka 1837
    else if(type == STRSXP) {
10910 luke 1838
	SEXP *data = STRING_PTR(s);
4849 ihaka 1839
	for (i = 0; i < length; i++)
10910 luke 1840
	    data[i] = R_BlankString;
4849 ihaka 1841
    }
16455 luke 1842
    else if (type == CHARSXP)
1843
	CHAR(s)[length] = 0;
1820 ihaka 1844
    return s;
2 r 1845
}
1846
 
1847
SEXP allocList(int n)
1848
{
1820 ihaka 1849
    int i;
1850
    SEXP result;
1851
    result = R_NilValue;
1852
    for (i = 0; i < n; i++) {
1853
	result = CONS(R_NilValue, result);
1854
    }
1855
    return result;
2 r 1856
}
1857
 
10172 luke 1858
/* "gc" a mark-sweep or in-place generational garbage collector */
2 r 1859
 
11197 ripley 1860
void R_gc(void)
1861
{
1862
    R_gc_internal(0);
1863
}
10172 luke 1864
 
19066 hornik 1865
#ifdef _R_HAVE_TIMING_
10172 luke 1866
double R_getClockIncrement(void);
1867
void R_getProcTime(double *data);
1868
 
1869
static double gctimes[5], gcstarttimes[5];
25199 luke 1870
static Rboolean gctime_enabled = FALSE;
10172 luke 1871
 
1872
SEXP do_gctime(SEXP call, SEXP op, SEXP args, SEXP env)
2 r 1873
{
19066 hornik 1874
    SEXP ans;
25199 luke 1875
    if (args == R_NilValue)
1876
	gctime_enabled = TRUE;
1877
    else
1878
	gctime_enabled = asLogical(CAR(args));
19066 hornik 1879
    ans = allocVector(REALSXP, 5);
1880
    REAL(ans)[0] = gctimes[0];
1881
    REAL(ans)[1] = gctimes[1];
1882
    REAL(ans)[2] = gctimes[2];
1883
    REAL(ans)[3] = gctimes[3];
1884
    REAL(ans)[4] = gctimes[4];
1885
    return ans;
10172 luke 1886
}
19066 hornik 1887
#else /* not _R_HAVE_TIMING_ */
1888
SEXP do_gctime(SEXP call, SEXP op, SEXP args, SEXP env)
1889
{
1890
    error("gc.time is not implemented on this system");
1891
    return R_NilValue;		/* -Wall */
1892
}
1893
#endif /* not _R_HAVE_TIMING_ */
10172 luke 1894
 
1895
static void gc_start_timing(void)
1896
{
19066 hornik 1897
#ifdef _R_HAVE_TIMING_
25199 luke 1898
    if (gctime_enabled)
1899
	R_getProcTime(gcstarttimes);
19066 hornik 1900
#endif /* _R_HAVE_TIMING_ */
10172 luke 1901
}
10407 maechler 1902
 
10172 luke 1903
static void gc_end_timing(void)
1904
{
19066 hornik 1905
#ifdef _R_HAVE_TIMING_
25199 luke 1906
    if (gctime_enabled) {
1907
	double times[5], delta;
1908
	R_getProcTime(times);
1909
	delta = R_getClockIncrement();
10172 luke 1910
 
25199 luke 1911
	/* add delta to compensate for timer resolution */
1912
	gctimes[0] += times[0] - gcstarttimes[0] + delta;
1913
	gctimes[1] += times[1] - gcstarttimes[1] + delta;
1914
	gctimes[2] += times[2] - gcstarttimes[2] + delta;
1915
	gctimes[3] += times[3] - gcstarttimes[3];
1916
	gctimes[4] += times[4] - gcstarttimes[4];
1917
    }
19066 hornik 1918
#endif /* _R_HAVE_TIMING_ */
10172 luke 1919
}
1920
 
20094 ripley 1921
static void R_gc_internal(R_size_t size_needed)
10172 luke 1922
{
20094 ripley 1923
    R_size_t vcells;
6366 ripley 1924
    double vfrac;
11390 luke 1925
    Rboolean first = TRUE;
2437 maechler 1926
 
11390 luke 1927
 again:
1928
 
1858 ihaka 1929
    gc_count++;
8686 luke 1930
 
1931
    BEGIN_SUSPEND_INTERRUPTS {
10172 luke 1932
      gc_start_timing();
1933
      RunGenCollect(size_needed);
1934
      gc_end_timing();
8686 luke 1935
    } END_SUSPEND_INTERRUPTS;
1936
 
1820 ihaka 1937
    if (gc_reporting) {
11116 ripley 1938
	REprintf("\n%d cons cells free (%d%%)\n",
1820 ihaka 1939
		 R_Collected, (100 * R_Collected / R_NSize));
10172 luke 1940
	vcells = VHEAP_FREE();
6366 ripley 1941
	vfrac = (100.0 * vcells) / R_VSize;
11197 ripley 1942
	/* arrange for percentage to be rounded down, or we get
11116 ripley 1943
	   `100% free' ! */
1944
	REprintf("%.1f Mbytes of heap free (%d%%)\n",
1945
		 vcells * sizeof(VECREC) / Mega, (int)vfrac);
1820 ihaka 1946
    }
11390 luke 1947
 
1948
    if (first) {
1949
	first = FALSE;
1950
	/* Run any eligible finalizers.  The return result of
1951
	   RunFinalizers is TRUE if any finalizers are actually run.
1952
	   There is a small chance that running finalizers here may
1953
	   chew up enough memory to make another immediate collection
1954
	   necessary.  If so, we jump back to the beginning and run
1955
	   the collection, but on this second pass we do not run
1956
	   finalizers. */
1957
	if (RunFinalizers() &&
1958
	    (NO_FREE_NODES() || size_needed > VHEAP_FREE()))
1959
	    goto again;
1960
    }
2 r 1961
}
1962
 
11197 ripley 1963
SEXP do_memlimits(SEXP call, SEXP op, SEXP args, SEXP env)
1964
{
1965
    SEXP ans;
20094 ripley 1966
    int nsize, vsize;
1967
    R_size_t tmp;
11197 ripley 1968
 
1969
    checkArity(op, args);
1970
    nsize = asInteger(CAR(args));
1971
    vsize = asInteger(CADR(args));
20094 ripley 1972
    if(nsize != NA_INTEGER) R_SetMaxNSize((R_size_t) nsize);
1973
    if(vsize != NA_INTEGER) R_SetMaxVSize((R_size_t) vsize);
11197 ripley 1974
    PROTECT(ans = allocVector(INTSXP, 2));
1975
    tmp = R_GetMaxNSize();
20094 ripley 1976
    INTEGER(ans)[0] = (tmp < INT_MAX) ? tmp : NA_INTEGER;
11197 ripley 1977
    tmp = R_GetMaxVSize();
20094 ripley 1978
    INTEGER(ans)[1] = (tmp < INT_MAX) ? tmp : NA_INTEGER;
11197 ripley 1979
    UNPROTECT(1);
1980
    return ans;
1981
}
2 r 1982
 
3558 r 1983
SEXP do_memoryprofile(SEXP call, SEXP op, SEXP args, SEXP env)
1984
{
1985
    SEXP ans, nms;
1986
    int i;
8686 luke 1987
 
15928 luke 1988
    PROTECT(ans = allocVector(INTSXP, 24));
1989
    PROTECT(nms = allocVector(STRSXP, 24));
1990
    for (i = 0; i < 24; i++) {
6994 pd 1991
        INTEGER(ans)[i] = 0;
10172 luke 1992
        SET_STRING_ELT(nms, i, R_BlankString);
3558 r 1993
    }
10172 luke 1994
    SET_STRING_ELT(nms, NILSXP, mkChar("NILSXP"));
1995
    SET_STRING_ELT(nms, SYMSXP, mkChar("SYMSXP"));
1996
    SET_STRING_ELT(nms, LISTSXP, mkChar("LISTSXP"));
1997
    SET_STRING_ELT(nms, CLOSXP, mkChar("CLOSXP"));
1998
    SET_STRING_ELT(nms, ENVSXP, mkChar("ENVSXP"));
1999
    SET_STRING_ELT(nms, PROMSXP, mkChar("PROMSXP"));
2000
    SET_STRING_ELT(nms, LANGSXP, mkChar("LANGSXP"));
2001
    SET_STRING_ELT(nms, SPECIALSXP, mkChar("SPECIALSXP"));
2002
    SET_STRING_ELT(nms, BUILTINSXP, mkChar("BUILTINSXP"));
2003
    SET_STRING_ELT(nms, CHARSXP, mkChar("CHARSXP"));
2004
    SET_STRING_ELT(nms, LGLSXP, mkChar("LGLSXP"));
2005
    SET_STRING_ELT(nms, INTSXP, mkChar("INTSXP"));
2006
    SET_STRING_ELT(nms, REALSXP, mkChar("REALSXP"));
2007
    SET_STRING_ELT(nms, CPLXSXP, mkChar("CPLXSXP"));
2008
    SET_STRING_ELT(nms, STRSXP, mkChar("STRSXP"));
2009
    SET_STRING_ELT(nms, DOTSXP, mkChar("DOTSXP"));
2010
    SET_STRING_ELT(nms, ANYSXP, mkChar("ANYSXP"));
2011
    SET_STRING_ELT(nms, VECSXP, mkChar("VECSXP"));
2012
    SET_STRING_ELT(nms, EXPRSXP, mkChar("EXPRSXP"));
26045 luke 2013
#ifdef BYTECODE
2014
    SET_STRING_ELT(nms, BCODESXP, mkChar("BCODESXP"));
2015
#endif
11390 luke 2016
    SET_STRING_ELT(nms, EXTPTRSXP, mkChar("EXTPTRSXP"));
15928 luke 2017
    SET_STRING_ELT(nms, WEAKREFSXP, mkChar("WEAKREFSXP"));
8686 luke 2018
    setAttrib(ans, R_NamesSymbol, nms);
2019
 
2020
    BEGIN_SUSPEND_INTERRUPTS {
10172 luke 2021
      int gen;
2022
 
2023
      /* run a full GC to make sure that all stuff in use in in Old space */
2024
      num_old_gens_to_collect = NUM_OLD_GENERATIONS;
2025
      R_gc();
2026
      for (gen = 0; gen < NUM_OLD_GENERATIONS; gen++) {
2027
	for (i = 0; i < NUM_NODE_CLASSES; i++) {
2028
	  SEXP s;
2029
	  for (s = NEXT_NODE(R_GenHeap[i].Old[gen]);
2030
	       s != R_GenHeap[i].Old[gen];
2031
	       s = NEXT_NODE(s))
2032
	    INTEGER(ans)[TYPEOF(s)]++;
2033
	}
2034
      }
8686 luke 2035
    } END_SUSPEND_INTERRUPTS;
3558 r 2036
    UNPROTECT(2);
2037
    return ans;
2038
}
2039
 
1820 ihaka 2040
/* "protect" push a single argument onto R_PPStack */
2041
 
26646 luke 2042
/* In handling a stack overflow we have to be careful not to use
2043
   PROTECT. error("protect(): stack overflow") would call deparse1,
2044
   which uses PROTECT and segfaults.*/
10407 maechler 2045
 
26646 luke 2046
/* However, the traceback creation in the normal error handler also
2047
   does a PROTECT, as does the jumping code, at least if there are
2048
   cleanup expressions to handle on the way out.  So for the moment
2049
   we'll allocate a slightly larger PP stack and only enable the added
2050
   red zone during handling of a stack overflow error.  LT */
2051
 
2052
static void reset_pp_stack(void *data)
2053
{
2054
    R_size_t *poldpps = data;
2055
    R_PPStackSize =  *poldpps;
2056
}
2579 pd 2057
SEXP protect(SEXP s)
2 r 2058
{
26646 luke 2059
    if (R_PPStackTop >= R_PPStackSize) {
2060
	RCNTXT cntxt;
2061
	R_size_t oldpps = R_PPStackSize;
2062
 
2063
	begincontext(&cntxt, CTXT_CCODE, R_NilValue, R_NilValue, R_NilValue,
2064
		     R_NilValue, R_NilValue);
2065
	cntxt.cend = &reset_pp_stack;
2066
	cntxt.cenddata = &oldpps;
2067
 
2068
	if (R_PPStackSize < R_RealPPStackSize)
2069
	    R_PPStackSize = R_RealPPStackSize;
11116 ripley 2070
	errorcall(R_NilValue, "protect(): stack overflow");
26646 luke 2071
 
2072
	endcontext(&cntxt); /* not reached */
2073
    }
8657 pd 2074
    R_PPStack[R_PPStackTop++] = s;
2579 pd 2075
    return s;
2 r 2076
}
2077
 
2078
 
1820 ihaka 2079
/* "unprotect" pop argument list from top of R_PPStack */
2080
 
2 r 2081
void unprotect(int l)
2082
{
8657 pd 2083
    if (R_PPStackTop >=  l)
2084
	R_PPStackTop -= l;
1820 ihaka 2085
    else
5731 ripley 2086
	error("unprotect(): stack imbalance");
2 r 2087
}
2088
 
2408 pd 2089
/* "unprotect_ptr" remove pointer from somewhere in R_PPStack */
2 r 2090
 
2408 pd 2091
void unprotect_ptr(SEXP s)
2092
{
2093
    int i = R_PPStackTop;
2437 maechler 2094
 
2408 pd 2095
    /* go look for  s  in  R_PPStack */
2096
    /* (should be among the top few items) */
2097
    do {
2098
    	if (i == 0)
5731 ripley 2099
	    error("unprotect_ptr: pointer not found");
2408 pd 2100
    } while ( R_PPStack[--i] != s );
2101
 
2102
    /* OK, got it, and  i  is indexing its location */
2103
    /* Now drop stack above it */
2104
 
2105
    do {
2106
    	R_PPStack[i] = R_PPStack[i + 1];
2107
    } while ( i++ < R_PPStackTop );
2108
 
2109
    R_PPStackTop--;
2110
}
2111
 
10776 luke 2112
void R_ProtectWithIndex(SEXP s, PROTECT_INDEX *pi)
2113
{
11116 ripley 2114
    protect(s);
2115
    *pi = R_PPStackTop - 1;
10776 luke 2116
}
2408 pd 2117
 
10776 luke 2118
void R_Reprotect(SEXP s, PROTECT_INDEX i)
2119
{
11116 ripley 2120
    R_PPStack[i] = s;
10776 luke 2121
}
2122
 
2123
 
1820 ihaka 2124
/* "initStack" initialize environment stack */
2 r 2125
void initStack(void)
2126
{
1820 ihaka 2127
    R_PPStackTop = 0;
2 r 2128
}
563 ihaka 2129
 
2130
 
3795 ripley 2131
/* S-like wrappers for calloc, realloc and free that check for error
2132
   conditions */
2133
 
2134
void *R_chk_calloc(size_t nelem, size_t elsize)
2135
{
3875 hornik 2136
    void *p;
15252 hornik 2137
#ifndef HAVE_WORKING_CALLOC
5377 hornik 2138
    if(nelem == 0)
2139
	return(NULL);
2140
#endif
3875 hornik 2141
    p = calloc(nelem, elsize);
10407 maechler 2142
    if(!p) error("Calloc could not allocate (%d of %d) memory", nelem, elsize);
3875 hornik 2143
    return(p);
3795 ripley 2144
}
2145
void *R_chk_realloc(void *ptr, size_t size)
2146
{
3875 hornik 2147
    void *p;
19853 ripley 2148
    /* Protect against broken realloc */
2149
    if(ptr) p = realloc(ptr, size); else p = malloc(size);
10407 maechler 2150
    if(!p) error("Realloc could not re-allocate (size %d) memory", size);
3875 hornik 2151
    return(p);
3795 ripley 2152
}
3875 hornik 2153
void R_chk_free(void *ptr)
3795 ripley 2154
{
6374 ripley 2155
    /* S-PLUS warns here, but there seems no reason to do so */
2156
    /* if(!ptr) warning("attempt to free NULL pointer by Free"); */
2157
    if(ptr) free(ptr); /* ANSI C says free has no effect on NULL, but
2158
			  better to be safe here */
3795 ripley 2159
}
4881 ihaka 2160
 
2161
/* This code keeps a list of objects which are not assigned to variables
2162
   but which are required to persist across garbage collections.  The
4887 ihaka 2163
   objects are registered with R_PreserveObject and deregistered with
25927 ripley 2164
   R_ReleaseObject. */
4881 ihaka 2165
 
2166
void R_PreserveObject(SEXP object)
2167
{
2168
    R_PreciousList = CONS(object, R_PreciousList);
2169
}
2170
 
2171
static SEXP RecursiveRelease(SEXP object, SEXP list)
2172
{
2173
    if (!isNull(list)) {
2174
        if (object == CAR(list))
2175
            return CDR(list);
2176
        else
2177
            CDR(list) = RecursiveRelease(object, CDR(list));
2178
    }
2179
    return list;
2180
}
2181
 
2182
void R_ReleaseObject(SEXP object)
2183
{
2184
    R_PreciousList =  RecursiveRelease(object, R_PreciousList);
2185
}
10172 luke 2186
 
10407 maechler 2187
 
11390 luke 2188
/* External Pointer Objects */
2189
SEXP R_MakeExternalPtr(void *p, SEXP tag, SEXP prot)
2190
{
2191
    SEXP s = allocSExp(EXTPTRSXP);
2192
    EXTPTR_PTR(s) = p;
2193
    EXTPTR_PROT(s) = prot;
2194
    EXTPTR_TAG(s) = tag;
2195
    return s;
2196
}
2197
 
2198
void *R_ExternalPtrAddr(SEXP s)
2199
{
2200
    return EXTPTR_PTR(s);
2201
}
2202
 
2203
SEXP R_ExternalPtrTag(SEXP s)
2204
{
2205
    return EXTPTR_TAG(s);
2206
}
2207
 
2208
SEXP R_ExternalPtrProtected(SEXP s)
2209
{
2210
    return EXTPTR_PROT(s);
2211
}
2212
 
2213
void R_ClearExternalPtr(SEXP s)
2214
{
2215
    EXTPTR_PTR(s) = NULL;
2216
}
2217
 
2218
void R_SetExternalPtrAddr(SEXP s, void *p)
2219
{
2220
    EXTPTR_PTR(s) = p;
2221
}
2222
 
2223
void R_SetExternalPtrTag(SEXP s, SEXP tag)
2224
{
2225
    CHECK_OLD_TO_NEW(s, tag);
2226
    EXTPTR_TAG(s) = tag;
2227
}
2228
 
2229
void R_SetExternalPtrProtected(SEXP s, SEXP p)
2230
{
2231
    CHECK_OLD_TO_NEW(s, p);
2232
    EXTPTR_PROT(s) = p;
2233
}
2234
 
2235
 
10172 luke 2236
/* The following functions are replacements for the accessor macros.
2237
   They are used by code that does not have direct access to the
2238
   internal representation of objects.  The assignment functions
2239
   implement the write barrier. */
2240
 
2241
/* General Cons Cell Attributes */
2242
SEXP (ATTRIB)(SEXP x) { return ATTRIB(x); }
2243
int (OBJECT)(SEXP x) { return OBJECT(x); }
2244
int (MARK)(SEXP x) { return MARK(x); }
2245
int (TYPEOF)(SEXP x) { return TYPEOF(x); }
2246
int (NAMED)(SEXP x) { return NAMED(x); }
2247
 
2248
void (SET_ATTRIB)(SEXP x, SEXP v) { CHECK_OLD_TO_NEW(x, v); ATTRIB(x) = v; }
2249
void (SET_OBJECT)(SEXP x, int v) { SET_OBJECT(x, v); }
2250
void (SET_TYPEOF)(SEXP x, int v) { SET_TYPEOF(x, v); }
2251
void (SET_NAMED)(SEXP x, int v) { SET_NAMED(x, v); }
2252
 
2253
/* Vector Accessors */
2254
int (LENGTH)(SEXP x) { return LENGTH(x); }
2255
int (TRUELENGTH)(SEXP x) { return TRUELENGTH(x); }
2256
char *(R_CHAR)(SEXP x) { return CHAR(x); }
2257
SEXP (STRING_ELT)(SEXP x, int i) { return STRING_ELT(x, i); }
2258
SEXP (VECTOR_ELT)(SEXP x, int i) { return VECTOR_ELT(x, i); }
2259
int (LEVELS)(SEXP x) { return LEVELS(x); }
2260
 
2261
int *(LOGICAL)(SEXP x) { return LOGICAL(x); }
2262
int *(INTEGER)(SEXP x) { return INTEGER(x); }
2263
double *(REAL)(SEXP x) { return REAL(x); }
2264
Rcomplex *(COMPLEX)(SEXP x) { return COMPLEX(x); }
2265
SEXP *(STRING_PTR)(SEXP x) { return STRING_PTR(x); }
2266
SEXP *(VECTOR_PTR)(SEXP x)
2267
{
2268
  error("not safe to return vector pointer");
2269
  return NULL;
2270
}
2271
 
2272
void (SETLENGTH)(SEXP x, int v) { SETLENGTH(x, v); }
2273
void (SET_TRUELENGTH)(SEXP x, int v) { SET_TRUELENGTH(x, v); }
2274
void (SET_STRING_ELT)(SEXP x, int i, SEXP v) { CHECK_OLD_TO_NEW(x, v); STRING_ELT(x, i) = v; }
2275
SEXP (SET_VECTOR_ELT)(SEXP x, int i, SEXP v) { CHECK_OLD_TO_NEW(x, v); return VECTOR_ELT(x, i) =v; }
2276
int (SETLEVELS)(SEXP x, int v) { return SETLEVELS(x, v); }
2277
 
2278
/* List Accessors */
2279
SEXP (TAG)(SEXP e) { return TAG(e); }
2280
SEXP (CAR)(SEXP e) { return CAR(e); }
2281
SEXP (CDR)(SEXP e) {return CDR(e); }
2282
SEXP (CAAR)(SEXP e) { return CAAR(e); }
2283
SEXP (CDAR)(SEXP e) { return CDAR(e); }
2284
SEXP (CADR)(SEXP e) { return CADR(e); }
2285
SEXP (CDDR)(SEXP e) { return CDDR(e); }
2286
SEXP (CADDR)(SEXP e) { return CADDR(e); }
2287
SEXP (CADDDR)(SEXP e) { return CADDDR(e); }
2288
SEXP (CAD4R)(SEXP e) { return CAD4R(e); }
2289
int (MISSING)(SEXP x) { return MISSING(x); }
2290
 
2291
void (SET_TAG)(SEXP x, SEXP v) { CHECK_OLD_TO_NEW(x, v); TAG(x) = v; }
2292
 
2293
SEXP (SETCAR)(SEXP x, SEXP y)
2294
{
2295
  if (x == NULL || x == R_NilValue)
2296
    error("bad value");
2297
  CHECK_OLD_TO_NEW(x, y);
2298
  CAR(x) = y;
2299
  return y;
2300
}
2301
 
2302
SEXP (SETCDR)(SEXP x, SEXP y)
2303
{
2304
  if (x == NULL || x == R_NilValue)
2305
    error("bad value");
2306
  CHECK_OLD_TO_NEW(x, y);
2307
  CDR(x) = y;
2308
  return y;
2309
}
2310
 
2311
SEXP (SETCADR)(SEXP x, SEXP y)
2312
{
2313
  SEXP cell;
2314
  if (x == NULL || x == R_NilValue ||
2315
      CDR(x) == NULL || CDR(x) == R_NilValue)
2316
    error("bad value");
2317
  cell = CDR(x);
2318
  CHECK_OLD_TO_NEW(cell, y);
2319
  CAR(cell) = y;
2320
  return y;
2321
}
2322
 
2323
SEXP (SETCADDR)(SEXP x, SEXP y)
2324
{
2325
  SEXP cell;
2326
  if (x == NULL || x == R_NilValue ||
2327
      CDR(x) == NULL || CDR(x) == R_NilValue ||
2328
      CDDR(x) == NULL || CDDR(x) == R_NilValue)
2329
    error("bad value");
2330
  cell = CDDR(x);
2331
  CHECK_OLD_TO_NEW(cell, y);
2332
  CAR(cell) = y;
2333
  return y;
2334
}
2335
 
2336
#define CDDDR(x) CDR(CDR(CDR(x)))
2337
 
2338
SEXP (SETCADDDR)(SEXP x, SEXP y)
2339
{
2340
  SEXP cell;
2341
  if (x == NULL || x == R_NilValue ||
2342
      CDR(x) == NULL || CDR(x) == R_NilValue ||
2343
      CDDR(x) == NULL || CDDR(x) == R_NilValue ||
2344
      CDDDR(x) == NULL || CDDDR(x) == R_NilValue)
2345
    error("bad value");
2346
  cell = CDDDR(x);
2347
  CHECK_OLD_TO_NEW(cell, y);
2348
  CAR(cell) = y;
2349
  return y;
2350
}
2351
 
2352
#define CD4R(x) CDR(CDR(CDR(CDR(x))))
2353
 
2354
SEXP (SETCAD4R)(SEXP x, SEXP y)
2355
{
2356
  SEXP cell;
2357
  if (x == NULL || x == R_NilValue ||
2358
      CDR(x) == NULL || CDR(x) == R_NilValue ||
2359
      CDDR(x) == NULL || CDDR(x) == R_NilValue ||
2360
      CDDDR(x) == NULL || CDDDR(x) == R_NilValue ||
2361
      CD4R(x) == NULL || CD4R(x) == R_NilValue)
2362
    error("bad value");
2363
  cell = CD4R(x);
2364
  CHECK_OLD_TO_NEW(cell, y);
2365
  CAR(cell) = y;
2366
  return y;
2367
}
2368
 
2369
void (SET_MISSING)(SEXP x, int v) { SET_MISSING(x, v); }
2370
 
2371
/* Closure Accessors */
2372
SEXP (FORMALS)(SEXP x) { return FORMALS(x); }
2373
SEXP (BODY)(SEXP x) { return BODY(x); }
2374
SEXP (CLOENV)(SEXP x) { return CLOENV(x); }
2375
int (DEBUG)(SEXP x) { return DEBUG(x); }
2376
int (TRACE)(SEXP x) { return TRACE(x); }
2377
 
2378
void (SET_FORMALS)(SEXP x, SEXP v) { CHECK_OLD_TO_NEW(x, v); FORMALS(x) = v; }
2379
void (SET_BODY)(SEXP x, SEXP v) { CHECK_OLD_TO_NEW(x, v); BODY(x) = v; }
2380
void (SET_CLOENV)(SEXP x, SEXP v) { CHECK_OLD_TO_NEW(x, v); CLOENV(x) = v; }
2381
void (SET_DEBUG)(SEXP x, int v) { SET_DEBUG(x, v); }
2382
void (SET_TRACE)(SEXP x, int v) { SET_TRACE(x, v); }
2383
 
2384
/* Primitive Accessors */
2385
int (PRIMOFFSET)(SEXP x) { return PRIMOFFSET(x); }
2386
 
2387
void (SET_PRIMOFFSET)(SEXP x, int v) { SET_PRIMOFFSET(x, v); }
2388
 
2389
/* Symbol Accessors */
2390
SEXP (PRINTNAME)(SEXP x) { return PRINTNAME(x); }
2391
SEXP (SYMVALUE)(SEXP x) { return SYMVALUE(x); }
2392
SEXP (INTERNAL)(SEXP x) { return INTERNAL(x); }
2393
int (DDVAL)(SEXP x) { return DDVAL(x); }
2394
 
2395
void (SET_PRINTNAME)(SEXP x, SEXP v) { CHECK_OLD_TO_NEW(x, v); PRINTNAME(x) = v; }
2396
void (SET_SYMVALUE)(SEXP x, SEXP v) { CHECK_OLD_TO_NEW(x, v); SYMVALUE(x) = v; }
2397
void (SET_INTERNAL)(SEXP x, SEXP v) { CHECK_OLD_TO_NEW(x, v); INTERNAL(x) = v; }
2398
void (SET_DDVAL)(SEXP x, int v) { SET_DDVAL(x, v); }
2399
 
2400
/* Environment Accessors */
2401
SEXP (FRAME)(SEXP x) { return FRAME(x); }
2402
SEXP (ENCLOS)(SEXP x) { return ENCLOS(x); }
2403
SEXP (HASHTAB)(SEXP x) { return HASHTAB(x); }
10383 luke 2404
int (ENVFLAGS)(SEXP x) { return ENVFLAGS(x); }
10172 luke 2405
 
2406
void (SET_FRAME)(SEXP x, SEXP v) { CHECK_OLD_TO_NEW(x, v); FRAME(x) = v; }
2407
void (SET_ENCLOS)(SEXP x, SEXP v) { CHECK_OLD_TO_NEW(x, v); ENCLOS(x) = v; }
2408
void (SET_HASHTAB)(SEXP x, SEXP v) { CHECK_OLD_TO_NEW(x, v); HASHTAB(x) = v; }
10383 luke 2409
void (SET_ENVFLAGS)(SEXP x, int v) { SET_ENVFLAGS(x, v); }
10172 luke 2410
 
2411
/* Promise Accessors */
26020 luke 2412
SEXP (PRCODE)(SEXP x) { return PRCODE(x); }
10172 luke 2413
SEXP (PRENV)(SEXP x) { return PRENV(x); }
2414
SEXP (PRVALUE)(SEXP x) { return PRVALUE(x); }
2415
int (PRSEEN)(SEXP x) { return PRSEEN(x); }
2416
 
2417
void (SET_PRENV)(SEXP x, SEXP v){ CHECK_OLD_TO_NEW(x, v); PRENV(x) = v; }
2418
void (SET_PRVALUE)(SEXP x, SEXP v) { CHECK_OLD_TO_NEW(x, v); PRVALUE(x) = v; }
2419
void (SET_PRSEEN)(SEXP x, int v) { SET_PRSEEN(x, v); }
2420
 
2421
/* Hashing Accessors */
2422
int (HASHASH)(SEXP x) { return HASHASH(x); }
2423
int (HASHVALUE)(SEXP x) { return HASHVALUE(x); }
2424
 
2425
void (SET_HASHASH)(SEXP x, int v) { SET_HASHASH(x, v); }
2426
void (SET_HASHVALUE)(SEXP x, int v) { SET_HASHVALUE(x, v); }