1 #include "schpriv.h"
2 #include "schrunst.h"
3 #include "schmach.h"
4
5 /* Bytecode validation (now off by default!) is an abstract
6 interpretation on the stack, where the abstract values are "not
7 available", "value", "boxed value", "syntax object", or "global
8 array". */
9
10 /* FIXME: validation doesn't check LAMBDA_SINGLE_RESULT or
11 LAMBDA_PRESERVES_MARKS. (Maybe check them in the JIT pass?) */
12
13 static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
14 char *stack, Validate_TLS tls,
15 int depth, int letlimit, int delta,
16 int num_toplevels, int num_lifts, void *tl_use_map,
17 mzshort *tl_state, mzshort tl_timestamp,
18 Scheme_Object *app_rator, int proc_with_refs_ok,
19 int result_ignored, struct Validate_Clearing *vc,
20 int tailpos, int need_local_type, Scheme_Hash_Tree *procs,
21 int expected_results,
22 Scheme_Hash_Table **_st_ht);
23 static int validate_rator_wants_box(Scheme_Object *app_rator, int pos,
24 int hope,
25 Validate_TLS tls,
26 int num_toplevels, int num_lifts, void *tl_use_map);
27
28 #ifdef MZ_PRECISE_GC
29 static void register_traversers(void);
30 #endif
31
scheme_init_validate()32 void scheme_init_validate()
33 {
34 #ifdef MZ_PRECISE_GC
35 register_traversers();
36 #endif
37 }
38
39 #define VALID_NOT 0
40 #define VALID_UNINIT 1
41 #define VALID_VAL 2
42 #define VALID_BOX 3
43 #define VALID_TOPLEVELS 4
44 #define VALID_VAL_NOCLEAR 5
45 #define VALID_BOX_NOCLEAR 6
46 #define VALID_TYPED 7
47
48 typedef struct Validate_Clearing {
49 MZTAG_IF_REQUIRED
50 int stackpos, stacksize;
51 int *stack;
52 int ncstackpos, ncstacksize;
53 int *ncstack;
54 int self_pos, self_count, self_start;
55 } Validate_Clearing;
56
make_clearing_stack()57 static struct Validate_Clearing *make_clearing_stack()
58 {
59 Validate_Clearing *vc;
60 vc = MALLOC_ONE_RT(Validate_Clearing);
61 SET_REQUIRED_TAG(vc->type = scheme_rt_validate_clearing);
62 vc->self_pos = -1;
63 return vc;
64 }
65
reset_clearing(struct Validate_Clearing * vc)66 static void reset_clearing(struct Validate_Clearing *vc)
67 {
68 vc->stackpos = 0;
69 vc->ncstackpos = 0;
70 }
71
clearing_stack_push(struct Validate_Clearing * vc,int pos,int val)72 static void clearing_stack_push(struct Validate_Clearing *vc, int pos, int val)
73 {
74 if (vc->stackpos + 2 > vc->stacksize) {
75 int *a, sz;
76 sz = (vc->stacksize ? 2 * vc->stacksize : 32);
77 a = (int *)scheme_malloc_atomic(sizeof(int) * sz);
78 if (vc->stacksize)
79 memcpy(a, vc->stack, vc->stacksize * sizeof(int));
80 vc->stacksize = sz;
81 vc->stack = a;
82 }
83 vc->stack[vc->stackpos] = pos;
84 vc->stack[vc->stackpos + 1] = val;
85 vc->stackpos += 2;
86 }
87
noclear_stack_push(struct Validate_Clearing * vc,int pos)88 static void noclear_stack_push(struct Validate_Clearing *vc, int pos)
89 {
90 if (vc->ncstackpos + 1 > vc->ncstacksize) {
91 int *a, sz;
92 sz = (vc->ncstacksize ? 2 * vc->ncstacksize : 32);
93 a = (int *)scheme_malloc_atomic(sizeof(int) * sz);
94 if (vc->ncstacksize)
95 memcpy(a, vc->ncstack, vc->ncstacksize * sizeof(int));
96 vc->ncstacksize = sz;
97 vc->ncstack = a;
98 }
99 vc->ncstack[vc->ncstackpos] = pos;
100 vc->ncstackpos += 1;
101 }
102
103
add_struct_mapping(Scheme_Hash_Table ** _st_ht,int pos,int shape,int for_property)104 static void add_struct_mapping(Scheme_Hash_Table **_st_ht, int pos, int shape, int for_property)
105 {
106 if (!*_st_ht) {
107 Scheme_Hash_Table *ht;
108 ht = scheme_make_hash_table_eqv();
109 *_st_ht = ht;
110 }
111
112 if (for_property) {
113 /* negative value is for a structure type property: */
114 shape = -(shape+1);
115 }
116
117 scheme_hash_set(*_st_ht,
118 scheme_make_integer(pos),
119 scheme_make_integer(shape));
120 }
121
scheme_validate_linklet(Mz_CPort * port,Scheme_Linklet * linklet)122 void scheme_validate_linklet(Mz_CPort *port, Scheme_Linklet *linklet)
123 {
124 char *stack;
125 int depth, delta, num_toplevels, i, j, pos;
126 int cnt, tl_timestamp = 1;
127 struct Validate_Clearing *vc;
128 Validate_TLS tls;
129 mzshort *tl_state;
130 Scheme_Hash_Table **_st_ht = NULL;
131 Scheme_Object *form, *shape;
132
133 depth = linklet->max_let_depth + 1; /* +1 is for prefix */
134
135 stack = scheme_malloc_atomic(depth);
136 memset(stack, VALID_NOT, depth);
137
138 stack[depth - 1] = VALID_TOPLEVELS;
139 delta = depth - 1;
140
141 tls = MALLOC_N(mzshort*, linklet->num_lifts);
142 _st_ht = MALLOC_N(Scheme_Hash_Table*, 1);
143
144 num_toplevels = SCHEME_LINKLET_PREFIX_PREFIX + linklet->num_total_imports + SCHEME_VEC_SIZE(linklet->defns);
145
146 tl_state = MALLOC_N_ATOMIC(mzshort, num_toplevels);
147 memset(tl_state, 0, sizeof(mzshort) * num_toplevels);
148
149 if (linklet->need_instance_access)
150 tl_state[0] = 1;
151
152 pos = SCHEME_LINKLET_PREFIX_PREFIX;
153 for (i = 0; i < SCHEME_VEC_SIZE(linklet->importss); i++) {
154 for (j = 0; j < SCHEME_VEC_SIZE(SCHEME_VEC_ELS(linklet->importss)[i]); j++, pos++) {
155 shape = (linklet->import_shapes ? SCHEME_VEC_ELS(linklet->import_shapes)[pos-SCHEME_LINKLET_PREFIX_PREFIX] : scheme_false);
156 if (SCHEME_TRUEP(shape)) {
157 if (SAME_OBJ(shape, scheme_void))
158 tl_state[pos] = SCHEME_TOPLEVEL_FIXED;
159 else {
160 intptr_t k;
161 tl_state[pos] = SCHEME_TOPLEVEL_CONST;
162 if (scheme_decode_struct_shape(shape, &k))
163 add_struct_mapping(_st_ht, pos, k, 0);
164 else if (scheme_decode_struct_prop_shape(shape, &k))
165 add_struct_mapping(_st_ht, pos, k, 1);
166 }
167 } else
168 tl_state[pos] = SCHEME_TOPLEVEL_READY;
169 }
170 }
171
172 vc = make_clearing_stack();
173
174 cnt = SCHEME_VEC_SIZE(linklet->bodies);
175 for (i = 0; i < cnt; i++) {
176 form = SCHEME_VEC_ELS(linklet->bodies)[i];
177 reset_clearing(vc);
178 if (!validate_expr(port, form,
179 stack, tls,
180 depth, delta, delta,
181 num_toplevels, linklet->num_lifts, NULL,
182 tl_state, tl_timestamp,
183 NULL, 0, 0,
184 vc, 1, 0, NULL, -1, _st_ht)) {
185 tl_timestamp++;
186 if (0) {
187 printf("increment to %d for %d %p\n", tl_timestamp,
188 SCHEME_TYPE(SCHEME_VEC_ELS(linklet->bodies)[i]),
189 SCHEME_VEC_ELS(linklet->bodies)[i]);
190 }
191 }
192 }
193 }
194
validate_join(int r1,int r2)195 static int validate_join(int r1, int r2)
196 /* both r1 and r2 is result */
197 {
198 if (!r1 || !r2) return 0;
199 if ((r1 == 2) && (r2 == 2)) return 2;
200 return 1;
201 }
202
validate_join_seq(int r1,int r2)203 static int validate_join_seq(int r1, int r2)
204 /* only r2 is result */
205 {
206 if (!r1 || !r2) return 0;
207 return r2;
208 }
209
210 /*========================================================================*/
211 /* other syntax */
212 /*========================================================================*/
213
validate_toplevel(Scheme_Object * expr,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int skip_refs_check)214 static int validate_toplevel(Scheme_Object *expr, Mz_CPort *port,
215 char *stack, Validate_TLS tls,
216 int depth, int delta,
217 int num_toplevels, int num_lifts, void *tl_use_map,
218 mzshort *tl_state, mzshort tl_timestamp,
219 int skip_refs_check)
220 {
221 if (!SAME_TYPE(scheme_toplevel_type, SCHEME_TYPE(expr)))
222 scheme_ill_formed_code(port);
223
224 return validate_expr(port, expr, stack, tls,
225 depth, delta, delta,
226 num_toplevels, num_lifts, tl_use_map,
227 tl_state, tl_timestamp,
228 NULL, skip_refs_check ? 1 : 0, 0,
229 make_clearing_stack(), 0, 0, NULL, 1, NULL);
230 }
231
define_values_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)232 static int define_values_validate(Scheme_Object *data, Mz_CPort *port,
233 char *stack, Validate_TLS tls,
234 int depth, int letlimit, int delta,
235 int num_toplevels, int num_lifts,
236 void *tl_use_map,
237 mzshort *tl_state, mzshort tl_timestamp,
238 int result_ignored,
239 struct Validate_Clearing *vc, int tailpos,
240 Scheme_Hash_Tree *procs,
241 Scheme_Hash_Table **_st_ht)
242 {
243 int i, size, flags, result, is_struct, is_struct_prop, has_guard;
244 Simple_Struct_Type_Info stinfo;
245 Scheme_Object *val, *only_var;
246
247 val = SCHEME_VEC_ELS(data)[0];
248 size = SCHEME_VEC_SIZE(data);
249
250 if (size == 2)
251 only_var = SCHEME_VEC_ELS(data)[1];
252 else
253 only_var = NULL;
254
255 for (i = 1; i < size; i++) {
256 validate_toplevel(SCHEME_VEC_ELS(data)[i], port, stack, tls, depth, delta,
257 num_toplevels, num_lifts, tl_use_map,
258 NULL, tl_timestamp,
259 1);
260 }
261
262 if (only_var) {
263 int pos;
264 pos = SCHEME_TOPLEVEL_POS(only_var);
265 if (pos >= (num_toplevels - num_lifts)) {
266 /* It's a lift. Check whether it needs to take reference arguments
267 and/or install reference info. */
268 Scheme_Object *app_rator;
269 Scheme_Lambda *data = NULL;
270 int tp = pos - (num_toplevels - num_lifts);
271 mzshort *a, *new_a = NULL;
272
273 /* Make sure that no one has tried to register information. */
274 a = tls[tp];
275 if (a && (a != (mzshort *)0x1) && (a[0] < 1))
276 scheme_ill_formed_code(port);
277
278 /* Convert rator to ref-arg info: */
279 app_rator = val;
280 while (1) {
281 if (SAME_TYPE(SCHEME_TYPE(app_rator), scheme_closure_type)) {
282 data = SCHEME_CLOSURE_CODE(app_rator);
283 break;
284 } else if (SAME_TYPE(SCHEME_TYPE(app_rator), scheme_lambda_type)) {
285 data = (Scheme_Lambda *)app_rator;
286 break;
287 } else if (SAME_TYPE(SCHEME_TYPE(app_rator), scheme_toplevel_type)) {
288 /* Record an indirection */
289 data = NULL;
290 new_a = MALLOC_N_ATOMIC(mzshort, 2);
291 new_a[0] = 0;
292 new_a[1] = SCHEME_TOPLEVEL_POS(app_rator);
293 break;
294 } else {
295 /* Not a procedure */
296 data = NULL;
297 new_a = (mzshort *)0x1;
298 break;
299 }
300 }
301 if (data) {
302 if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
303 int sz;
304 sz = data->num_params;
305 new_a = MALLOC_N_ATOMIC(mzshort, (sz + 2));
306 new_a[0] = -sz;
307 new_a[sz+1] = !!(SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_REST);
308 for (i = 0; i < sz; i++) {
309 int ct;
310 ct = scheme_boxmap_get(data->closure_map, i, data->closure_size);
311 if (ct == LAMBDA_TYPE_BOXED)
312 new_a[i + 1] = 1;
313 else
314 new_a[i + 1] = 0;
315 }
316 } else {
317 new_a = (mzshort *)0x1;
318 }
319 }
320
321 /* Install info: */
322 tls[tp] = new_a;
323
324 /* Check old hopes against actual */
325 if (a == (mzshort *)0x1) {
326 if (new_a != (mzshort *)0x1)
327 scheme_ill_formed_code(port);
328 } else if (a) {
329 int cnt = a[0], i;
330
331 for (i = 0; i < cnt; i++) {
332 if (a[i + 1]) {
333 int is;
334 is = validate_rator_wants_box(val, i,
335 a[i + 1] == 2,
336 tls, num_toplevels, num_lifts, tl_use_map);
337 if ((is && (a[i + 1] == 1))
338 || (!is && (a[i + 1] == 2)))
339 scheme_ill_formed_code(port);
340 }
341 }
342 }
343 } else
344 only_var = NULL;
345 }
346
347 if (scheme_is_simple_make_struct_type(val, size-1, CHECK_STRUCT_TYPE_RESOLVED,
348 NULL,
349 &stinfo, NULL,
350 NULL, (_st_ht ? *_st_ht : NULL),
351 NULL, 0, NULL, NULL, 5)) {
352 /* This set of bindings is constant across invocations, but
353 if `uses_super', we need to increment tl_timestamp for
354 subtype-defining `struct' sequences. */
355 is_struct = 1;
356 } else {
357 is_struct = 0;
358 }
359
360 has_guard = 0;
361 if (scheme_is_simple_make_struct_type_property(val, size-1, CHECK_STRUCT_TYPE_RESOLVED,
362 &has_guard,
363 NULL, (_st_ht ? *_st_ht : NULL),
364 NULL, 0, NULL, 5)) {
365 is_struct_prop = 1;
366 } else {
367 is_struct_prop = 0;
368 }
369
370 result = validate_expr(port, val, stack, tls,
371 depth, letlimit, delta,
372 num_toplevels, num_lifts, tl_use_map,
373 tl_state, tl_timestamp + ((is_struct && stinfo.uses_super) ? 1 : 0),
374 NULL, !!only_var, 0, vc, 0, 0, NULL,
375 size-1, _st_ht);
376
377 if (is_struct) {
378 if (_st_ht) {
379 /* Record `struct:' binding as constant across invocations,
380 so that it can be recognized for sub-struct declarations,
381 and so on: */
382 for (i = 1; i < size; i++) {
383 /* For the struct:, we need the init and field counts to be the
384 same, otherwise anything is fine: */
385 if ((i > 1)
386 || (stinfo.field_count == stinfo.init_field_count))
387 add_struct_mapping(_st_ht,
388 SCHEME_TOPLEVEL_POS(SCHEME_VEC_ELS(data)[i]),
389 scheme_get_struct_proc_shape(i-1, &stinfo),
390 0);
391 }
392 }
393 /* In any case, treat the bindings as constant */
394 result = 2;
395 } else if (is_struct_prop) {
396 if (_st_ht) {
397 /* Record `prop:' binding as constant across invocations,
398 so that it can be recognized for struct declarations,
399 and so on: */
400 for (i = 1; i < size; i++) {
401 add_struct_mapping(_st_ht,
402 SCHEME_TOPLEVEL_POS(SCHEME_VEC_ELS(data)[i]),
403 scheme_get_struct_property_proc_shape(i-1, has_guard),
404 1);
405 }
406 }
407 /* In any case, treat the bindings as constant */
408 result = 2;
409 }
410
411 flags = SCHEME_TOPLEVEL_READY;
412 if (result == 2) {
413 /* We may treat more things as constant (more than fixed)
414 than the compiler would in terms of copyable literals, but
415 that's good enough for ensuring safety. */
416 flags = SCHEME_TOPLEVEL_CONST;
417 }
418
419 for (i = 1; i < size; i++) {
420 int ts = (tl_timestamp + (result ? 0 : 1));
421 if (tl_state) {
422 int p = SCHEME_TOPLEVEL_POS(SCHEME_VEC_ELS(data)[i]);
423 if (p < (num_toplevels - num_lifts)) {
424 int s = -tl_state[p];
425 int expected_flags = s & SCHEME_TOPLEVEL_FLAGS_MASK;
426 int this_flags = flags;
427 if ((this_flags == SCHEME_TOPLEVEL_READY)
428 && (SCHEME_TOPLEVEL_FLAGS(SCHEME_VEC_ELS(data)[i]) & SCHEME_TOPLEVEL_SEAL))
429 this_flags = SCHEME_TOPLEVEL_FIXED;
430 if (0) {
431 printf("%d is %d for %d %p; at %d\n", p, this_flags, SCHEME_TYPE(val), val, ts);
432 }
433 if (tl_state[p] > 0)
434 scheme_ill_formed_code(port);
435 if ((expected_flags > this_flags)
436 || (expected_flags
437 /* Use "<=" instead of "<" to prevent things like
438 `(define x x)' with `x' claimed as constant. The
439 `tl_timestamp++' before checking a closure body
440 allows things like `(define x (lambda () x))'. */
441 && ((s >> 2) <= ts))) {
442 scheme_ill_formed_code(port);
443 }
444 tl_state[p] = (ts << 2) | this_flags;
445 }
446 }
447 }
448
449 return result;
450 }
451
set_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)452 static int set_validate(Scheme_Object *data, Mz_CPort *port,
453 char *stack, Validate_TLS tls,
454 int depth, int letlimit, int delta,
455 int num_toplevels, int num_lifts,
456 void *tl_use_map,
457 mzshort *tl_state, mzshort tl_timestamp,
458 int result_ignored,
459 struct Validate_Clearing *vc, int tailpos,
460 Scheme_Hash_Tree *procs,
461 Scheme_Hash_Table **_st_ht)
462 {
463 Scheme_Set_Bang *sb = (Scheme_Set_Bang *)data;
464 int r1, r2;
465
466 r1 = validate_expr(port, sb->val, stack, tls, depth, letlimit, delta,
467 num_toplevels, num_lifts, tl_use_map,
468 tl_state, tl_timestamp,
469 NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
470 r2 = validate_toplevel(sb->var, port, stack, tls, depth, delta,
471 num_toplevels, num_lifts, tl_use_map,
472 tl_state, tl_timestamp,
473 0);
474
475 return validate_join(validate_join_seq(r1, r2), 2);
476 }
477
ref_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs)478 static void ref_validate(Scheme_Object *data, Mz_CPort *port,
479 char *stack, Validate_TLS tls,
480 int depth, int letlimit, int delta,
481 int num_toplevels, int num_lifts,
482 void *tl_use_map,
483 mzshort *tl_state, mzshort tl_timestamp,
484 int result_ignored,
485 struct Validate_Clearing *vc, int tailpos,
486 Scheme_Hash_Tree *procs)
487 {
488 tl_timestamp = tl_timestamp + 1; /* allows (define x (#%variable-reference x)) */
489
490 if (!SCHEME_FALSEP(SCHEME_PTR1_VAL(data)))
491 validate_toplevel(SCHEME_PTR1_VAL(data), port, stack, tls, depth, delta,
492 num_toplevels, num_lifts, tl_use_map,
493 tl_state, tl_timestamp,
494 0);
495
496 if (!SCHEME_FALSEP(SCHEME_PTR2_VAL(data))) {
497 /* must reference */
498 int p;
499 data = SCHEME_PTR2_VAL(data);
500 if (!SAME_TYPE(scheme_toplevel_type, SCHEME_TYPE(data)))
501 scheme_ill_formed_code(port);
502 p = SCHEME_TOPLEVEL_POS(data);
503 if (p != 0)
504 scheme_ill_formed_code(port);
505
506 validate_toplevel(data, port, stack, tls, depth, delta,
507 num_toplevels, num_lifts, tl_use_map,
508 tl_state, tl_timestamp,
509 0);
510 }
511 }
512
apply_values_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)513 static int apply_values_validate(Scheme_Object *data, Mz_CPort *port,
514 char *stack, Validate_TLS tls,
515 int depth, int letlimit, int delta,
516 int num_toplevels, int num_lifts,
517 void *tl_use_map,
518 mzshort *tl_state, mzshort tl_timestamp,
519 int result_ignored,
520 struct Validate_Clearing *vc, int tailpos,
521 Scheme_Hash_Tree *procs,
522 Scheme_Hash_Table **_st_ht)
523 {
524 Scheme_Object *f, *e;
525 int r1, r2;
526
527 f = SCHEME_PTR1_VAL(data);
528 e = SCHEME_PTR2_VAL(data);
529
530 r1 = validate_expr(port, f, stack, tls,
531 depth, letlimit, delta,
532 num_toplevels, num_lifts, tl_use_map,
533 tl_state, tl_timestamp,
534 NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
535 r2 = validate_expr(port, e, stack, tls,
536 depth, letlimit, delta,
537 num_toplevels, num_lifts, tl_use_map,
538 tl_state, tl_timestamp,
539 NULL, 0, 0, vc, 0, 0, procs, -1, _st_ht);
540
541 return validate_join(r1, r2);
542 }
543
inline_variant_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)544 static void inline_variant_validate(Scheme_Object *data, Mz_CPort *port,
545 char *stack, Validate_TLS tls,
546 int depth, int letlimit, int delta,
547 int num_toplevels, int num_lifts,
548 void *tl_use_map,
549 mzshort *tl_state, mzshort tl_timestamp,
550 int result_ignored,
551 struct Validate_Clearing *vc, int tailpos,
552 Scheme_Hash_Tree *procs,
553 Scheme_Hash_Table **_st_ht)
554 {
555 Scheme_Object *f1, *f2;
556
557 f1 = SCHEME_VEC_ELS(data)[0];
558 f2 = SCHEME_VEC_ELS(data)[1];
559
560 validate_expr(port, f1, stack, tls,
561 depth, letlimit, delta,
562 num_toplevels, num_lifts, tl_use_map,
563 tl_state, tl_timestamp,
564 NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
565 validate_expr(port, f2, stack, tls,
566 depth, letlimit, delta,
567 num_toplevels, num_lifts, tl_use_map,
568 tl_state, tl_timestamp,
569 NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
570 }
571
case_lambda_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)572 static void case_lambda_validate(Scheme_Object *data, Mz_CPort *port, char *stack, Validate_TLS tls,
573 int depth, int letlimit, int delta,
574 int num_toplevels, int num_lifts,
575 void *tl_use_map,
576 mzshort *tl_state, mzshort tl_timestamp,
577 int result_ignored,
578 struct Validate_Clearing *vc, int tailpos,
579 Scheme_Hash_Tree *procs,
580 Scheme_Hash_Table **_st_ht)
581 {
582 Scheme_Case_Lambda *seq = (Scheme_Case_Lambda *)data;
583 Scheme_Object *e;
584 int i;
585
586 if (!SAME_TYPE(SCHEME_TYPE(data), scheme_case_lambda_sequence_type))
587 scheme_ill_formed_code(port);
588
589 for (i = 0; i < seq->count; i++) {
590 e = seq->array[i];
591 if (!SAME_TYPE(SCHEME_TYPE(e), scheme_lambda_type)
592 && !SAME_TYPE(SCHEME_TYPE(e), scheme_closure_type))
593 scheme_ill_formed_code(port);
594 validate_expr(port, e, stack, tls, depth, letlimit, delta,
595 num_toplevels, num_lifts, tl_use_map,
596 tl_state, tl_timestamp,
597 NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
598 }
599 }
600
validate_boxenv(int p,Mz_CPort * port,char * stack,int depth,int delta,int letlimit)601 static void validate_boxenv(int p, Mz_CPort *port, char *stack, int depth, int delta, int letlimit)
602 {
603 if (p >= 0)
604 p += delta;
605
606 if ((p < 0) || (p >= letlimit) || (stack[p] != VALID_VAL))
607 scheme_ill_formed_code(port);
608
609 stack[p] = VALID_BOX;
610 }
611
bangboxenv_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht,int expected_results)612 static int bangboxenv_validate(Scheme_Object *data, Mz_CPort *port,
613 char *stack, Validate_TLS tls,
614 int depth, int letlimit, int delta,
615 int num_toplevels, int num_lifts,
616 void *tl_use_map,
617 mzshort *tl_state, mzshort tl_timestamp,
618 int result_ignored,
619 struct Validate_Clearing *vc, int tailpos,
620 Scheme_Hash_Tree *procs,
621 Scheme_Hash_Table **_st_ht,
622 int expected_results)
623 {
624 validate_boxenv(SCHEME_INT_VAL(SCHEME_PTR1_VAL(data)), port, stack, depth, delta, letlimit);
625
626 return validate_expr(port, SCHEME_PTR2_VAL(data), stack, tls, depth, letlimit, delta,
627 num_toplevels, num_lifts, tl_use_map,
628 tl_state, tl_timestamp,
629 NULL, 0, result_ignored, vc, tailpos, 0, procs, expected_results, _st_ht);
630 }
631
begin0_validate(Scheme_Object * data,Mz_CPort * port,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int result_ignored,struct Validate_Clearing * vc,int tailpos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht,int expected_results)632 static int begin0_validate(Scheme_Object *data, Mz_CPort *port,
633 char *stack, Validate_TLS tls,
634 int depth, int letlimit, int delta,
635 int num_toplevels, int num_lifts,
636 void *tl_use_map,
637 mzshort *tl_state, mzshort tl_timestamp,
638 int result_ignored,
639 struct Validate_Clearing *vc, int tailpos,
640 Scheme_Hash_Tree *procs,
641 Scheme_Hash_Table **_st_ht,
642 int expected_results)
643 {
644 Scheme_Sequence *seq = (Scheme_Sequence *)data;
645 int i, r, result = 2;
646
647 if (!SAME_TYPE(SCHEME_TYPE(seq), scheme_begin0_sequence_type)
648 && !SAME_TYPE(SCHEME_TYPE(seq), scheme_sequence_type))
649 scheme_ill_formed_code(port);
650
651 for (i = 0; i < seq->count; i++) {
652 r = validate_expr(port, seq->array[i], stack, tls,
653 depth, letlimit, delta,
654 num_toplevels, num_lifts, tl_use_map,
655 tl_state, tl_timestamp,
656 NULL, 0, i > 0, vc, 0, 0, procs,
657 (i > 0) ? -1 : expected_results, _st_ht);
658 result = validate_join_seq(r, result);
659 }
660
661 return result;
662 }
663
664 /*========================================================================*/
665 /* expressions */
666 /*========================================================================*/
667
validate_k(void)668 static Scheme_Object *validate_k(void)
669 {
670 Scheme_Thread *p = scheme_current_thread;
671 Mz_CPort *port = (Mz_CPort *)p->ku.k.p1;
672 Scheme_Object *expr = (Scheme_Object *)p->ku.k.p2;
673 char *stack = (char *)p->ku.k.p3;
674 int *args = (int *)(((void **)p->ku.k.p5)[0]);
675 Scheme_Object *app_rator = (Scheme_Object *)(((void **)p->ku.k.p5)[1]);
676 Validate_TLS tls = (Validate_TLS)(((void **)p->ku.k.p5)[2]);
677 Scheme_Hash_Tree *procs = (Scheme_Hash_Tree *)(((void **)p->ku.k.p5)[3]);
678 struct Validate_Clearing *vc = (struct Validate_Clearing *)p->ku.k.p4;
679 void *tl_use_map = (((void **)p->ku.k.p5)[4]);
680 mzshort *tl_state = (((void **)p->ku.k.p5)[5]);
681 Scheme_Hash_Table **_st_ht = (((void **)p->ku.k.p5)[6]);
682 int r;
683
684 p->ku.k.p1 = NULL;
685 p->ku.k.p2 = NULL;
686 p->ku.k.p3 = NULL;
687 p->ku.k.p4 = NULL;
688 p->ku.k.p5 = NULL;
689
690 r = validate_expr(port, expr, stack, tls,
691 args[0], args[1], args[2],
692 args[3], args[5], tl_use_map,
693 tl_state, args[10],
694 app_rator, args[6], args[7], vc, args[8],
695 args[9], procs, args[11],
696 _st_ht);
697
698 return scheme_make_integer(r);
699 }
700
701 /* FIXME: need to validate that a flonum is provided when a
702 procedure expects a flonum */
703
validate_rator_wants_box(Scheme_Object * app_rator,int pos,int hope,Validate_TLS tls,int num_toplevels,int num_lifts,void * tl_use_map)704 int validate_rator_wants_box(Scheme_Object *app_rator, int pos,
705 int hope,
706 Validate_TLS tls,
707 int num_toplevels, int num_lifts, void *tl_use_map)
708 {
709 Scheme_Lambda *data = NULL;
710 Scheme_Type ty;
711
712 while (1) {
713 ty = SCHEME_TYPE(app_rator);
714 if (SAME_TYPE(ty, scheme_closure_type)) {
715 data = SCHEME_CLOSURE_CODE(app_rator);
716 break;
717 } else if (SAME_TYPE(ty, scheme_lambda_type)) {
718 data = (Scheme_Lambda *)app_rator;
719 break;
720 } else if (SAME_TYPE(ty, scheme_toplevel_type)) {
721 int p;
722 p = SCHEME_TOPLEVEL_POS(app_rator);
723 while (1) {
724 if (p >= (num_toplevels - num_lifts)) {
725 /* It's a lift. Check that the lift is defined, and that it
726 doesn't want reference arguments. */
727 mzshort *a; /* 0x1 => no ref args,
728 ptr with pos length => expected (0 => don't care, 1 => want not, 2 => want is),
729 ptr with neg length => actual
730 ptr with 0 => another top-level */
731 int tp;
732
733 tp = (p - (num_toplevels - num_lifts));
734 if (tp >= num_lifts)
735 return 0;
736
737 a = tls[tp];
738 if (a == (mzshort *)0x1) {
739 return 0;
740 } else if (!a || (a[0] > 0)) {
741 /* The lift isn't ready.
742 Record what we expect to find when it is ready. */
743 if (!a || (a[0] < (pos + 1))) {
744 mzshort *naya;
745 int sz;
746 if (a)
747 sz = a[0];
748 else
749 sz = 3;
750 sz *= 2;
751 if (sz <= pos)
752 sz = pos + 1;
753 naya = scheme_malloc_atomic((sz + 1) * sizeof(mzshort));
754 memset(naya, 0, (sz + 1) * sizeof(mzshort));
755 if (a)
756 memcpy(naya, a, (a[0] + 1) * sizeof(mzshort));
757 naya[0] = sz;
758 a = naya;
759 tls[tp] = a;
760 }
761
762 if (!a[pos + 1]) {
763 a[pos + 1] = hope ? 2 : 1;
764 return hope;
765 } else if (a[pos + 1] == 2)
766 return 1;
767 else
768 return 0;
769 } else if (!a[0]) {
770 /* try again */
771 p = a[1];
772 } else {
773 if (pos >= -a[0]) {
774 /* last slot indicates whether rest args are allowed */
775 return (a[-a[0]+1] ? hope : !hope);
776 } else
777 return a[pos + 1];
778 }
779 } else
780 return 0;
781 }
782 } else
783 return 0;
784 }
785
786 if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
787 if (pos < data->num_params) {
788 int ct;
789 ct = scheme_boxmap_get(data->closure_map, pos, data->closure_size);
790 if (ct == LAMBDA_TYPE_BOXED)
791 return 1;
792 }
793 }
794
795 return 0;
796 }
797
argument_to_arity_error(Scheme_Object * app_rator,int proc_with_refs_ok)798 static int argument_to_arity_error(Scheme_Object *app_rator, int proc_with_refs_ok)
799 {
800 /* Since `raise-arity-error' doesn't actually apply its argument,
801 it's ok to pass any procedure. In particular, the compiler generates
802 calls to converted procedures. */
803 return ((proc_with_refs_ok == 2)
804 && SAME_OBJ(app_rator, scheme_raise_arity_error_proc));
805 }
806
scheme_validate_closure(Mz_CPort * port,Scheme_Object * expr,char * closure_stack,Validate_TLS tls,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,int self_pos_in_closure,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)807 void scheme_validate_closure(Mz_CPort *port, Scheme_Object *expr,
808 char *closure_stack, Validate_TLS tls,
809 int num_toplevels, int num_lifts, void *tl_use_map,
810 mzshort *tl_state, mzshort tl_timestamp,
811 int self_pos_in_closure, Scheme_Hash_Tree *procs,
812 Scheme_Hash_Table **_st_ht)
813 {
814 Scheme_Lambda *data = (Scheme_Lambda *)expr;
815 int i, sz, cnt, base, base2;
816 char *new_stack;
817 struct Validate_Clearing *vc;
818
819 if (data->max_let_depth < (data->num_params + data->closure_size))
820 scheme_ill_formed_code(port);
821
822 sz = data->max_let_depth;
823 new_stack = scheme_malloc_atomic(sz);
824 memset(new_stack, VALID_NOT, sz - data->num_params - data->closure_size);
825
826 cnt = data->num_params;
827 base = sz - cnt;
828
829 if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
830 base2 = data->closure_size;
831 for (i = 0; i < cnt; i++) {
832 new_stack[base + i] = closure_stack[base2 + i];
833 }
834 } else {
835 for (i = 0; i < cnt; i++) {
836 new_stack[i + base] = VALID_VAL;
837 }
838 }
839
840 cnt = data->closure_size;
841 base = base - cnt;
842 for (i = 0; i < cnt; i++) {
843 new_stack[i + base] = closure_stack[i];
844 }
845
846 vc = make_clearing_stack();
847 if (self_pos_in_closure >= 0) {
848 vc->self_pos = base + self_pos_in_closure;
849 vc->self_count = data->closure_size;
850 vc->self_start = base;
851 }
852
853 if (data->tl_map) {
854 if (tl_use_map) {
855 /* check that data->tl_use_map => tl_use_map */
856 int *a, a_buf[2], len;
857
858 if ((uintptr_t)tl_use_map & 0x1) {
859 len = 1;
860 a_buf[1] = (((uintptr_t)data->tl_map) >> 1) & 0x7FFFFFFF;
861 a = a_buf;
862 } else {
863 len = ((int *)tl_use_map)[0];
864 a = (int *)tl_use_map;
865 }
866
867 if (tl_use_map) {
868 if ((uintptr_t)data->tl_map & 0x1) {
869 int map = (((uintptr_t)data->tl_map) >> 1) & 0x7FFFFFFF;
870 if ((len < 1) || ((a[1] & map) != map))
871 scheme_ill_formed_code(port);
872 } else {
873 int *b = ((int *)data->tl_map);
874 for (i = b[0]; i--; ) {
875 if ((len <= i) || ((a[i+1] & b[i+1]) != b[i+1]))
876 scheme_ill_formed_code(port);
877 }
878 }
879 }
880 }
881 tl_use_map = data->tl_map;
882 }
883
884 validate_expr(port, data->body, new_stack, tls, sz, sz, base,
885 num_toplevels, num_lifts, tl_use_map,
886 tl_state, tl_timestamp,
887 NULL, 0, 0, vc, 1, 0, procs, -1, _st_ht);
888 }
889
as_nonempty_procs(Scheme_Hash_Tree * procs)890 static Scheme_Hash_Tree *as_nonempty_procs(Scheme_Hash_Tree *procs)
891 {
892 if (!procs)
893 procs = scheme_make_hash_tree(SCHEME_hashtr_eq);
894 return procs;
895 }
896
validate_lambda(Mz_CPort * port,Scheme_Object * expr,char * stack,Validate_TLS tls,int depth,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,Scheme_Object * app_rator,int proc_with_refs_ok,int self_pos,Scheme_Hash_Tree * procs,Scheme_Hash_Table ** _st_ht)897 static void validate_lambda(Mz_CPort *port, Scheme_Object *expr,
898 char *stack, Validate_TLS tls,
899 int depth, int delta,
900 int num_toplevels, int num_lifts, void *tl_use_map,
901 mzshort *tl_state, mzshort tl_timestamp,
902 Scheme_Object *app_rator, int proc_with_refs_ok,
903 int self_pos, Scheme_Hash_Tree *procs,
904 Scheme_Hash_Table **_st_ht)
905 {
906 Scheme_Lambda *data = (Scheme_Lambda *)expr;
907 int i, cnt, q, p, sz, base, stack_delta, vld, self_pos_in_closure = -1, typed_arg = 0;
908 mzshort *map;
909 char *closure_stack;
910 Scheme_Object *proc;
911 Scheme_Hash_Tree *new_procs = NULL;
912
913 if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
914 sz = data->closure_size + data->num_params;
915 } else {
916 sz = data->closure_size;
917 }
918 map = data->closure_map;
919
920 if (sz)
921 closure_stack = scheme_malloc_atomic(sz);
922 else
923 closure_stack = NULL;
924
925 if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
926 cnt = data->num_params;
927 base = sz - cnt;
928 for (i = 0; i < cnt; i++) {
929 int ct;
930 ct = scheme_boxmap_get(map, i, data->closure_size);
931 if (ct == LAMBDA_TYPE_BOXED) {
932 vld = VALID_BOX;
933 typed_arg = 1;
934 } else if (ct) {
935 if ((ct - LAMBDA_TYPE_TYPE_OFFSET) > SCHEME_MAX_LOCAL_TYPE)
936 scheme_ill_formed_code(port);
937 vld = (VALID_TYPED + (ct - LAMBDA_TYPE_TYPE_OFFSET));
938 typed_arg = 1;
939 } else
940 vld = VALID_VAL;
941 closure_stack[i + base] = vld;
942 }
943 } else {
944 base = sz;
945 }
946
947 cnt = data->closure_size;
948 base = base - cnt;
949 stack_delta = data->max_let_depth - sz;
950
951 for (i = 0; i < cnt; i++) {
952 q = map[i];
953 if (q == self_pos)
954 self_pos_in_closure = i;
955 p = q + delta;
956 if ((q < 0) || (p < 0) || (p >= depth) || (stack[p] <= VALID_UNINIT))
957 scheme_ill_formed_code(port);
958 vld = stack[p];
959 if (vld == VALID_VAL_NOCLEAR)
960 vld = VALID_VAL;
961 else if (vld == VALID_BOX_NOCLEAR)
962 vld = VALID_BOX;
963
964 if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
965 int pos = data->num_params + i;
966 int ct;
967 ct = scheme_boxmap_get(map, pos, data->closure_size);
968 if (ct == LAMBDA_TYPE_BOXED)
969 scheme_ill_formed_code(port);
970 if (ct > LAMBDA_TYPE_TYPE_OFFSET) {
971 if (vld != (VALID_TYPED + (ct - LAMBDA_TYPE_TYPE_OFFSET)))
972 vld = VALID_NOT;
973 } else if (vld > VALID_TYPED)
974 vld = VALID_NOT;
975 } else if (vld > VALID_TYPED)
976 vld = VALID_NOT;
977
978 closure_stack[i + base] = vld;
979
980 if (procs) {
981 proc = scheme_hash_tree_get(procs, scheme_make_integer(p));
982 if (proc)
983 new_procs = scheme_hash_tree_set(as_nonempty_procs(new_procs),
984 scheme_make_integer(i + base + stack_delta),
985 proc);
986 }
987 }
988
989 if (typed_arg) {
990 if ((proc_with_refs_ok != 1)
991 && !argument_to_arity_error(app_rator, proc_with_refs_ok))
992 scheme_ill_formed_code(port);
993 }
994
995 tl_timestamp++; /* closure delays use; needed for self-use <= check */
996
997 if (SCHEME_RPAIRP(data->body)) {
998 /* Delay validation */
999 Scheme_Object *vec;
1000 vec = scheme_make_vector(12, NULL);
1001 SCHEME_VEC_ELS(vec)[0] = SCHEME_CAR(data->body);
1002 SCHEME_VEC_ELS(vec)[1] = (Scheme_Object *)closure_stack;
1003 SCHEME_VEC_ELS(vec)[2] = (Scheme_Object *)tls;
1004 SCHEME_VEC_ELS(vec)[3] = scheme_make_integer(num_toplevels);
1005 SCHEME_VEC_ELS(vec)[4] = scheme_make_integer(0); /* not used anymore */
1006 SCHEME_VEC_ELS(vec)[5] = scheme_make_integer(num_lifts);
1007 SCHEME_VEC_ELS(vec)[6] = scheme_make_integer(self_pos_in_closure);
1008 SCHEME_VEC_ELS(vec)[7] = new_procs ? (Scheme_Object *)new_procs : scheme_false;
1009 SCHEME_VEC_ELS(vec)[8] = tl_use_map ? tl_use_map : scheme_false;
1010 SCHEME_VEC_ELS(vec)[9] = tl_state ? (Scheme_Object *)tl_state : scheme_false;
1011 SCHEME_VEC_ELS(vec)[10] = scheme_make_integer(tl_timestamp);
1012 SCHEME_VEC_ELS(vec)[11] = (Scheme_Object *)_st_ht;
1013 SCHEME_CAR(data->body) = vec;
1014 } else
1015 scheme_validate_closure(port, expr, closure_stack, tls,
1016 num_toplevels, num_lifts, tl_use_map,
1017 tl_state, tl_timestamp,
1018 self_pos_in_closure, new_procs, _st_ht);
1019 }
1020
check_self_call_valid(Scheme_Object * rator,Mz_CPort * port,struct Validate_Clearing * vc,int delta,char * stack)1021 static void check_self_call_valid(Scheme_Object *rator, Mz_CPort *port, struct Validate_Clearing *vc,
1022 int delta, char *stack)
1023 {
1024 if ((vc->self_pos >= 0)
1025 && SAME_TYPE(SCHEME_TYPE(rator), scheme_local_type)
1026 && !SCHEME_GET_LOCAL_FLAGS(rator)
1027 && ((SCHEME_LOCAL_POS(rator) + delta) == vc->self_pos)) {
1028 /* For a self call, the JIT needs the closure data to be intact. */
1029 int i, pos;
1030 for (i = vc->self_count; i--; ) {
1031 pos = i + vc->self_start;
1032 if (stack[pos] <= VALID_UNINIT)
1033 scheme_ill_formed_code(port);
1034 }
1035 }
1036 }
1037
no_typed(int need_local_type,Mz_CPort * port)1038 static void no_typed(int need_local_type, Mz_CPort *port)
1039 {
1040 if (need_local_type) scheme_ill_formed_code(port);
1041 }
1042
check_typed(Scheme_Object * expr,int need_local_type,Mz_CPort * port)1043 static void check_typed(Scheme_Object *expr, int need_local_type, Mz_CPort *port)
1044 {
1045 if (need_local_type) {
1046 if (scheme_expr_produces_local_type(expr, NULL) != need_local_type)
1047 scheme_ill_formed_code(port);
1048 }
1049 }
1050
validate_join_const(int result,int expected_results)1051 static int validate_join_const(int result, int expected_results)
1052 {
1053 return validate_join_seq(result,
1054 (((expected_results == 1) || (expected_results == -1))
1055 ? 2
1056 : 0));
1057 }
1058
is_functional_nonfailing_rator(Scheme_Object * rator,int num_args,int expected_results,Scheme_Hash_Table ** _st_ht)1059 static int is_functional_nonfailing_rator(Scheme_Object *rator, int num_args, int expected_results,
1060 Scheme_Hash_Table **_st_ht)
1061 {
1062 if (_st_ht && *_st_ht && SAME_TYPE(SCHEME_TYPE(rator), scheme_toplevel_type)) {
1063 int flags = (SCHEME_TOPLEVEL_FLAGS(rator) & SCHEME_TOPLEVEL_FLAGS_MASK);
1064 if (flags == SCHEME_TOPLEVEL_CONST) {
1065 /* could be a struct operation... */
1066 int pos = SCHEME_TOPLEVEL_POS(rator);
1067 Scheme_Object *v;
1068 v = scheme_hash_get(*_st_ht, scheme_make_integer(pos));
1069 if (v) {
1070 int k = SCHEME_INT_VAL(v);
1071 if (((k & STRUCT_PROC_SHAPE_MASK) == STRUCT_PROC_SHAPE_CONSTR)
1072 && (k & STRUCT_PROC_SHAPE_NONFAIL_CONSTR)) {
1073 if (num_args == (k >> STRUCT_PROC_SHAPE_SHIFT))
1074 return 1;
1075 } else if ((k & STRUCT_PROC_SHAPE_MASK) == STRUCT_PROC_SHAPE_PRED) {
1076 if (num_args == 1)
1077 return 1;
1078 }
1079 }
1080 }
1081 }
1082
1083 return scheme_is_functional_nonfailing_primitive(rator, num_args, expected_results);
1084 }
1085
1086 #define CAN_RESET_STACK_SLOT 0
1087 #if !CAN_RESET_STACK_SLOT
1088 # define WHEN_CAN_RESET_STACK_SLOT(x) 0
1089 #else
1090 # define WHEN_CAN_RESET_STACK_SLOT(x) (x)
1091 #endif
1092
validate_expr(Mz_CPort * port,Scheme_Object * expr,char * stack,Validate_TLS tls,int depth,int letlimit,int delta,int num_toplevels,int num_lifts,void * tl_use_map,mzshort * tl_state,mzshort tl_timestamp,Scheme_Object * app_rator,int proc_with_refs_ok,int result_ignored,struct Validate_Clearing * vc,int tailpos,int need_local_type,Scheme_Hash_Tree * procs,int expected_results,Scheme_Hash_Table ** _st_ht)1093 static int validate_expr(Mz_CPort *port, Scheme_Object *expr,
1094 char *stack, Validate_TLS tls,
1095 int depth, int letlimit, int delta,
1096 int num_toplevels, int num_lifts, void *tl_use_map,
1097 mzshort *tl_state, mzshort tl_timestamp,
1098 Scheme_Object *app_rator, int proc_with_refs_ok,
1099 int result_ignored,
1100 struct Validate_Clearing *vc, int tailpos,
1101 int need_local_type, Scheme_Hash_Tree *procs,
1102 int expected_results,
1103 Scheme_Hash_Table **_st_ht)
1104 /* result is 1 if result is `expected_results' values with no
1105 exceptions and no use of any non-ready binding; it's 2 if the
1106 result is furthermore a "constant" (i.e., the same shape result for
1107 every instantiation) */
1108 {
1109 Scheme_Type type;
1110 int did_one = 0, vc_merge = 0, vc_merge_start = 0, result = 2;
1111
1112 #ifdef DO_STACK_CHECK
1113 # include "mzstkchk.h"
1114 {
1115 Scheme_Thread *p = scheme_current_thread;
1116 Scheme_Object *r;
1117 void **pr;
1118 int *args;
1119
1120 args = MALLOC_N_ATOMIC(int, 12);
1121
1122 p->ku.k.p1 = (void *)port;
1123 p->ku.k.p2 = (void *)expr;
1124 p->ku.k.p3 = (void *)stack;
1125 p->ku.k.p4 = (void *)vc;
1126
1127 args[0] = depth;
1128 args[1] = letlimit;
1129 args[2] = delta;
1130 args[3] = num_toplevels;
1131 args[4] = 0; /* not used anymore */
1132 args[5] = num_lifts;
1133 args[6] = proc_with_refs_ok;
1134 args[7] = result_ignored;
1135 args[8] = tailpos;
1136 args[9] = need_local_type;
1137 args[10] = tl_timestamp;
1138 args[11] = expected_results;
1139
1140 pr = MALLOC_N(void*, 7);
1141 pr[0] = (void *)args;
1142 pr[1] = (void *)app_rator;
1143 pr[2] = (void *)tls;
1144 pr[3] = (void *)procs;
1145 pr[4] = tl_use_map;
1146 pr[5] = tl_state;
1147 pr[6] = _st_ht;
1148
1149 p->ku.k.p5 = (void *)pr;
1150
1151 r = scheme_handle_stack_overflow(validate_k);
1152
1153 return SCHEME_INT_VAL(r);
1154 }
1155 #endif
1156
1157 top:
1158 if (did_one) {
1159 if (app_rator) {
1160 if (validate_rator_wants_box(app_rator, proc_with_refs_ok - 2, 0,
1161 tls, num_toplevels, num_lifts,
1162 tl_use_map))
1163 scheme_ill_formed_code(port);
1164 app_rator = NULL;
1165 }
1166 proc_with_refs_ok = 0;
1167 } else
1168 did_one = 1;
1169
1170 type = SCHEME_TYPE(expr);
1171
1172 switch (type) {
1173 case scheme_toplevel_type:
1174 {
1175 int c = SCHEME_TOPLEVEL_DEPTH(expr);
1176 int d = c + delta;
1177 int p = SCHEME_TOPLEVEL_POS(expr);
1178 int flags = (SCHEME_TOPLEVEL_FLAGS(expr) & SCHEME_TOPLEVEL_FLAGS_MASK);
1179
1180 no_typed(need_local_type, port);
1181
1182 if ((c < 0) || (p < 0) || (d < 0) || (d >= depth)
1183 || (stack[d] != VALID_TOPLEVELS)
1184 || (p >= num_toplevels))
1185 scheme_ill_formed_code(port);
1186
1187 if (tl_use_map) {
1188 if ((uintptr_t)tl_use_map & 0x1) {
1189 if (p >= 31)
1190 scheme_ill_formed_code(port);
1191 if (!((uintptr_t)tl_use_map & ((unsigned int)1 << (p + 1))))
1192 scheme_ill_formed_code(port);
1193 } else {
1194 if (p >= (*(int *)tl_use_map * 32))
1195 scheme_ill_formed_code(port);
1196 if (!(((int *)tl_use_map)[1 + (p / 32)] & ((unsigned int)1 << (p & 31))))
1197 scheme_ill_formed_code(port);
1198 }
1199 }
1200
1201 if ((flags > SCHEME_TOPLEVEL_UNKNOWN) && tl_state && (p < num_toplevels)) {
1202 if (p < SCHEME_LINKLET_PREFIX_PREFIX) {
1203 /* instance-access toplevel available? */
1204 if (!tl_state[p])
1205 scheme_ill_formed_code(port);
1206 } else if (tl_state[p] <= 0) {
1207 /* record expectation */
1208 int s = -tl_state[p];
1209 int new_flags;
1210 new_flags = ((flags > (s & SCHEME_TOPLEVEL_FLAGS_MASK))
1211 ? flags
1212 : (s & SCHEME_TOPLEVEL_FLAGS_MASK));
1213 s >>= 2;
1214 if (!s || (tl_timestamp < s))
1215 s = tl_timestamp;
1216 tl_state[p] = -((s << 2) | new_flags);
1217 } else {
1218 /* check expectation */
1219 if (((tl_state[p] & SCHEME_TOPLEVEL_FLAGS_MASK) < flags)
1220 || ((tl_state[p] >> 2) > tl_timestamp)) {
1221 scheme_ill_formed_code(port);
1222 }
1223 }
1224 }
1225
1226 if ((proc_with_refs_ok != 1)
1227 && !argument_to_arity_error(app_rator, proc_with_refs_ok)) {
1228 if (p >= (num_toplevels - num_lifts)) {
1229 /* It's a lift. Check that the lift is defined, and that it
1230 doesn't want reference arguments. */
1231 int tp;
1232 mzshort *a;
1233 tp = p - (num_toplevels - num_lifts);
1234 a = tls[tp];
1235 if (a) {
1236 if (a == (mzshort *)0x1) {
1237 /* Ok */
1238 } else if (a[0] > 0) {
1239 int i, cnt;
1240 cnt = a[0];
1241 for (i = 0; i < cnt; i++) {
1242 if (a[i] == 2)
1243 scheme_ill_formed_code(port);
1244 }
1245 tls[tp] = (mzshort *)0x1;
1246 } else {
1247 /* a[0] is either 0 (top-level ref; shouldn't happen) or < 0 (wants some ref args) */
1248 scheme_ill_formed_code(port);
1249 }
1250 } else {
1251 tls[tp] = (mzshort *)0x1; /* means "no ref args anywhere" */
1252 }
1253 }
1254 }
1255
1256 if (flags == SCHEME_TOPLEVEL_UNKNOWN)
1257 result = validate_join_seq(result, 0);
1258 else {
1259 result = validate_join_const(result, expected_results);
1260 if (flags < SCHEME_TOPLEVEL_CONST)
1261 result = validate_join_seq(result, 1);
1262 }
1263 }
1264 break;
1265 case scheme_local_type:
1266 {
1267 int q = SCHEME_LOCAL_POS(expr);
1268 int p = q + delta;
1269 int ct;
1270
1271 if ((q < 0) || (p >= depth) || (p < 0))
1272 scheme_ill_formed_code(port);
1273
1274 ct = SCHEME_GET_LOCAL_TYPE(expr);
1275 if (!ct)
1276 no_typed(need_local_type, port);
1277
1278 if (ct) {
1279 if (stack[p] != (VALID_TYPED + ct))
1280 scheme_ill_formed_code(port);
1281 } else if ((stack[p] != VALID_VAL) && (stack[p] != VALID_VAL_NOCLEAR)) {
1282 if (result_ignored && ((stack[p] == VALID_BOX)
1283 || (stack[p] == VALID_BOX_NOCLEAR)
1284 || (stack[p] >= VALID_TYPED))) {
1285 /* ok to look up and ignore box or typed */
1286 } else if ((proc_with_refs_ok >= 2)
1287 && ((stack[p] == VALID_BOX) || (stack[p] == VALID_BOX_NOCLEAR))
1288 && validate_rator_wants_box(app_rator, proc_with_refs_ok - 2, 1,
1289 tls, num_toplevels, num_lifts,
1290 tl_use_map)) {
1291 /* It's ok - the function wants us to pass it a box, and
1292 we did. */
1293 app_rator = NULL;
1294 } else
1295 scheme_ill_formed_code(port);
1296 }
1297
1298 if (SCHEME_GET_LOCAL_FLAGS(expr) == SCHEME_LOCAL_CLEAR_ON_READ) {
1299 if ((stack[p] == VALID_VAL_NOCLEAR)
1300 || (stack[p] == VALID_BOX_NOCLEAR)
1301 || (stack[p] >= VALID_TYPED))
1302 scheme_ill_formed_code(port);
1303 if (p >= letlimit)
1304 clearing_stack_push(vc, p, stack[p]);
1305 stack[p] = VALID_NOT;
1306 } else if (!(SCHEME_GET_LOCAL_FLAGS(expr) == SCHEME_LOCAL_OTHER_CLEARS)) {
1307 if (stack[p] == VALID_BOX) {
1308 if (p >= letlimit)
1309 noclear_stack_push(vc, p);
1310 stack[p] = VALID_BOX_NOCLEAR;
1311 } else if (stack[p] == VALID_VAL) {
1312 if (p >= letlimit)
1313 noclear_stack_push(vc, p);
1314 stack[p] = VALID_VAL_NOCLEAR;
1315 }
1316 }
1317
1318 if (procs && !proc_with_refs_ok && !result_ignored) {
1319 if (scheme_hash_tree_get(procs, scheme_make_integer(p)))
1320 scheme_ill_formed_code(port);
1321 }
1322
1323 result = validate_join_const(result, expected_results);
1324 }
1325 break;
1326 case scheme_local_unbox_type:
1327 {
1328 int q = SCHEME_LOCAL_POS(expr);
1329 int p = q + delta;
1330
1331 no_typed(need_local_type, port);
1332
1333 if ((q < 0) || (p >= depth) || (p < 0)
1334 || ((stack[p] != VALID_BOX)
1335 && (stack[p] != VALID_BOX_NOCLEAR)))
1336 scheme_ill_formed_code(port);
1337
1338 if (SCHEME_GET_LOCAL_FLAGS(expr) == SCHEME_LOCAL_CLEAR_ON_READ) {
1339 if (stack[p] == VALID_BOX_NOCLEAR)
1340 scheme_ill_formed_code(port);
1341 if (p >= letlimit)
1342 clearing_stack_push(vc, p, stack[p]);
1343 stack[p] = VALID_NOT;
1344 } else if (!(SCHEME_GET_LOCAL_FLAGS(expr) == SCHEME_LOCAL_OTHER_CLEARS)) {
1345 if (stack[p] == VALID_BOX) {
1346 if (p >= letlimit)
1347 noclear_stack_push(vc, p);
1348 stack[p] = VALID_BOX_NOCLEAR;
1349 }
1350 }
1351
1352 result = validate_join_const(result, expected_results);
1353 }
1354 break;
1355 case scheme_application_type:
1356 {
1357 Scheme_App_Rec *app = (Scheme_App_Rec *)expr;
1358 int i, n, r;
1359
1360 check_typed(expr, need_local_type, port);
1361
1362 n = app->num_args + 1;
1363
1364 delta -= (n - 1);
1365 if (delta < 0)
1366 scheme_ill_formed_code(port);
1367 memset(stack + delta, VALID_NOT, n - 1);
1368
1369 for (i = 0; i < n; i++) {
1370 r = validate_expr(port, app->args[i], stack, tls, depth, letlimit, delta,
1371 num_toplevels, num_lifts, tl_use_map,
1372 tl_state, tl_timestamp,
1373 i ? app->args[0] : NULL, i + 1, 0, vc, 0, 0, procs, 1, _st_ht);
1374 result = validate_join(result, r);
1375 }
1376
1377 if (tailpos)
1378 check_self_call_valid(app->args[0], port, vc, delta, stack);
1379
1380 if (result) {
1381 r = is_functional_nonfailing_rator(app->args[0], app->num_args, expected_results, _st_ht);
1382 result = validate_join(result, r);
1383 }
1384 }
1385 break;
1386 case scheme_application2_type:
1387 {
1388 Scheme_App2_Rec *app = (Scheme_App2_Rec *)expr;
1389 int r;
1390
1391 check_typed(expr, need_local_type, port);
1392
1393 delta -= 1;
1394 if (delta < 0)
1395 scheme_ill_formed_code(port);
1396 stack[delta] = VALID_NOT;
1397
1398 r = validate_expr(port, app->rator, stack, tls, depth, letlimit, delta,
1399 num_toplevels, num_lifts, tl_use_map,
1400 tl_state, tl_timestamp,
1401 NULL, 1, 0, vc, 0, 0, procs, 1, _st_ht);
1402 result = validate_join(r, result);
1403 r = validate_expr(port, app->rand, stack, tls, depth, letlimit, delta,
1404 num_toplevels, num_lifts, tl_use_map,
1405 tl_state, tl_timestamp,
1406 app->rator, 2, 0, vc, 0, 0, procs, 1, _st_ht);
1407 result = validate_join(r, result);
1408
1409 if (tailpos)
1410 check_self_call_valid(app->rator, port, vc, delta, stack);
1411
1412 if (result) {
1413 r = is_functional_nonfailing_rator(app->rator, 1, expected_results, _st_ht);
1414 if (!r
1415 && SAME_OBJ(app->rator, scheme_make_vector_proc)
1416 && (expected_results == 1 || expected_results == -1)
1417 && (SCHEME_INTP(app->rand)
1418 && (SCHEME_INT_VAL(app->rand) >= 0)
1419 && IN_FIXNUM_RANGE_ON_ALL_PLATFORMS(SCHEME_INT_VAL(app->rand)))) {
1420 r = 1;
1421 }
1422 result = validate_join(result, r);
1423 }
1424 }
1425 break;
1426 case scheme_application3_type:
1427 {
1428 Scheme_App3_Rec *app = (Scheme_App3_Rec *)expr;
1429 int r;
1430
1431 check_typed(expr, need_local_type, port);
1432
1433 delta -= 2;
1434 if (delta < 0)
1435 scheme_ill_formed_code(port);
1436 stack[delta] = VALID_NOT;
1437 stack[delta+1] = VALID_NOT;
1438
1439 r = validate_expr(port, app->rator, stack, tls, depth, letlimit, delta,
1440 num_toplevels, num_lifts, tl_use_map,
1441 tl_state, tl_timestamp,
1442 NULL, 1, 0, vc, 0, 0, procs, 1, _st_ht);
1443 result = validate_join(r, result);
1444 r = validate_expr(port, app->rand1, stack, tls, depth, letlimit, delta,
1445 num_toplevels, num_lifts, tl_use_map,
1446 tl_state, tl_timestamp,
1447 app->rator, 2, 0, vc, 0, 0, procs, 1, _st_ht);
1448 result = validate_join(r, result);
1449 r = validate_expr(port, app->rand2, stack, tls, depth, letlimit, delta,
1450 num_toplevels, num_lifts, tl_use_map,
1451 tl_state, tl_timestamp,
1452 app->rator, 3, 0, vc, 0, 0, procs, 1, _st_ht);
1453 result = validate_join(r, result);
1454
1455 if (tailpos)
1456 check_self_call_valid(app->rator, port, vc, delta, stack);
1457
1458 if (result) {
1459 r = is_functional_nonfailing_rator(app->rator, 2, expected_results, _st_ht);
1460 if (!r
1461 && SAME_OBJ(app->rator, scheme_make_vector_proc)
1462 && (expected_results == 1 || expected_results == -1)
1463 && (SCHEME_INTP(app->rand1)
1464 && (SCHEME_INT_VAL(app->rand1) >= 0)
1465 && IN_FIXNUM_RANGE_ON_ALL_PLATFORMS(SCHEME_INT_VAL(app->rand1)))) {
1466 r = 1;
1467 }
1468 result = validate_join(r, result);
1469 }
1470 }
1471 break;
1472 case scheme_sequence_type:
1473 {
1474 Scheme_Sequence *seq = (Scheme_Sequence *)expr;
1475 int cnt;
1476 int i, r;
1477
1478 if (type != scheme_sequence_type)
1479 no_typed(need_local_type, port);
1480
1481 cnt = seq->count;
1482
1483 for (i = 0; i < cnt - 1; i++) {
1484 r = validate_expr(port, seq->array[i], stack, tls, depth, letlimit, delta,
1485 num_toplevels, num_lifts, tl_use_map,
1486 tl_state, tl_timestamp,
1487 NULL, 0, 1, vc, 0, 0, procs, -1, _st_ht);
1488 result = validate_join_seq(result, r);
1489 }
1490
1491 expr = seq->array[cnt - 1];
1492 goto top;
1493 }
1494 break;
1495 case scheme_branch_type:
1496 {
1497 Scheme_Branch_Rec *b;
1498 int vc_pos, vc_ncpos, r;
1499
1500 b = (Scheme_Branch_Rec *)expr;
1501 r = validate_expr(port, b->test, stack, tls, depth, letlimit, delta,
1502 num_toplevels, num_lifts, tl_use_map,
1503 tl_state, tl_timestamp,
1504 NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
1505 result = validate_join(r, result);
1506
1507 /* This is where letlimit is useful. It prevents let-assignment in the
1508 "then" branch that could permit bad code in the "else" branch (or the
1509 same thing with either branch affecting later code in a sequence). */
1510 letlimit = delta;
1511 vc_pos = vc->stackpos;
1512 vc_ncpos = vc->ncstackpos;
1513 r = validate_expr(port, b->tbranch, stack, tls, depth, letlimit, delta,
1514 num_toplevels, num_lifts, tl_use_map,
1515 tl_state, tl_timestamp,
1516 NULL, 0, result_ignored, vc, tailpos, need_local_type, procs,
1517 expected_results, _st_ht);
1518 result = validate_join_seq(result, r);
1519
1520 /* since we're branchig, the result isn't constant: */
1521 result = validate_join(1, result);
1522
1523 /* Rewind clears and noclears, but also save the clears,
1524 so that the branches' effects can be merged. */
1525 {
1526 int i, j;
1527
1528 if (!vc_merge) {
1529 vc_merge = 1;
1530 vc_merge_start = vc_pos;
1531 }
1532
1533 for (i = vc->stackpos - 2; i >= vc_pos; i -= 2) {
1534 stack[vc->stack[i]] = vc->stack[i + 1];
1535 }
1536
1537 for (i = vc->ncstackpos - 1; i >= vc_ncpos; i--) {
1538 j = vc->ncstack[i];
1539 if (stack[j] == VALID_VAL_NOCLEAR)
1540 stack[j] = VALID_VAL;
1541 else if (stack[j] == VALID_BOX_NOCLEAR)
1542 stack[j] = VALID_BOX;
1543 }
1544 vc->ncstackpos = vc_ncpos;
1545 }
1546
1547 expr = b->fbranch;
1548 goto top;
1549 }
1550 break;
1551 case scheme_with_cont_mark_type:
1552 {
1553 Scheme_With_Continuation_Mark *wcm = (Scheme_With_Continuation_Mark *)expr;
1554 int r;
1555
1556 r = validate_expr(port, wcm->key, stack, tls, depth, letlimit, delta,
1557 num_toplevels, num_lifts, tl_use_map,
1558 tl_state, tl_timestamp,
1559 NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
1560 result = validate_join_seq(result, r);
1561 r = validate_expr(port, wcm->val, stack, tls, depth, letlimit, delta,
1562 num_toplevels, num_lifts, tl_use_map,
1563 tl_state, tl_timestamp,
1564 NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
1565 result = validate_join_seq(result, r);
1566
1567 expr = wcm->body;
1568 goto top;
1569 }
1570 break;
1571 case scheme_lambda_type:
1572 {
1573 no_typed(need_local_type, port);
1574 validate_lambda(port, expr, stack, tls, depth, delta,
1575 num_toplevels, num_lifts, tl_use_map,
1576 tl_state, tl_timestamp,
1577 app_rator, proc_with_refs_ok, -1, procs, _st_ht);
1578
1579 result = validate_join_const(result, expected_results);
1580 }
1581 break;
1582 case scheme_let_value_type:
1583 {
1584 Scheme_Let_Value *lv = (Scheme_Let_Value *)expr;
1585 int q, p, c, i, r;
1586
1587 r = validate_expr(port, lv->value, stack, tls, depth, letlimit, delta,
1588 num_toplevels, num_lifts, tl_use_map,
1589 tl_state, tl_timestamp,
1590 NULL, 0, 0, vc, 0, 0, procs, lv->count, _st_ht);
1591 result = validate_join_seq(r, result);
1592
1593 /* memset(stack, VALID_NOT, delta); <-- seems unnecessary (and slow) */
1594
1595 c = lv->count;
1596 q = lv->position;
1597 p = q + delta;
1598
1599 for (i = 0; i < c; i++, p++) {
1600 if ((q < 0)
1601 || (p < 0)
1602 || (SCHEME_LET_VALUE_AUTOBOX(lv) && ((p >= depth)
1603 || ((stack[p] != VALID_BOX)
1604 && (stack[p] != VALID_BOX_NOCLEAR))))
1605 || (!SCHEME_LET_VALUE_AUTOBOX(lv) && ((p >= letlimit)
1606 || !(WHEN_CAN_RESET_STACK_SLOT(stack[p] == VALID_VAL)
1607 || WHEN_CAN_RESET_STACK_SLOT(stack[p] == VALID_VAL_NOCLEAR)
1608 || (stack[p] == VALID_UNINIT)))))
1609 scheme_ill_formed_code(port);
1610
1611 if (!SCHEME_LET_VALUE_AUTOBOX(lv)) {
1612 if (stack[p] != VALID_VAL_NOCLEAR)
1613 stack[p] = VALID_VAL;
1614 }
1615 }
1616
1617 expr = lv->body;
1618 goto top;
1619 }
1620 break;
1621 case scheme_let_void_type:
1622 {
1623 Scheme_Let_Void *lv = (Scheme_Let_Void *)expr;
1624 int c, i;
1625
1626 c = lv->count;
1627
1628 if ((c < 0) || (c > delta))
1629 scheme_ill_formed_code(port);
1630
1631 if (SCHEME_LET_VOID_AUTOBOX(lv)) {
1632 for (i = 0; i < c; i++) {
1633 stack[--delta] = VALID_BOX;
1634 }
1635 } else {
1636 delta -= c;
1637 memset(stack + delta, VALID_UNINIT, c);
1638 }
1639
1640 expr = lv->body;
1641 goto top;
1642 }
1643 break;
1644 case scheme_letrec_type:
1645 {
1646 Scheme_Letrec *l = (Scheme_Letrec *)expr;
1647 Scheme_Lambda *data;
1648 int i, c;
1649
1650 c = l->count;
1651
1652 if ((c < 0) || (c + delta > depth))
1653 scheme_ill_formed_code(port);
1654
1655 for (i = 0; i < c; i++) {
1656 if (!SAME_TYPE(SCHEME_TYPE(l->procs[i]), scheme_lambda_type))
1657 scheme_ill_formed_code(port);
1658 }
1659
1660 for (i = 0; i < c; i++) {
1661 #if !CAN_RESET_STACK_SLOT
1662 if (stack[delta + i] != VALID_UNINIT)
1663 scheme_ill_formed_code(port);
1664 #endif
1665 stack[delta + i] = VALID_VAL;
1666 data = (Scheme_Lambda *)l->procs[i];
1667 if (SCHEME_LAMBDA_FLAGS(data) & LAMBDA_HAS_TYPED_ARGS) {
1668 /* If any arguments (as opposed to closure slots) are typed, then
1669 add the procedure to `procs': */
1670 int j;
1671 for (j = data->num_params; j--; ) {
1672 if (scheme_boxmap_get(data->closure_map, j, data->closure_size))
1673 break;
1674 }
1675 if (j >= 0) {
1676 procs = scheme_hash_tree_set(as_nonempty_procs(procs),
1677 scheme_make_integer(delta + i),
1678 l->procs[i]);
1679 }
1680 }
1681 }
1682
1683 for (i = 0; i < c; i++) {
1684 validate_lambda(port, l->procs[i], stack, tls, depth, delta,
1685 num_toplevels, num_lifts, tl_use_map,
1686 tl_state, tl_timestamp,
1687 NULL, 1, i, procs, _st_ht);
1688 }
1689
1690 expr = l->body;
1691 goto top;
1692 }
1693 break;
1694 case scheme_let_one_type:
1695 {
1696 Scheme_Let_One *lo = (Scheme_Let_One *)expr;
1697 int r;
1698
1699 --delta;
1700 if (delta < 0)
1701 scheme_ill_formed_code(port);
1702 stack[delta] = VALID_UNINIT;
1703
1704 r = validate_expr(port, lo->value, stack, tls, depth, letlimit, delta,
1705 num_toplevels, num_lifts, tl_use_map,
1706 tl_state, tl_timestamp,
1707 NULL, 0, 0, vc, 0, SCHEME_LET_ONE_TYPE(lo), procs,
1708 1, _st_ht);
1709 result = validate_join_seq(r, result);
1710
1711 #if !CAN_RESET_STACK_SLOT
1712 if (stack[delta] != VALID_UNINIT)
1713 scheme_ill_formed_code(port);
1714 #endif
1715
1716 if (SCHEME_LET_EVAL_TYPE(lo) & LET_ONE_UNUSED) {
1717 stack[delta] = VALID_NOT;
1718 } else if (SCHEME_LET_ONE_TYPE(lo)) {
1719 stack[delta] = (VALID_TYPED + SCHEME_LET_ONE_TYPE(lo));
1720 /* FIXME: need to check that lo->value produces a flonum */
1721 } else
1722 stack[delta] = VALID_VAL;
1723
1724 expr = lo->body;
1725 goto top;
1726 }
1727 break;
1728
1729 case scheme_define_values_type:
1730 no_typed(need_local_type, port);
1731 result = validate_join_seq(result,
1732 define_values_validate(expr, port, stack, tls, depth, letlimit, delta,
1733 num_toplevels, num_lifts, tl_use_map,
1734 tl_state, tl_timestamp,
1735 result_ignored, vc, tailpos, procs,
1736 _st_ht));
1737 break;
1738 case scheme_set_bang_type:
1739 no_typed(need_local_type, port);
1740 result = validate_join_seq(result,
1741 set_validate(expr, port, stack, tls, depth, letlimit, delta,
1742 num_toplevels, num_lifts, tl_use_map,
1743 tl_state, tl_timestamp,
1744 result_ignored, vc, tailpos, procs, _st_ht));
1745 break;
1746 case scheme_boxenv_type:
1747 no_typed(need_local_type, port);
1748 result = validate_join_seq(result,
1749 bangboxenv_validate(expr, port, stack, tls, depth, letlimit, delta,
1750 num_toplevels, num_lifts, tl_use_map,
1751 tl_state, tl_timestamp,
1752 result_ignored, vc, tailpos, procs, _st_ht, expected_results));
1753 break;
1754 case scheme_begin0_sequence_type:
1755 no_typed(need_local_type, port);
1756 result = validate_join_seq(result,
1757 begin0_validate(expr, port, stack, tls, depth, letlimit, delta,
1758 num_toplevels, num_lifts, tl_use_map,
1759 tl_state, tl_timestamp,
1760 result_ignored, vc, tailpos, procs, _st_ht, expected_results));
1761 break;
1762 case scheme_varref_form_type:
1763 no_typed(need_local_type, port);
1764 ref_validate(expr, port, stack, tls, depth, letlimit, delta,
1765 num_toplevels, num_lifts, tl_use_map,
1766 tl_state, tl_timestamp,
1767 result_ignored, vc, tailpos, procs);
1768 result = validate_join_const(result, expected_results);
1769 break;
1770 case scheme_apply_values_type:
1771 no_typed(need_local_type, port);
1772 apply_values_validate(expr, port, stack, tls, depth, letlimit, delta,
1773 num_toplevels, num_lifts, tl_use_map,
1774 tl_state, tl_timestamp,
1775 result_ignored, vc, tailpos, procs, _st_ht);
1776 result = validate_join(0, result);
1777 break;
1778 case scheme_with_immed_mark_type:
1779 {
1780 Scheme_With_Continuation_Mark *wcm = (Scheme_With_Continuation_Mark *)expr;
1781 int r;
1782
1783 no_typed(need_local_type, port);
1784
1785 r = validate_expr(port, wcm->key, stack, tls, depth, letlimit, delta,
1786 num_toplevels, num_lifts, tl_use_map,
1787 tl_state, tl_timestamp,
1788 NULL, 0, 0, vc, 0, 0, procs,
1789 1, _st_ht);
1790 result = validate_join_seq(r, result);
1791
1792 r = validate_expr(port, wcm->val, stack, tls, depth, letlimit, delta,
1793 num_toplevels, num_lifts, tl_use_map,
1794 tl_state, tl_timestamp,
1795 NULL, 0, 0, vc, 0, 0, procs,
1796 1, _st_ht);
1797 result = validate_join_seq(r, result);
1798
1799 --delta;
1800 if (delta < 0)
1801 scheme_ill_formed_code(port);
1802 stack[delta] = VALID_VAL;
1803
1804 expr = wcm->body;
1805 goto top;
1806 }
1807 break;
1808 case scheme_case_lambda_sequence_type:
1809 no_typed(need_local_type, port);
1810 case_lambda_validate(expr, port, stack, tls, depth, letlimit, delta,
1811 num_toplevels, num_lifts, tl_use_map,
1812 tl_state, tl_timestamp,
1813 result_ignored, vc, tailpos, procs, _st_ht);
1814 result = validate_join_const(result, expected_results);
1815 break;
1816 case scheme_inline_variant_type:
1817 no_typed(need_local_type, port);
1818 inline_variant_validate(expr, port, stack, tls, depth, letlimit, delta,
1819 num_toplevels, num_lifts, tl_use_map,
1820 tl_state, tl_timestamp,
1821 result_ignored, vc, tailpos, procs, _st_ht);
1822 result = validate_join_const(result, expected_results);
1823 break;
1824 case scheme_ir_local_type:
1825 {
1826 scheme_ill_formed_code(port);
1827 }
1828 default:
1829 /* All values are definitely ok, except pre-closed closures.
1830 Such a closure can refer back to itself, so we use a flag
1831 to track cycles. Also check need_local_type. */
1832 result = validate_join_const(result, expected_results);
1833 if (SAME_TYPE(type, scheme_closure_type)
1834 /* If the closure is not empty, then it must be from 3-D code
1835 (where PLT_VALIDATE_COMPILE is set), and validation is not
1836 our responsibility here: */
1837 && (SCHEME_CLOSURE_CODE(expr)->closure_size == 0)) {
1838 Scheme_Lambda *data;
1839 no_typed(need_local_type, port);
1840 expr = (Scheme_Object *)SCHEME_CLOSURE_CODE(expr);
1841 data = (Scheme_Lambda *)expr;
1842 if ((SCHEME_LAMBDA_FLAGS(data) & LAMBDA_STATUS_MASK) == LAMBDA_STATUS_VALIDATED) {
1843 /* Done with this one. */
1844 } else {
1845 SCHEME_LAMBDA_FLAGS(data) = (SCHEME_LAMBDA_FLAGS(data) & ~LAMBDA_STATUS_MASK) | LAMBDA_STATUS_VALIDATED;
1846 did_one = 0;
1847 goto top;
1848 }
1849 } else if (SAME_TYPE(type, scheme_case_closure_type)) {
1850 Scheme_Case_Lambda *seq;
1851 int i;
1852 seq = (Scheme_Case_Lambda *)expr;
1853 for (i = 0; i < seq->count; i++) {
1854 validate_expr(port, seq->array[i], stack, tls, depth, letlimit, delta,
1855 num_toplevels, num_lifts, tl_use_map,
1856 tl_state, tl_timestamp,
1857 NULL, 0, 0, vc, 0, 0, procs, 1, _st_ht);
1858 }
1859 } else if (need_local_type) {
1860 if (SCHEME_DBLP(expr) && (need_local_type == SCHEME_LOCAL_TYPE_FLONUM))
1861 need_local_type = 0;
1862 #ifdef MZ_LONG_DOUBLE
1863 if (SCHEME_LONG_DBLP(expr) && (need_local_type == SCHEME_LOCAL_TYPE_EXTFLONUM))
1864 need_local_type = 0;
1865 #endif
1866 if (SCHEME_INTP(expr) && (need_local_type == SCHEME_LOCAL_TYPE_FIXNUM))
1867 need_local_type = 0;
1868 no_typed(need_local_type, port);
1869 }
1870 break;
1871 }
1872
1873 if (app_rator)
1874 if (validate_rator_wants_box(app_rator, proc_with_refs_ok - 2, 0,
1875 tls, num_toplevels, num_lifts, tl_use_map))
1876 scheme_ill_formed_code(port);
1877
1878 if (vc_merge) {
1879 /* Re-clear to merge effects from branches */
1880 int i, p;
1881 for (i = vc_merge_start; i < vc->stackpos; i += 2) {
1882 p = vc->stack[i];
1883 stack[p] = VALID_NOT;
1884 }
1885 }
1886
1887 return result;
1888 }
1889
1890 /*========================================================================*/
1891 /* precise GC traversers */
1892 /*========================================================================*/
1893
1894 #ifdef MZ_PRECISE_GC
1895
1896 START_XFORM_SKIP;
1897
1898 #include "mzmark_validate.inc"
1899
register_traversers(void)1900 static void register_traversers(void)
1901 {
1902 GC_REG_TRAV(scheme_rt_validate_clearing, mark_validate_clearing);
1903 }
1904
1905 END_XFORM_SKIP;
1906
1907 #endif
1908