2
stacks.c -- Binding/History/Frame stacks.
5
Copyright (c) 1984, Taiichi Yuasa and Masami Hagiya.
6
Copyright (c) 1990, Giuseppe Attardi.
7
Copyright (c) 2001, Juan Jose Garcia Ripoll.
9
ECL is free software; you can redistribute it and/or
10
modify it under the terms of the GNU Library General Public
11
License as published by the Free Software Foundation; either
12
version 2 of the License, or (at your option) any later version.
14
See file '../Copyright' for full details.
18
#ifdef HAVE_SYS_RESOURCE_H
19
# include <sys/time.h>
20
# include <sys/resource.h>
23
/********************* BINDING STACK ************************/
27
bds_bind(cl_object s, cl_object value)
29
struct ecl_hashtable_entry *h = ecl_search_hash(s, cl_env.bindings_hash);
30
struct bds_bd *slot = ++cl_env.bds_top;
31
if (h->key == OBJNULL) {
32
/* The previous binding was at most global */
34
slot->value = OBJNULL;
35
sethash(s, cl_env.bindings_hash, value);
37
/* We have to save a dynamic binding */
38
slot->symbol = h->key;
39
slot->value = h->value;
42
s->symbol.dynamic |= 1;
48
struct ecl_hashtable_entry *h = ecl_search_hash(s, cl_env.bindings_hash);
49
struct bds_bd *slot = ++cl_env.bds_top;
50
if (h->key == OBJNULL) {
51
/* The previous binding was at most global */
53
slot->value = OBJNULL;
54
sethash(s, cl_env.bindings_hash, s->symbol.value);
56
/* We have to save a dynamic binding */
57
slot->symbol = h->key;
58
slot->value = h->value;
60
s->symbol.dynamic |= 1;
66
struct bds_bd *slot = cl_env.bds_top--;
67
cl_object s = slot->symbol;
68
struct ecl_hashtable_entry *h = ecl_search_hash(s, cl_env.bindings_hash);
69
if (slot->value == OBJNULL) {
70
/* We have deleted all dynamic bindings */
73
cl_env.bindings_hash->hash.entries--;
75
/* We restore the previous dynamic binding */
76
h->value = slot->value;
83
while (n--) bds_unwind1();
87
ecl_symbol_slot(cl_object s)
89
if (s->symbol.dynamic) {
90
struct ecl_hashtable_entry *h = ecl_search_hash(s, cl_env.bindings_hash);
91
if (h->key != OBJNULL)
94
return &s->symbol.value;
98
ecl_set_symbol(cl_object s, cl_object value)
100
if (s->symbol.dynamic) {
101
struct ecl_hashtable_entry *h = ecl_search_hash(s, cl_env.bindings_hash);
102
if (h->key != OBJNULL) {
103
return (h->value = value);
106
return (s->symbol.value = value);
114
if (cl_env.bds_limit > cl_env.bds_org + cl_env.bds_size)
115
error("bind stack overflow.");
116
cl_env.bds_limit += BDSGETA;
117
FEerror("Bind stack overflow.", 0);
121
bds_unwind(bds_ptr new_bds_top)
123
register bds_ptr bds = cl_env.bds_top;
124
for (; bds > new_bds_top; bds--)
128
bds->symbol->symbol.value = bds->value;
130
cl_env.bds_top = new_bds_top;
134
get_bds_ptr(cl_object x)
139
p = cl_env.bds_org + fix(x);
140
if (cl_env.bds_org <= p && p <= cl_env.bds_top)
143
FEerror("~S is an illegal bds index.", 1, x);
149
@(return MAKE_FIXNUM(cl_env.bds_top - cl_env.bds_org))
153
si_bds_var(cl_object arg)
155
@(return get_bds_ptr(arg)->symbol)
159
si_bds_val(cl_object arg)
161
@(return get_bds_ptr(arg)->value)
164
/******************** INVOCATION STACK **********************/
167
ihs_function_name(cl_object x)
171
switch (type_of(x)) {
176
y = x->bytecodes.name;
183
return(x->cfun.name);
191
get_ihs_ptr(cl_index n)
193
ihs_ptr p = cl_env.ihs_top;
195
FEerror("~D is an illegal IHS index.", 1, MAKE_FIXNUM(n));
202
ihs_top_function_name(void)
204
return ihs_function_name(cl_env.ihs_top->function);
208
si_ihs_top(cl_object name)
210
@(return MAKE_FIXNUM(cl_env.ihs_top->index))
214
si_ihs_prev(cl_object x)
220
si_ihs_next(cl_object x)
226
si_ihs_fun(cl_object arg)
228
@(return get_ihs_ptr(fixnnint(arg))->function)
232
si_ihs_env(cl_object arg)
234
@(return get_ihs_ptr(fixnnint(si_ihs_next(arg)))->lex_env)
237
/********************** FRAME STACK *************************/
239
static int frame_id = 0;
244
return(MAKE_FIXNUM(frame_id++));
248
frs_overflow(void) /* used as condition in list.d */
251
if (cl_env.frs_limit > cl_env.frs_org + cl_env.frs_size)
252
error("frame stack overflow.");
253
cl_env.frs_limit += FRSGETA;
254
FEerror("Frame stack overflow.", 0);
258
_frs_push(register cl_object val)
260
ecl_frame_ptr output = ++cl_env.frs_top;
261
if (output >= cl_env.frs_limit) frs_overflow();
262
output->frs_lex = cl_env.lex_env;
263
output->frs_bds_top = cl_env.bds_top;
264
output->frs_val = val;
265
output->frs_ihs = cl_env.ihs_top;
266
output->frs_sp = cl_stack_index();
271
unwind(ecl_frame_ptr fr)
274
while (cl_env.frs_top != fr && cl_env.frs_top->frs_val != ECL_PROTECT_TAG)
276
cl_env.lex_env = cl_env.frs_top->frs_lex;
277
cl_env.ihs_top = cl_env.frs_top->frs_ihs;
278
bds_unwind(cl_env.frs_top->frs_bds_top);
279
cl_stack_set_index(cl_env.frs_top->frs_sp);
280
ecl_longjmp(cl_env.frs_top->frs_jmpbuf, 1);
285
frs_sch (cl_object frame_id)
289
for (top = cl_env.frs_top; top >= cl_env.frs_org; top--)
290
if (top->frs_val == frame_id)
296
get_frame_ptr(cl_object x)
301
p = cl_env.frs_org + fix(x);
302
if (cl_env.frs_org <= p && p <= cl_env.frs_top)
305
FEerror("~S is an illegal frs index.", 1, x);
311
@(return MAKE_FIXNUM(cl_env.frs_top - cl_env.frs_org))
315
si_frs_bds(cl_object arg)
317
@(return MAKE_FIXNUM(get_frame_ptr(arg)->frs_bds_top - cl_env.bds_org))
321
si_frs_tag(cl_object arg)
323
@(return get_frame_ptr(arg)->frs_val)
327
si_frs_ihs(cl_object arg)
329
@(return MAKE_FIXNUM(get_frame_ptr(arg)->frs_ihs->index))
333
si_sch_frs_base(cl_object fr, cl_object ihs)
339
for (x = get_frame_ptr(fr);
340
x <= cl_env.frs_top && x->frs_ihs->index < y;
342
@(return ((x > cl_env.frs_top) ? Cnil : MAKE_FIXNUM(x - cl_env.frs_org)))
345
/********************* INITIALIZATION ***********************/
348
si_reset_stack_limits()
350
volatile int foo = 0;
351
if (cl_env.bds_top < cl_env.bds_org + (cl_env.bds_size - 2*BDSGETA))
352
cl_env.bds_limit = cl_env.bds_org + (cl_env.bds_size - 2*BDSGETA);
354
error("can't reset bds_limit.");
355
if (cl_env.frs_top < cl_env.frs_org + (cl_env.frs_size - 2*FRSGETA))
356
cl_env.frs_limit = cl_env.frs_org + (cl_env.frs_size - 2*FRSGETA);
358
error("can't reset frs_limit.");
360
if (&foo > cl_env.cs_org - cl_env.cs_size + 16)
361
cl_env.cs_limit = cl_env.cs_org - cl_env.cs_size;
363
if (&foo < cl_env.cs_org + cl_env.cs_size - 16)
364
cl_env.cs_limit = cl_env.cs_org + cl_env.cs_size;
367
error("can't reset cl_env.cs_limit.");
373
init_stacks(int *new_cs_org)
375
static struct ihs_frame ihs_org = { NULL, NULL, NULL, 0};
378
cl_env.frs_size = size = FRSSIZE + 2*FRSGETA;
379
cl_env.frs_org = (ecl_frame_ptr)cl_alloc_atomic(size * sizeof(*cl_env.frs_org));
380
cl_env.frs_top = cl_env.frs_org-1;
381
cl_env.frs_limit = &cl_env.frs_org[size - 2*FRSGETA];
382
cl_env.bds_size = size = BDSSIZE + 2*BDSGETA;
383
cl_env.bds_org = (bds_ptr)cl_alloc_atomic(size * sizeof(*cl_env.bds_org));
384
cl_env.bds_top = cl_env.bds_org-1;
385
cl_env.bds_limit = &cl_env.bds_org[size - 2*BDSGETA];
387
cl_env.ihs_top = &ihs_org;
388
ihs_org.function = @'si::top-level';
389
ihs_org.lex_env = Cnil;
392
cl_env.cs_org = new_cs_org;
393
#if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_STACK)
396
getrlimit(RLIMIT_STACK, &rl);
397
cl_env.cs_size = rl.rlim_cur/4 - 4*CSGETA;
400
cl_env.cs_size = CSSIZE;
403
/* Sanity check - in case rlimit is set too high */
404
if (cl_env.cs_org - cl_env.cs_size > cl_env.cs_org) {
405
cl_env.cs_size = CSSIZE;
407
cl_env.cs_limit = cl_env.cs_org - cl_env.cs_size; /* in THREADS I'm assigning to the main thread clwp */
409
/* Sanity check - in case rlimit is set too high */
410
if (cl_env.cs_org + cl_env.cs_size < cl_env.cs_org) {
411
cl_env.cs_size = CSSIZE;
413
cl_env.cs_limit = cl_env.cs_org + cl_env.cs_size;