1 /* -*-C-*-
2
3 Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
4 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Massachusetts
6 Institute of Technology
7
8 This file is part of MIT/GNU Scheme.
9
10 MIT/GNU Scheme is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or (at
13 your option) any later version.
14
15 MIT/GNU Scheme is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with MIT/GNU Scheme; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
23 USA.
24
25 */
26
27 /* Environment lookup, modification, and definition. */
28
29 #include "scheme.h"
30 #include "trap.h"
31 #include "lookup.h"
32
33 /* Hopefully a conservative guesstimate. */
34 #ifndef SPACE_PER_UUO_LINK /* So it can be overriden from config.h */
35 # define SPACE_PER_UUO_LINK 10
36 #endif
37
38 /* Cache objects are 3-tuples. */
39 #define SPACE_PER_CACHE 3
40
41 /* Each reference uses a pair and a weak pair, and potentially two
42 more pairs if the reference introduces a new name. */
43 #define SPACE_PER_REFERENCE 8
44
45 #define RETURN_IF_ERROR(expression) \
46 { \
47 long RIE_result = (expression); \
48 if (RIE_result != PRIM_DONE) \
49 return (RIE_result); \
50 }
51
52 #define DIE_IF_ERROR(expression) \
53 { \
54 if ((expression) != PRIM_DONE) \
55 { \
56 outf_fatal ("\nRan out of guaranteed space!\n"); \
57 Microcode_Termination (TERM_EXIT); \
58 } \
59 }
60
61 #define GC_CHECK(n) \
62 { \
63 if (GC_NEEDED_P (n)) \
64 { \
65 REQUEST_GC (n); \
66 return (PRIM_INTERRUPT); \
67 } \
68 }
69
70 #define MAP_TO_UNASSIGNED(value) \
71 (((value) == EXTERNAL_UNASSIGNED_OBJECT) \
72 ? UNASSIGNED_OBJECT \
73 : (value))
74
75 #define MAP_FROM_UNASSIGNED(value) \
76 (((value) == UNASSIGNED_OBJECT) \
77 ? EXTERNAL_UNASSIGNED_OBJECT \
78 : (value))
79
80 #define EXTERNAL_UNASSIGNED_OBJECT \
81 (VECTOR_REF (fixed_objects, NON_OBJECT))
82
83 #define PALIST_COND(palist_var) (PAIR_P (*palist_var))
84
85 #define PALIST_HEADER(palist_var, prefs_var) \
86 SCHEME_OBJECT * prefs_var = (PAIR_CDR_LOC (PAIR_CAR (*palist_var)));
87
88 #define PALIST_FOOTER(palist_var) do \
89 { \
90 if (PAIR_P (PAIR_CDR (PAIR_CAR (*palist_var)))) \
91 palist_var = (PAIR_CDR_LOC (*palist_var)); \
92 else \
93 (*palist_var) = (PAIR_CDR (*palist_var)); \
94 } while (false)
95
96 #define PREFS_COND(prefs_var) (PAIR_P (*prefs_var))
97
98 #define PREFS_HEADER(prefs_var) \
99 PREFS_HEADER_1 (prefs_var, (PAIR_CAR (*prefs_var)))
100
101 #define PREFS_HEADER_1(prefs_var, cache) \
102 { \
103 if ((GET_CACHE_REFERENCE_BLOCK (cache)) == SHARP_F) \
104 { \
105 (*prefs_var) = (PAIR_CDR (*prefs_var)); \
106 continue; \
107 } \
108 }
109
110 #define PREFS_FOOTER(prefs_var) do \
111 { \
112 prefs_var = (PAIR_CDR_LOC (*prefs_var)); \
113 } while (false)
114
115 #define WALK_REFERENCES(refs_pointer, ref_var, body) \
116 { \
117 SCHEME_OBJECT * WR_palist = (refs_pointer); \
118 while (PALIST_COND (WR_palist)) \
119 { \
120 PALIST_HEADER (WR_palist, WR_prefs); \
121 while (PREFS_COND (WR_prefs)) \
122 { \
123 SCHEME_OBJECT ref_var = (PAIR_CAR (*WR_prefs)); \
124 PREFS_HEADER_1 (WR_prefs, ref_var); \
125 body; \
126 PREFS_FOOTER (WR_prefs); \
127 } \
128 PALIST_FOOTER (WR_palist); \
129 } \
130 }
131
132 /***** Forward References *****/
133
134 static long lookup_variable_cache
135 (SCHEME_OBJECT, SCHEME_OBJECT *);
136 static long assign_variable_end
137 (SCHEME_OBJECT *, SCHEME_OBJECT, SCHEME_OBJECT *, int);
138 static long assign_variable_cache
139 (SCHEME_OBJECT, SCHEME_OBJECT, SCHEME_OBJECT *, int);
140 static long guarantee_extension_space
141 (SCHEME_OBJECT);
142 static long allocate_frame_extension
143 (unsigned long, SCHEME_OBJECT, SCHEME_OBJECT *);
144 static long unbind_cached_variable
145 (SCHEME_OBJECT *, SCHEME_OBJECT, SCHEME_OBJECT);
146 static void unbind_variable_1
147 (SCHEME_OBJECT *, SCHEME_OBJECT, SCHEME_OBJECT);
148 static unsigned long update_cache_refs_space
149 (SCHEME_OBJECT, SCHEME_OBJECT, SCHEME_OBJECT);
150 static unsigned long update_cache_refs_space_1
151 (SCHEME_OBJECT, unsigned int, SCHEME_OBJECT, SCHEME_OBJECT);
152 static long update_cache_references
153 (SCHEME_OBJECT, SCHEME_OBJECT *, SCHEME_OBJECT, SCHEME_OBJECT);
154 static SCHEME_OBJECT * find_binding_cell
155 (SCHEME_OBJECT, SCHEME_OBJECT, SCHEME_OBJECT *);
156 static SCHEME_OBJECT * scan_frame
157 (SCHEME_OBJECT, SCHEME_OBJECT, int);
158 static SCHEME_OBJECT * scan_procedure_bindings
159 (SCHEME_OBJECT, SCHEME_OBJECT, SCHEME_OBJECT, int);
160 static unsigned long count_references
161 (SCHEME_OBJECT *);
162 static void update_assignment_references
163 (SCHEME_OBJECT);
164 static long guarantee_cache
165 (SCHEME_OBJECT *);
166 static void update_clone
167 (SCHEME_OBJECT);
168 static long make_cache
169 (SCHEME_OBJECT, SCHEME_OBJECT, SCHEME_OBJECT, SCHEME_OBJECT *);
170
171 #ifdef CC_SUPPORT_P
172
173 static long update_uuo_links
174 (SCHEME_OBJECT, SCHEME_OBJECT);
175 static void move_all_references
176 (SCHEME_OBJECT, SCHEME_OBJECT, unsigned int);
177 static long add_cache_reference
178 (SCHEME_OBJECT, SCHEME_OBJECT, SCHEME_OBJECT, unsigned long, unsigned int);
179 static void add_reference
180 (SCHEME_OBJECT *, SCHEME_OBJECT, SCHEME_OBJECT, unsigned long);
181 static void install_cache
182 (SCHEME_OBJECT, SCHEME_OBJECT, unsigned long, unsigned int);
183 static void install_operator_cache
184 (SCHEME_OBJECT, SCHEME_OBJECT, unsigned long);
185 static unsigned long ref_pairs_to_move
186 (SCHEME_OBJECT *, SCHEME_OBJECT, SCHEME_OBJECT);
187 static void delete_ref_pairs
188 (SCHEME_OBJECT, unsigned int, SCHEME_OBJECT, SCHEME_OBJECT);
189 static void move_ref_pairs
190 (SCHEME_OBJECT, SCHEME_OBJECT, unsigned int, SCHEME_OBJECT, SCHEME_OBJECT);
191 static SCHEME_OBJECT * new_alist_entry
192 (SCHEME_OBJECT *, SCHEME_OBJECT);
193 static int move_ref_pair_p
194 (SCHEME_OBJECT, SCHEME_OBJECT);
195 static SCHEME_OBJECT * find_references_named
196 (SCHEME_OBJECT *, SCHEME_OBJECT);
197 static long make_cache_reference
198 (SCHEME_OBJECT, unsigned long, SCHEME_OBJECT *);
199
200 #endif
201
202 /***** Basic environment manipulation (lookup, assign, define). *****/
203
204 long
lookup_variable(SCHEME_OBJECT environment,SCHEME_OBJECT symbol,SCHEME_OBJECT * value_ret)205 lookup_variable (SCHEME_OBJECT environment, SCHEME_OBJECT symbol,
206 SCHEME_OBJECT * value_ret)
207 {
208 SCHEME_OBJECT * cell;
209 SCHEME_OBJECT value;
210
211 if (! ((ENVIRONMENT_P (environment)) && (SYMBOL_P (symbol))))
212 return (ERR_BAD_FRAME);
213
214 cell = (find_binding_cell (environment, symbol, 0));
215 if (cell == 0)
216 return (ERR_UNBOUND_VARIABLE);
217
218 value = (*cell);
219 switch (get_trap_kind (value))
220 {
221 case NON_TRAP_KIND:
222 (*value_ret) = value;
223 return (PRIM_DONE);
224
225 case TRAP_UNASSIGNED:
226 return (ERR_UNASSIGNED_VARIABLE);
227
228 case TRAP_UNBOUND:
229 return (ERR_UNBOUND_VARIABLE);
230
231 case TRAP_MACRO:
232 (*value_ret) = value;
233 return (ERR_MACRO_BINDING);
234
235 case TRAP_COMPILER_CACHED:
236 return (lookup_variable_cache ((GET_TRAP_CACHE (value)), value_ret));
237
238 default:
239 return (ERR_ILLEGAL_REFERENCE_TRAP);
240 }
241 }
242
243 static long
lookup_variable_cache(SCHEME_OBJECT cache,SCHEME_OBJECT * value_ret)244 lookup_variable_cache (SCHEME_OBJECT cache, SCHEME_OBJECT * value_ret)
245 {
246 SCHEME_OBJECT value = (GET_CACHE_VALUE (cache));
247 switch (get_trap_kind (value))
248 {
249 case NON_TRAP_KIND:
250 (*value_ret) = value;
251 return (PRIM_DONE);
252
253 case TRAP_UNASSIGNED:
254 return (ERR_UNASSIGNED_VARIABLE);
255
256 case TRAP_UNBOUND:
257 return (ERR_UNBOUND_VARIABLE);
258
259 case TRAP_MACRO:
260 (*value_ret) = value;
261 return (ERR_MACRO_BINDING);
262
263 default:
264 return (ERR_ILLEGAL_REFERENCE_TRAP);
265 }
266 }
267
268 long
safe_lookup_variable(SCHEME_OBJECT environment,SCHEME_OBJECT symbol,SCHEME_OBJECT * value_ret)269 safe_lookup_variable (SCHEME_OBJECT environment, SCHEME_OBJECT symbol,
270 SCHEME_OBJECT * value_ret)
271 {
272 long result = (lookup_variable (environment, symbol, value_ret));
273 if (result == ERR_UNASSIGNED_VARIABLE)
274 {
275 (*value_ret) = EXTERNAL_UNASSIGNED_OBJECT;
276 return (PRIM_DONE);
277 }
278 return (result);
279 }
280
281 long
variable_unassigned_p(SCHEME_OBJECT environment,SCHEME_OBJECT symbol,SCHEME_OBJECT * value_ret)282 variable_unassigned_p (SCHEME_OBJECT environment, SCHEME_OBJECT symbol,
283 SCHEME_OBJECT * value_ret)
284 {
285 SCHEME_OBJECT dummy_value;
286 long result = (lookup_variable (environment, symbol, (&dummy_value)));
287 switch (result)
288 {
289 case ERR_UNASSIGNED_VARIABLE:
290 (*value_ret) = SHARP_T;
291 return (PRIM_DONE);
292
293 case PRIM_DONE:
294 (*value_ret) = SHARP_F;
295 return (PRIM_DONE);
296
297 default:
298 return (result);
299 }
300 }
301
302 long
variable_unbound_p(SCHEME_OBJECT environment,SCHEME_OBJECT symbol,SCHEME_OBJECT * value_ret)303 variable_unbound_p (SCHEME_OBJECT environment, SCHEME_OBJECT symbol,
304 SCHEME_OBJECT * value_ret)
305 {
306 SCHEME_OBJECT dummy_value;
307 long result = (lookup_variable (environment, symbol, (&dummy_value)));
308 switch (result)
309 {
310 case ERR_UNBOUND_VARIABLE:
311 (*value_ret) = SHARP_T;
312 return (PRIM_DONE);
313
314 case ERR_UNASSIGNED_VARIABLE:
315 case ERR_MACRO_BINDING:
316 case PRIM_DONE:
317 (*value_ret) = SHARP_F;
318 return (PRIM_DONE);
319
320 default:
321 return (result);
322 }
323 }
324
325 long
variable_unreferenceable_p(SCHEME_OBJECT environment,SCHEME_OBJECT symbol,SCHEME_OBJECT * value_ret)326 variable_unreferenceable_p (SCHEME_OBJECT environment, SCHEME_OBJECT symbol,
327 SCHEME_OBJECT * value_ret)
328 {
329 SCHEME_OBJECT dummy_value;
330 long result = (lookup_variable (environment, symbol, (&dummy_value)));
331 switch (result)
332 {
333 case ERR_UNBOUND_VARIABLE:
334 case ERR_UNASSIGNED_VARIABLE:
335 case ERR_MACRO_BINDING:
336 (*value_ret) = SHARP_T;
337 return (PRIM_DONE);
338
339 case PRIM_DONE:
340 (*value_ret) = SHARP_F;
341 return (PRIM_DONE);
342
343 default:
344 return (result);
345 }
346 }
347
348 long
assign_variable(SCHEME_OBJECT environment,SCHEME_OBJECT symbol,SCHEME_OBJECT value,SCHEME_OBJECT * value_ret)349 assign_variable (SCHEME_OBJECT environment, SCHEME_OBJECT symbol,
350 SCHEME_OBJECT value, SCHEME_OBJECT * value_ret)
351 {
352 if (! ((ENVIRONMENT_P (environment)) || (SYMBOL_P (symbol))))
353 return (ERR_BAD_FRAME);
354 {
355 SCHEME_OBJECT * cell = (find_binding_cell (environment, symbol, 0));
356 if (cell == 0)
357 return (ERR_UNBOUND_VARIABLE);
358 return (assign_variable_end (cell, value, value_ret, 0));
359 }
360 }
361
362 static long
assign_variable_end(SCHEME_OBJECT * cell,SCHEME_OBJECT value,SCHEME_OBJECT * value_ret,int force_p)363 assign_variable_end (SCHEME_OBJECT * cell, SCHEME_OBJECT value,
364 SCHEME_OBJECT * value_ret, int force_p)
365 {
366 SCHEME_OBJECT old_value = (*cell);
367 switch (get_trap_kind (old_value))
368 {
369 case NON_TRAP_KIND:
370 case TRAP_UNASSIGNED:
371 break;
372
373 case TRAP_UNBOUND:
374 if (force_p)
375 break;
376 return (ERR_UNBOUND_VARIABLE);
377
378 case TRAP_MACRO:
379 if (force_p)
380 break;
381 return (ERR_MACRO_BINDING);
382
383 case TRAP_COMPILER_CACHED:
384 return
385 (assign_variable_cache
386 ((GET_TRAP_CACHE (old_value)), value, value_ret, force_p));
387
388 default:
389 return (ERR_ILLEGAL_REFERENCE_TRAP);
390 }
391 (*value_ret) = (MAP_FROM_UNASSIGNED (old_value));
392 (*cell) = (MAP_TO_UNASSIGNED (value));
393 return (PRIM_DONE);
394 }
395
396 static long
assign_variable_cache(SCHEME_OBJECT cache,SCHEME_OBJECT value,SCHEME_OBJECT * value_ret,int force_p)397 assign_variable_cache (SCHEME_OBJECT cache, SCHEME_OBJECT value,
398 SCHEME_OBJECT * value_ret, int force_p)
399 {
400 SCHEME_OBJECT old_value = (GET_CACHE_VALUE (cache));
401 switch (get_trap_kind (old_value))
402 {
403 case NON_TRAP_KIND:
404 case TRAP_UNASSIGNED:
405 break;
406
407 case TRAP_UNBOUND:
408 if (force_p)
409 break;
410 return (ERR_UNBOUND_VARIABLE);
411
412 case TRAP_MACRO:
413 if (force_p)
414 break;
415 return (ERR_MACRO_BINDING);
416
417 default:
418 return (ERR_ILLEGAL_REFERENCE_TRAP);
419 }
420 (*value_ret) = (MAP_FROM_UNASSIGNED (old_value));
421 /* Perform the assignment. If there are any operator references to
422 this variable, update their links. */
423 #ifdef CC_SUPPORT_P
424 if (PAIR_P (* (GET_CACHE_OPERATOR_REFERENCES (cache))))
425 return (update_uuo_links (cache, (MAP_TO_UNASSIGNED (value))));
426 #endif
427 SET_CACHE_VALUE (cache, (MAP_TO_UNASSIGNED (value)));
428 return (PRIM_DONE);
429 }
430
431 #ifdef CC_SUPPORT_P
432 static long
update_uuo_links(SCHEME_OBJECT cache,SCHEME_OBJECT new_value)433 update_uuo_links (SCHEME_OBJECT cache, SCHEME_OBJECT new_value)
434 {
435 GC_CHECK
436 (((count_references (GET_CACHE_OPERATOR_REFERENCES (cache)))
437 * SPACE_PER_UUO_LINK)
438 + SPACE_PER_CACHE);
439 SET_CACHE_VALUE (cache, new_value);
440 update_clone (cache);
441 WALK_REFERENCES
442 ((GET_CACHE_OPERATOR_REFERENCES (cache)),
443 reference,
444 {
445 install_operator_cache (cache,
446 (GET_CACHE_REFERENCE_BLOCK (reference)),
447 (GET_CACHE_REFERENCE_OFFSET (reference)));
448 });
449 return (PRIM_DONE);
450 }
451 #endif
452
453 long
define_variable(SCHEME_OBJECT environment,SCHEME_OBJECT symbol,SCHEME_OBJECT value)454 define_variable (SCHEME_OBJECT environment, SCHEME_OBJECT symbol,
455 SCHEME_OBJECT value)
456 {
457 if (! ((ENVIRONMENT_P (environment)) || (SYMBOL_P (symbol))))
458 return (ERR_BAD_FRAME);
459
460 /* If there is already a binding, just assign to it. */
461 {
462 SCHEME_OBJECT * cell = (scan_frame (environment, symbol, 1));
463 SCHEME_OBJECT old_value;
464 if (cell != 0)
465 {
466 if (GLOBAL_FRAME_P (environment))
467 strengthen_symbol (symbol);
468 return (assign_variable_end (cell, value, (&old_value), 1));
469 }
470 }
471
472 /* At this point, we know that environment can't be the global
473 environment, because scan_frame would have returned a non-null
474 pointer for the global environment. */
475
476 RETURN_IF_ERROR (guarantee_extension_space (environment));
477
478 /* If this binding shadows another binding, we'll have to recache
479 any references to the other binding, because some of them might
480 now refer to the new binding instead. */
481 {
482 SCHEME_OBJECT * shadowed_cell
483 = (find_binding_cell ((GET_FRAME_PARENT (environment)), symbol, 0));
484 SCHEME_OBJECT old_cache
485 = (((shadowed_cell != 0)
486 && ((get_trap_kind (*shadowed_cell)) == TRAP_COMPILER_CACHED))
487 ? (GET_TRAP_CACHE (*shadowed_cell))
488 : SHARP_F);
489 unsigned long length = (GET_EXTENDED_FRAME_LENGTH (environment));
490 SCHEME_OBJECT pair;
491
492 /* Make sure there is enough space available to move any
493 references that need moving. */
494 GC_CHECK
495 (2
496 + ((old_cache != SHARP_F)
497 ? (update_cache_refs_space (old_cache, environment, symbol))
498 : 0));
499
500 /* Create the binding. */
501 pair = (cons (symbol, (MAP_TO_UNASSIGNED (value))));
502 ((GET_EXTENDED_FRAME_BINDINGS (environment)) [length]) = pair;
503 SET_EXTENDED_FRAME_LENGTH (environment, (length + 1));
504
505 /* Move any references that need moving. */
506 return
507 ((old_cache != SHARP_F)
508 ? (update_cache_references
509 (old_cache, (PAIR_CDR_LOC (pair)), environment, symbol))
510 : PRIM_DONE);
511 }
512 }
513
514 static long
guarantee_extension_space(SCHEME_OBJECT environment)515 guarantee_extension_space (SCHEME_OBJECT environment)
516 {
517 if (EXTENDED_FRAME_P (environment))
518 /* Guarantee that there is room in the extension for a binding. */
519 {
520 unsigned long length = (GET_EXTENDED_FRAME_LENGTH (environment));
521 if (length == (GET_MAX_EXTENDED_FRAME_LENGTH (environment)))
522 {
523 SCHEME_OBJECT extension;
524 RETURN_IF_ERROR
525 (allocate_frame_extension
526 ((2 * length),
527 (GET_EXTENDED_FRAME_PROCEDURE (environment)),
528 (&extension)));
529 memcpy ((GET_FRAME_EXTENSION_BINDINGS (extension)),
530 (GET_EXTENDED_FRAME_BINDINGS (environment)),
531 (length * (sizeof (SCHEME_OBJECT))));
532 SET_FRAME_EXTENSION_LENGTH (extension, length);
533 SET_FRAME_EXTENSION (environment, extension);
534 }
535 }
536 else
537 /* There's no extension, so create one. */
538 {
539 SCHEME_OBJECT extension;
540 RETURN_IF_ERROR
541 (allocate_frame_extension (16,
542 (GET_FRAME_PROCEDURE (environment)),
543 (&extension)));
544 SET_FRAME_EXTENSION (environment, extension);
545 }
546 return (PRIM_DONE);
547 }
548
549 static long
allocate_frame_extension(unsigned long length,SCHEME_OBJECT procedure,SCHEME_OBJECT * extension_ret)550 allocate_frame_extension (unsigned long length, SCHEME_OBJECT procedure,
551 SCHEME_OBJECT * extension_ret)
552 {
553 unsigned long n_words = (ENV_EXTENSION_MIN_SIZE + length);
554 GC_CHECK (n_words);
555 {
556 SCHEME_OBJECT extension = (make_vector ((n_words - 1), SHARP_F, 0));
557 SET_FRAME_EXTENSION_PARENT_FRAME
558 (extension, (GET_PROCEDURE_ENVIRONMENT (procedure)));
559 SET_FRAME_EXTENSION_PROCEDURE (extension, procedure);
560 SET_FRAME_EXTENSION_LENGTH (extension, 0);
561 (*extension_ret) = extension;
562 return (PRIM_DONE);
563 }
564 }
565
566 long
link_variables(SCHEME_OBJECT target_environment,SCHEME_OBJECT target_symbol,SCHEME_OBJECT source_environment,SCHEME_OBJECT source_symbol)567 link_variables (SCHEME_OBJECT target_environment, SCHEME_OBJECT target_symbol,
568 SCHEME_OBJECT source_environment, SCHEME_OBJECT source_symbol)
569 {
570 SCHEME_OBJECT * source_cell;
571 trap_kind_t source_kind;
572 SCHEME_OBJECT * target_cell;
573
574 if (! ((ENVIRONMENT_P (target_environment))
575 && (ENVIRONMENT_P (source_environment))
576 && (SYMBOL_P (target_symbol))
577 && (SYMBOL_P (source_symbol))))
578 return (ERR_BAD_FRAME);
579
580 source_cell = (find_binding_cell (source_environment, source_symbol, 0));
581 if (source_cell == 0)
582 return (ERR_UNBOUND_VARIABLE);
583
584 source_kind = (get_trap_kind (*source_cell));
585 if (source_kind == TRAP_UNBOUND)
586 return (ERR_UNBOUND_VARIABLE);
587
588 target_cell = (scan_frame (target_environment, target_symbol, 1));
589 if (target_cell == source_cell)
590 return (PRIM_DONE);
591
592 if ((target_cell != 0) && (GLOBAL_FRAME_P (target_environment)))
593 strengthen_symbol (target_symbol);
594
595 if ((target_cell != 0)
596 && ((get_trap_kind (*target_cell)) == TRAP_COMPILER_CACHED))
597 {
598 SCHEME_OBJECT target_cache = (GET_TRAP_CACHE (*target_cell));
599 if (source_kind == TRAP_COMPILER_CACHED)
600 {
601 SCHEME_OBJECT source_cache = (GET_TRAP_CACHE (*source_cell));
602 if (source_cache == target_cache)
603 /* Already linked. */
604 return (PRIM_DONE);
605 GC_CHECK
606 (((count_references (GET_CACHE_OPERATOR_REFERENCES (target_cache)))
607 * SPACE_PER_UUO_LINK)
608 + (2 * SPACE_PER_CACHE));
609 SET_CACHE_VALUE (target_cache, (GET_CACHE_VALUE (source_cache)));
610 #ifdef CC_SUPPORT_P
611 move_all_references
612 (source_cache, target_cache, CACHE_REFERENCES_LOOKUP);
613 move_all_references
614 (source_cache, target_cache, CACHE_REFERENCES_ASSIGNMENT);
615 move_all_references
616 (source_cache, target_cache, CACHE_REFERENCES_OPERATOR);
617 #endif
618 update_clone (source_cache);
619 update_clone (target_cache);
620
621 /* Make sure both traps share the same cache: */
622 SET_TRAP_CACHE ((*source_cell), target_cache);
623 }
624 else
625 SET_CACHE_VALUE (target_cache, (*source_cell));
626 (*source_cell) = (*target_cell);
627 return (PRIM_DONE);
628 }
629
630 RETURN_IF_ERROR (guarantee_cache (source_cell));
631 return (define_variable (target_environment, target_symbol, (*source_cell)));
632 }
633
634 #ifdef CC_SUPPORT_P
635 static void
move_all_references(SCHEME_OBJECT from_cache,SCHEME_OBJECT to_cache,unsigned int reference_kind)636 move_all_references (SCHEME_OBJECT from_cache, SCHEME_OBJECT to_cache,
637 unsigned int reference_kind)
638 {
639 SCHEME_OBJECT * pfrom = (GET_CACHE_REFERENCES (from_cache, reference_kind));
640 SCHEME_OBJECT * pto = (GET_CACHE_REFERENCES (to_cache, reference_kind));
641
642 WALK_REFERENCES
643 (pfrom,
644 reference,
645 {
646 install_cache (to_cache,
647 (GET_CACHE_REFERENCE_BLOCK (reference)),
648 (GET_CACHE_REFERENCE_OFFSET (reference)),
649 reference_kind);
650 });
651
652 while (PAIR_P (*pto))
653 pto = (PAIR_CDR_LOC (*pto));
654 (*pto) = (*pfrom);
655 (*pfrom) = EMPTY_LIST;
656 }
657 #endif
658
659 long
unbind_variable(SCHEME_OBJECT environment,SCHEME_OBJECT symbol,SCHEME_OBJECT * value_ret)660 unbind_variable (SCHEME_OBJECT environment, SCHEME_OBJECT symbol,
661 SCHEME_OBJECT * value_ret)
662 {
663 SCHEME_OBJECT frame;
664 SCHEME_OBJECT * cell = (find_binding_cell (environment, symbol, (&frame)));
665 if (GLOBAL_FRAME_P (frame))
666 weaken_symbol (symbol);
667 switch ((cell == 0) ? TRAP_UNBOUND : (get_trap_kind (*cell)))
668 {
669 case TRAP_UNBOUND:
670 (*value_ret) = SHARP_F;
671 return (PRIM_DONE);
672
673 case NON_TRAP_KIND:
674 case TRAP_UNASSIGNED:
675 case TRAP_MACRO:
676 unbind_variable_1 (cell, frame, symbol);
677 (*value_ret) = SHARP_T;
678 return (PRIM_DONE);
679
680 case TRAP_COMPILER_CACHED:
681 {
682 SCHEME_OBJECT cache = (GET_TRAP_CACHE (*cell));
683 switch (get_trap_kind (GET_CACHE_VALUE (cache)))
684 {
685 case TRAP_UNBOUND:
686 (*value_ret) = SHARP_F;
687 return (PRIM_DONE);
688
689 case NON_TRAP_KIND:
690 case TRAP_UNASSIGNED:
691 case TRAP_MACRO:
692 if (PROCEDURE_FRAME_P (frame))
693 {
694 RETURN_IF_ERROR
695 (unbind_cached_variable (cell, frame, symbol));
696 }
697 else
698 {
699 SET_CACHE_VALUE (cache, UNBOUND_OBJECT);
700 }
701 (*value_ret) = SHARP_T;
702 return (PRIM_DONE);
703
704 default:
705 return (ERR_ILLEGAL_REFERENCE_TRAP);
706 }
707 }
708
709 default:
710 return (ERR_ILLEGAL_REFERENCE_TRAP);
711 }
712 }
713
714 static long
unbind_cached_variable(SCHEME_OBJECT * cell,SCHEME_OBJECT frame,SCHEME_OBJECT symbol)715 unbind_cached_variable (SCHEME_OBJECT * cell, SCHEME_OBJECT frame,
716 SCHEME_OBJECT symbol)
717 {
718 SCHEME_OBJECT cache = (GET_TRAP_CACHE (*cell));
719 SCHEME_OBJECT * shadowed_cell
720 = (find_binding_cell ((GET_FRAME_PARENT (frame)), symbol, 0));
721 GC_CHECK (update_cache_refs_space (cache, frame, symbol));
722 unbind_variable_1 (cell, frame, symbol);
723 return (update_cache_references (cache, shadowed_cell, frame, symbol));
724 }
725
726 static void
unbind_variable_1(SCHEME_OBJECT * cell,SCHEME_OBJECT frame,SCHEME_OBJECT symbol)727 unbind_variable_1 (SCHEME_OBJECT * cell,
728 SCHEME_OBJECT frame, SCHEME_OBJECT symbol)
729 {
730 if ((PROCEDURE_FRAME_P (frame)) && (EXTENDED_FRAME_P (frame)))
731 {
732 SCHEME_OBJECT * start = (GET_EXTENDED_FRAME_BINDINGS (frame));
733 unsigned long length = (GET_EXTENDED_FRAME_LENGTH (frame));
734 unsigned long index = 0;
735 while (index < length)
736 {
737 if ((PAIR_CAR (start[index])) == symbol)
738 {
739 if (index < (length - 1))
740 (start[index]) = (start [length - 1]);
741 SET_EXTENDED_FRAME_LENGTH (frame, (length - 1));
742 (start [length - 1]) = SHARP_F;
743 return;
744 }
745 index += 1;
746 }
747 }
748 (*cell) = UNBOUND_OBJECT;
749 }
750
751 /***** Interface to compiled code. *****/
752
753 #ifdef CC_SUPPORT_P
754
755 long
compiler_cache_lookup(SCHEME_OBJECT name,SCHEME_OBJECT block,unsigned long offset)756 compiler_cache_lookup (SCHEME_OBJECT name, SCHEME_OBJECT block,
757 unsigned long offset)
758 {
759 return
760 (add_cache_reference ((cc_block_environment (block)),
761 name, block, offset,
762 CACHE_REFERENCES_LOOKUP));
763 }
764
765 long
compiler_cache_assignment(SCHEME_OBJECT name,SCHEME_OBJECT block,unsigned long offset)766 compiler_cache_assignment (SCHEME_OBJECT name, SCHEME_OBJECT block,
767 unsigned long offset)
768 {
769 return
770 (add_cache_reference ((cc_block_environment (block)),
771 name, block, offset,
772 CACHE_REFERENCES_ASSIGNMENT));
773 }
774
775 long
compiler_cache_operator(SCHEME_OBJECT name,SCHEME_OBJECT block,unsigned long offset)776 compiler_cache_operator (SCHEME_OBJECT name, SCHEME_OBJECT block,
777 unsigned long offset)
778 {
779 return
780 (add_cache_reference ((cc_block_environment (block)),
781 name, block, offset,
782 CACHE_REFERENCES_OPERATOR));
783 }
784
785 long
compiler_cache_global_operator(SCHEME_OBJECT name,SCHEME_OBJECT block,unsigned long offset)786 compiler_cache_global_operator (SCHEME_OBJECT name, SCHEME_OBJECT block,
787 unsigned long offset)
788 {
789 return
790 (add_cache_reference (THE_GLOBAL_ENV,
791 name, block, offset,
792 CACHE_REFERENCES_OPERATOR));
793 }
794
795 SCHEME_OBJECT
compiler_var_error(SCHEME_OBJECT cache,SCHEME_OBJECT block,unsigned int reference_kind)796 compiler_var_error (SCHEME_OBJECT cache, SCHEME_OBJECT block,
797 unsigned int reference_kind)
798 {
799 WALK_REFERENCES
800 ((GET_CACHE_REFERENCES (cache, reference_kind)),
801 reference,
802 {
803 /* If this reference is in the right block, return the symbol
804 being referenced. */
805 if ((GET_CACHE_REFERENCE_BLOCK (reference)) == block)
806 return (PAIR_CAR (PAIR_CAR (*WR_palist)));
807 });
808 return (SHARP_F);
809 }
810
811 long
compiler_lookup_trap(SCHEME_OBJECT cache,SCHEME_OBJECT * value_ret)812 compiler_lookup_trap (SCHEME_OBJECT cache, SCHEME_OBJECT * value_ret)
813 {
814 return (lookup_variable_cache (cache, value_ret));
815 }
816
817 long
compiler_safe_lookup_trap(SCHEME_OBJECT cache,SCHEME_OBJECT * value_ret)818 compiler_safe_lookup_trap (SCHEME_OBJECT cache, SCHEME_OBJECT * value_ret)
819 {
820 long result = (lookup_variable_cache (cache, value_ret));
821 if (result == ERR_UNASSIGNED_VARIABLE)
822 {
823 (*value_ret) = EXTERNAL_UNASSIGNED_OBJECT;
824 return (PRIM_DONE);
825 }
826 return (result);
827 }
828
829 long
compiler_unassigned_p_trap(SCHEME_OBJECT cache,SCHEME_OBJECT * value_ret)830 compiler_unassigned_p_trap (SCHEME_OBJECT cache, SCHEME_OBJECT * value_ret)
831 {
832 SCHEME_OBJECT dummy_value;
833 long result = (lookup_variable_cache (cache, (&dummy_value)));
834 switch (result)
835 {
836 case ERR_UNASSIGNED_VARIABLE:
837 (*value_ret) = SHARP_T;
838 return (PRIM_DONE);
839
840 case PRIM_DONE:
841 (*value_ret) = SHARP_F;
842 return (PRIM_DONE);
843
844 default:
845 return (result);
846 }
847 }
848
849 long
compiler_assignment_trap(SCHEME_OBJECT cache,SCHEME_OBJECT value,SCHEME_OBJECT * value_ret)850 compiler_assignment_trap (SCHEME_OBJECT cache, SCHEME_OBJECT value,
851 SCHEME_OBJECT * value_ret)
852 {
853 return
854 (assign_variable_cache
855 ((((GET_CACHE_VALUE (cache)) == EXPENSIVE_OBJECT)
856 /* The cache is a clone. Get the real cache object. */
857 ? (GET_CACHE_CLONE (cache))
858 : cache),
859 value,
860 value_ret,
861 0));
862 }
863
864 long
compiler_operator_reference_trap(SCHEME_OBJECT cache,SCHEME_OBJECT * value_ret)865 compiler_operator_reference_trap (SCHEME_OBJECT cache,
866 SCHEME_OBJECT * value_ret)
867 {
868 return (lookup_variable_cache (cache, value_ret));
869 }
870
871 /***** Variable-reference cache mechanism. *****/
872
873 /* add_cache_reference adds a reference to a variable's cache,
874 creating the cache if necessary. It takes the following arguments:
875
876 + environment and symbol specify the affected variable.
877
878 + block is a compiled-code block, and offset is an offset into
879 block. Together, these specify the location where the variable
880 cache is to be stored.
881
882 + reference_kind specifies the kind of reference that is being cached.
883
884 add_cache_reference creates a variable cache for the specified variable,
885 if needed, and stores it in the location specified by (block,
886 offset). It adds the (block,offset) reference to the appropriate
887 reference list for subsequent updating.
888
889 If the reference is a lookup reference, the cache is directly
890 stored in the block.
891
892 If the reference is an assignment reference, and there are no
893 operator references to this variable, the cache is directly stored
894 in the block.
895
896 If the reference is an assignment reference, and there _are_
897 operator references to this variable, a "clone" cache is stored in
898 the block. The "clone" cache has a value of EXPENSIVE_OBJECT,
899 which causes any assignment to this cell to trap out to the
900 microcode, where the expensive process of updating all the related
901 operator references can be performed.
902
903 If the reference is an operator reference, a "UUO" link is stored
904 in the block. If the variable's value is a compiled procedure, the
905 UUO link is a direct reference to the procedure. In all other
906 cases it is a dummy procedure that redirects as needed. If there
907 are assignment references to this variable but no "clone" cache,
908 one is created and all the assignment references updated to point
909 to it. */
910
911 static long
add_cache_reference(SCHEME_OBJECT environment,SCHEME_OBJECT symbol,SCHEME_OBJECT block,unsigned long offset,unsigned int reference_kind)912 add_cache_reference (SCHEME_OBJECT environment, SCHEME_OBJECT symbol,
913 SCHEME_OBJECT block, unsigned long offset,
914 unsigned int reference_kind)
915 {
916 SCHEME_OBJECT frame = 0;
917 SCHEME_OBJECT * cell = (find_binding_cell (environment, symbol, (&frame)));
918 SCHEME_OBJECT dummy_cell = UNBOUND_OBJECT;
919 if (cell == 0)
920 /* There's no binding for the variable, and we don't have access
921 to the global environment. The compiled code needs a cache, so
922 we'll install one, but it won't be attached to any environment
923 structure. */
924 cell = (&dummy_cell);
925 else if (GLOBAL_FRAME_P (frame))
926 strengthen_symbol (symbol);
927 /* This procedure must complete to keep the data structures
928 consistent, so we do a GC check in advance to guarantee that all
929 of the allocations will finish. */
930 GC_CHECK ((2 * SPACE_PER_CACHE) + SPACE_PER_REFERENCE + SPACE_PER_UUO_LINK);
931 DIE_IF_ERROR (guarantee_cache (cell));
932 {
933 SCHEME_OBJECT cache = (GET_TRAP_CACHE (*cell));
934 add_reference
935 ((GET_CACHE_REFERENCES (cache, reference_kind)), symbol, block, offset);
936 update_clone (cache);
937 install_cache (cache, block, offset, reference_kind);
938 }
939 return (PRIM_DONE);
940 }
941
942 /* Add a new cached reference to the cached reference list pointed at
943 by slot. Attempt to reuse pairs which have been "emptied" by the
944 garbage collector. */
945
946 static void
add_reference(SCHEME_OBJECT * palist,SCHEME_OBJECT symbol,SCHEME_OBJECT block,unsigned long offset)947 add_reference (SCHEME_OBJECT * palist,
948 SCHEME_OBJECT symbol, SCHEME_OBJECT block, unsigned long offset)
949 {
950 SCHEME_OBJECT * prefs = (find_references_named (palist, symbol));
951 if (prefs != 0)
952 {
953 while (PREFS_COND (prefs))
954 {
955 if ((GET_CACHE_REFERENCE_BLOCK (PAIR_CAR (*prefs))) == SHARP_F)
956 {
957 /* Reuse this pair. */
958 SET_CACHE_REFERENCE_BLOCK ((PAIR_CAR (*prefs)), block);
959 SET_CACHE_REFERENCE_OFFSET ((PAIR_CAR (*prefs)), offset);
960 return;
961 }
962 PREFS_FOOTER (prefs);
963 }
964 {
965 SCHEME_OBJECT reference;
966 DIE_IF_ERROR (make_cache_reference (block, offset, (&reference)));
967 (*prefs) = (cons (reference, EMPTY_LIST));
968 }
969 return;
970 }
971 {
972 SCHEME_OBJECT reference;
973 SCHEME_OBJECT alist;
974 DIE_IF_ERROR (make_cache_reference (block, offset, (&reference)));
975 alist = (*palist);
976 (*palist) = (cons ((cons (symbol, (cons (reference, EMPTY_LIST)))), alist));
977 }
978 }
979
980 static void
install_cache(SCHEME_OBJECT cache,SCHEME_OBJECT block,unsigned long offset,unsigned int reference_kind)981 install_cache (SCHEME_OBJECT cache, SCHEME_OBJECT block, unsigned long offset,
982 unsigned int reference_kind)
983 {
984 switch (reference_kind)
985 {
986 case CACHE_REFERENCES_LOOKUP:
987 write_variable_cache (cache, block, offset);
988 break;
989
990 case CACHE_REFERENCES_ASSIGNMENT:
991 write_variable_cache
992 ((((GET_CACHE_CLONE (cache)) != SHARP_F)
993 ? (GET_CACHE_CLONE (cache))
994 : cache),
995 block,
996 offset);
997 break;
998
999 case CACHE_REFERENCES_OPERATOR:
1000 install_operator_cache (cache, block, offset);
1001 break;
1002
1003 default:
1004 abort ();
1005 break;
1006 }
1007 }
1008
1009 static void
install_operator_cache(SCHEME_OBJECT cache,SCHEME_OBJECT block,unsigned long offset)1010 install_operator_cache (SCHEME_OBJECT cache,
1011 SCHEME_OBJECT block, unsigned long offset)
1012 {
1013 SCHEME_OBJECT value = (GET_CACHE_VALUE (cache));
1014 DIE_IF_ERROR (make_uuo_link (value, cache, block, offset));
1015 }
1016
1017 #endif /* CC_SUPPORT_P */
1018
1019 static unsigned long
update_cache_refs_space(SCHEME_OBJECT from_cache,SCHEME_OBJECT environment,SCHEME_OBJECT symbol)1020 update_cache_refs_space (SCHEME_OBJECT from_cache, SCHEME_OBJECT environment,
1021 SCHEME_OBJECT symbol)
1022 {
1023 #ifdef CC_SUPPORT_P
1024 return
1025 ((update_cache_refs_space_1
1026 (from_cache, CACHE_REFERENCES_LOOKUP, environment, symbol))
1027 + (update_cache_refs_space_1
1028 (from_cache, CACHE_REFERENCES_ASSIGNMENT, environment, symbol))
1029 + (update_cache_refs_space_1
1030 (from_cache, CACHE_REFERENCES_OPERATOR, environment, symbol)));
1031 #else
1032 return (0);
1033 #endif
1034 }
1035
1036 /* Generate a conservative estimate of the space needed to move some
1037 cache refs from one cache to another. */
1038
1039 static unsigned long
update_cache_refs_space_1(SCHEME_OBJECT from_cache,unsigned int kind,SCHEME_OBJECT environment,SCHEME_OBJECT symbol)1040 update_cache_refs_space_1 (SCHEME_OBJECT from_cache, unsigned int kind,
1041 SCHEME_OBJECT environment, SCHEME_OBJECT symbol)
1042 {
1043 SCHEME_OBJECT * from_palist = (GET_CACHE_REFERENCES (from_cache, kind));
1044 unsigned long n_refs = (ref_pairs_to_move (from_palist, environment, symbol));
1045 unsigned long result = 0;
1046 if (n_refs > 0)
1047 {
1048 /* Space for new cache and new alist entry, if needed. */
1049 result += (SPACE_PER_CACHE + 4);
1050 if (kind == CACHE_REFERENCES_OPERATOR)
1051 /* space for new trampolines, if needed. */
1052 result += (n_refs * SPACE_PER_UUO_LINK);
1053 }
1054 return (result);
1055 }
1056
1057 static long
update_cache_references(SCHEME_OBJECT from_cache,SCHEME_OBJECT * to_cell,SCHEME_OBJECT environment,SCHEME_OBJECT symbol)1058 update_cache_references (SCHEME_OBJECT from_cache, SCHEME_OBJECT * to_cell,
1059 SCHEME_OBJECT environment, SCHEME_OBJECT symbol)
1060 {
1061 if (to_cell != 0)
1062 {
1063 DIE_IF_ERROR (guarantee_cache (to_cell));
1064 {
1065 SCHEME_OBJECT to_cache = (GET_TRAP_CACHE (*to_cell));
1066 #ifdef CC_SUPPORT_P
1067 move_ref_pairs
1068 (from_cache, to_cache, CACHE_REFERENCES_LOOKUP,
1069 environment, symbol);
1070 move_ref_pairs
1071 (from_cache, to_cache, CACHE_REFERENCES_ASSIGNMENT,
1072 environment, symbol);
1073 move_ref_pairs
1074 (from_cache, to_cache, CACHE_REFERENCES_OPERATOR,
1075 environment, symbol);
1076 #endif
1077 update_clone (to_cache);
1078 }
1079 }
1080 #ifdef CC_SUPPORT_P
1081 else
1082 {
1083 delete_ref_pairs
1084 (from_cache, CACHE_REFERENCES_LOOKUP, environment, symbol);
1085 delete_ref_pairs
1086 (from_cache, CACHE_REFERENCES_ASSIGNMENT, environment, symbol);
1087 delete_ref_pairs
1088 (from_cache, CACHE_REFERENCES_OPERATOR, environment, symbol);
1089 }
1090 #endif
1091 update_clone (from_cache);
1092 return (PRIM_DONE);
1093 }
1094
1095 #ifdef CC_SUPPORT_P
1096
1097 static unsigned long
ref_pairs_to_move(SCHEME_OBJECT * palist,SCHEME_OBJECT environment,SCHEME_OBJECT symbol)1098 ref_pairs_to_move (SCHEME_OBJECT * palist, SCHEME_OBJECT environment,
1099 SCHEME_OBJECT symbol)
1100 {
1101 SCHEME_OBJECT * prefs = (find_references_named (palist, symbol));
1102 unsigned long n_refs = 0;
1103 if (prefs != 0)
1104 while (PREFS_COND (prefs))
1105 {
1106 PREFS_HEADER (prefs);
1107 if (move_ref_pair_p ((*prefs), environment))
1108 n_refs += 1;
1109 PREFS_FOOTER (prefs);
1110 }
1111 return (n_refs);
1112 }
1113
1114 static void
delete_ref_pairs(SCHEME_OBJECT from_cache,unsigned int kind,SCHEME_OBJECT environment,SCHEME_OBJECT symbol)1115 delete_ref_pairs (SCHEME_OBJECT from_cache, unsigned int kind,
1116 SCHEME_OBJECT environment, SCHEME_OBJECT symbol)
1117 {
1118 SCHEME_OBJECT * from_palist = (GET_CACHE_REFERENCES (from_cache, kind));
1119 SCHEME_OBJECT * from_prefs = (find_references_named (from_palist, symbol));
1120 if (from_prefs != 0)
1121 while (PREFS_COND (from_prefs))
1122 {
1123 PREFS_HEADER (from_prefs);
1124 if (move_ref_pair_p ((*from_prefs), environment))
1125 {
1126 (*from_prefs) = (PAIR_CDR (*from_prefs));
1127 continue;
1128 }
1129 PREFS_FOOTER (from_prefs);
1130 }
1131 }
1132
1133 static void
move_ref_pairs(SCHEME_OBJECT from_cache,SCHEME_OBJECT to_cache,unsigned int reference_kind,SCHEME_OBJECT environment,SCHEME_OBJECT symbol)1134 move_ref_pairs (SCHEME_OBJECT from_cache, SCHEME_OBJECT to_cache,
1135 unsigned int reference_kind, SCHEME_OBJECT environment,
1136 SCHEME_OBJECT symbol)
1137 {
1138 SCHEME_OBJECT * from_palist
1139 = (GET_CACHE_REFERENCES (from_cache, reference_kind));
1140 SCHEME_OBJECT * to_palist
1141 = (GET_CACHE_REFERENCES (to_cache, reference_kind));
1142 SCHEME_OBJECT * from_prefs = (find_references_named (from_palist, symbol));
1143 SCHEME_OBJECT * to_prefs = (find_references_named (to_palist, symbol));
1144 if (from_prefs != 0)
1145 while (PREFS_COND (from_prefs))
1146 {
1147 PREFS_HEADER (from_prefs);
1148 if (move_ref_pair_p ((*from_prefs), environment))
1149 {
1150 SCHEME_OBJECT p = (*from_prefs);
1151 (*from_prefs) = (PAIR_CDR (p));
1152 if (to_prefs == 0)
1153 to_prefs = (new_alist_entry (to_palist, symbol));
1154 SET_PAIR_CDR (p, (*to_prefs));
1155 (*to_prefs) = p;
1156 install_cache (to_cache,
1157 (GET_CACHE_REFERENCE_BLOCK (PAIR_CAR (p))),
1158 (GET_CACHE_REFERENCE_OFFSET (PAIR_CAR (p))),
1159 reference_kind);
1160 continue;
1161 }
1162 PREFS_FOOTER (from_prefs);
1163 }
1164 }
1165
1166 static SCHEME_OBJECT *
new_alist_entry(SCHEME_OBJECT * to_palist,SCHEME_OBJECT symbol)1167 new_alist_entry (SCHEME_OBJECT * to_palist, SCHEME_OBJECT symbol)
1168 {
1169 SCHEME_OBJECT entry = (cons (symbol, EMPTY_LIST));
1170 SCHEME_OBJECT head = (*to_palist);
1171 (*to_palist) = (cons (entry, head));
1172 return (PAIR_CDR_LOC (entry));
1173 }
1174
1175 static int
move_ref_pair_p(SCHEME_OBJECT ref_pair,SCHEME_OBJECT ancestor)1176 move_ref_pair_p (SCHEME_OBJECT ref_pair, SCHEME_OBJECT ancestor)
1177 {
1178 SCHEME_OBJECT descendant
1179 = (cc_block_environment
1180 (GET_CACHE_REFERENCE_BLOCK (PAIR_CAR (ref_pair))));
1181 while (PROCEDURE_FRAME_P (descendant))
1182 {
1183 if (descendant == ancestor)
1184 return (1);
1185 descendant = (GET_FRAME_PARENT (descendant));
1186 }
1187 return (descendant == ancestor);
1188 }
1189
1190 #endif /* CC_SUPPORT_P */
1191
1192 /***** Utilities *****/
1193
1194 static SCHEME_OBJECT *
find_binding_cell(SCHEME_OBJECT environment,SCHEME_OBJECT symbol,SCHEME_OBJECT * frame_ret)1195 find_binding_cell (SCHEME_OBJECT environment, SCHEME_OBJECT symbol,
1196 SCHEME_OBJECT * frame_ret)
1197 {
1198 SCHEME_OBJECT frame = environment;
1199 while (1)
1200 {
1201 SCHEME_OBJECT * cell = (scan_frame (frame, symbol, 0));
1202 if ((cell != 0) || (!PROCEDURE_FRAME_P (frame)))
1203 {
1204 if (frame_ret != 0)
1205 (*frame_ret) = frame;
1206 return (cell);
1207 }
1208 frame = (GET_FRAME_PARENT (frame));
1209 }
1210 }
1211
1212 static SCHEME_OBJECT *
scan_frame(SCHEME_OBJECT frame,SCHEME_OBJECT symbol,int find_unbound_p)1213 scan_frame (SCHEME_OBJECT frame, SCHEME_OBJECT symbol, int find_unbound_p)
1214 {
1215 if (PROCEDURE_FRAME_P (frame))
1216 {
1217 if (EXTENDED_FRAME_P (frame))
1218 {
1219 /* Search for a binding in the extension. */
1220 SCHEME_OBJECT * scan = (GET_EXTENDED_FRAME_BINDINGS (frame));
1221 SCHEME_OBJECT * end = (scan + (GET_EXTENDED_FRAME_LENGTH (frame)));
1222 while (scan < end)
1223 {
1224 if ((PAIR_CAR (*scan)) == symbol)
1225 return (PAIR_CDR_LOC (*scan));
1226 scan += 1;
1227 }
1228 return
1229 (scan_procedure_bindings ((GET_EXTENDED_FRAME_PROCEDURE (frame)),
1230 frame, symbol, find_unbound_p));
1231 }
1232 return
1233 (scan_procedure_bindings ((GET_FRAME_PROCEDURE (frame)),
1234 frame, symbol, find_unbound_p));
1235 }
1236 else if (GLOBAL_FRAME_P (frame))
1237 return (SYMBOL_GLOBAL_VALUE_CELL (symbol));
1238 else
1239 return (0);
1240 }
1241
1242 static SCHEME_OBJECT *
scan_procedure_bindings(SCHEME_OBJECT procedure,SCHEME_OBJECT frame,SCHEME_OBJECT symbol,int find_unbound_p)1243 scan_procedure_bindings (SCHEME_OBJECT procedure, SCHEME_OBJECT frame,
1244 SCHEME_OBJECT symbol, int find_unbound_p)
1245 {
1246 SCHEME_OBJECT lambda = (GET_PROCEDURE_LAMBDA (procedure));
1247 SCHEME_OBJECT * start = (GET_LAMBDA_PARAMETERS (lambda));
1248 SCHEME_OBJECT * scan = start;
1249 SCHEME_OBJECT * end = (scan + (GET_LAMBDA_N_PARAMETERS (lambda)));
1250 while (scan < end)
1251 {
1252 if ((*scan) == symbol)
1253 {
1254 SCHEME_OBJECT * cell = (GET_FRAME_ARG_CELL (frame, (scan - start)));
1255 if (find_unbound_p || ((*cell) != UNBOUND_OBJECT))
1256 return (cell);
1257 }
1258 scan += 1;
1259 }
1260 return (0);
1261 }
1262
1263 trap_kind_t
get_trap_kind(SCHEME_OBJECT object)1264 get_trap_kind (SCHEME_OBJECT object)
1265 {
1266 if (REFERENCE_TRAP_P (object))
1267 {
1268 unsigned long datum = (OBJECT_DATUM (object));
1269 return
1270 ((datum <= TRAP_MAX_IMMEDIATE)
1271 ? datum
1272 : (OBJECT_DATUM (GET_TRAP_TAG (object))));
1273 }
1274 else
1275 return (NON_TRAP_KIND);
1276 }
1277
1278 static unsigned long
count_references(SCHEME_OBJECT * palist)1279 count_references (SCHEME_OBJECT * palist)
1280 {
1281 unsigned long n_references = 0;
1282 WALK_REFERENCES (palist, reference, { n_references += 1; });
1283 return (n_references);
1284 }
1285
1286 #ifdef CC_SUPPORT_P
1287 static SCHEME_OBJECT *
find_references_named(SCHEME_OBJECT * palist,SCHEME_OBJECT symbol)1288 find_references_named (SCHEME_OBJECT * palist, SCHEME_OBJECT symbol)
1289 {
1290 while (PAIR_P (*palist))
1291 {
1292 if ((PAIR_CAR (PAIR_CAR (*palist))) == symbol)
1293 return (PAIR_CDR_LOC (PAIR_CAR (*palist)));
1294 palist = (PAIR_CDR_LOC (*palist));
1295 }
1296 return (0);
1297 }
1298 #endif
1299
1300 static void
update_assignment_references(SCHEME_OBJECT cache)1301 update_assignment_references (SCHEME_OBJECT cache)
1302 {
1303 #ifdef CC_SUPPORT_P
1304 SCHEME_OBJECT reference_cache
1305 = (((GET_CACHE_CLONE (cache)) != SHARP_F)
1306 ? (GET_CACHE_CLONE (cache))
1307 : cache);
1308 WALK_REFERENCES
1309 ((GET_CACHE_ASSIGNMENT_REFERENCES (cache)),
1310 reference,
1311 {
1312 write_variable_cache
1313 (reference_cache,
1314 (GET_CACHE_REFERENCE_BLOCK (reference)),
1315 (GET_CACHE_REFERENCE_OFFSET (reference)));
1316 });
1317 #endif
1318 }
1319
1320 static long
guarantee_cache(SCHEME_OBJECT * cell)1321 guarantee_cache (SCHEME_OBJECT * cell)
1322 {
1323 SCHEME_OBJECT references;
1324 SCHEME_OBJECT cache;
1325
1326 if ((get_trap_kind (*cell)) == TRAP_COMPILER_CACHED)
1327 return (PRIM_DONE);
1328
1329 GC_CHECK (3);
1330 references = (MAKE_POINTER_OBJECT (CACHE_REFERENCES_TYPE, Free));
1331 (*Free++) = EMPTY_LIST;
1332 (*Free++) = EMPTY_LIST;
1333 (*Free++) = EMPTY_LIST;
1334
1335 RETURN_IF_ERROR (make_cache ((*cell), SHARP_F, references, (&cache)));
1336
1337 GC_CHECK (2);
1338 (*Free++) = (LONG_TO_UNSIGNED_FIXNUM (TRAP_COMPILER_CACHED));
1339 (*Free++) = cache;
1340 (*cell) = (MAKE_POINTER_OBJECT (TC_REFERENCE_TRAP, (Free - 2)));
1341 return (PRIM_DONE);
1342 }
1343
1344 static void
update_clone(SCHEME_OBJECT cache)1345 update_clone (SCHEME_OBJECT cache)
1346 {
1347 if ((PAIR_P (* (GET_CACHE_ASSIGNMENT_REFERENCES (cache))))
1348 && (PAIR_P (* (GET_CACHE_OPERATOR_REFERENCES (cache)))))
1349 {
1350 if ((GET_CACHE_CLONE (cache)) == SHARP_F)
1351 {
1352 SCHEME_OBJECT clone;
1353 DIE_IF_ERROR
1354 (make_cache (EXPENSIVE_OBJECT,
1355 cache,
1356 (GET_CACHE_REFERENCES_OBJECT (cache)),
1357 (&clone)));
1358 SET_CACHE_CLONE (cache, clone);
1359 update_assignment_references (cache);
1360 }
1361 }
1362 else
1363 {
1364 if ((GET_CACHE_CLONE (cache)) != SHARP_F)
1365 {
1366 SET_CACHE_CLONE (cache, SHARP_F);
1367 update_assignment_references (cache);
1368 }
1369 }
1370 }
1371
1372 static long
make_cache(SCHEME_OBJECT value,SCHEME_OBJECT clone,SCHEME_OBJECT references,SCHEME_OBJECT * cache_ret)1373 make_cache (SCHEME_OBJECT value, SCHEME_OBJECT clone, SCHEME_OBJECT references,
1374 SCHEME_OBJECT * cache_ret)
1375 {
1376 GC_CHECK (3);
1377 (*Free++) = value;
1378 (*Free++) = clone;
1379 (*Free++) = references;
1380 (*cache_ret) = (MAKE_POINTER_OBJECT (CACHE_TYPE, (Free - 3)));
1381 return (PRIM_DONE);
1382 }
1383
1384 #ifdef CC_SUPPORT_P
1385 static long
make_cache_reference(SCHEME_OBJECT block,unsigned long offset,SCHEME_OBJECT * ref_ret)1386 make_cache_reference (SCHEME_OBJECT block, unsigned long offset,
1387 SCHEME_OBJECT * ref_ret)
1388 {
1389 GC_CHECK (2);
1390 (*Free++) = block;
1391 (*Free++) = (LONG_TO_UNSIGNED_FIXNUM (offset));
1392 (*ref_ret) = (MAKE_POINTER_OBJECT (TC_WEAK_CONS, (Free - 2)));
1393 return (PRIM_DONE);
1394 }
1395 #endif
1396