1 #include "local_context.hh"
2
3 /*
4 ** every subclass of local_context has a transfer method which keeps track
5 ** of the variable states during branching. These transfer methods are
6 ** called in method_desc::parse_code(
7 ** constant** constant_pool, const field_desc* is_this)
8 ** for every bytecode and at the end after parsing all the bytecode of the method
9 ** before cleanup to pop up all the local variables.
10 */
11
12
13
transfer(method_desc * method,vbm_operand * sp,byte,byte &)14 vbm_operand* ctx_push_var::transfer(method_desc* method, vbm_operand* sp,
15 byte, byte&)
16 {
17 var_desc* var = &method->vars[var_index];
18 if (var->type == tp_void) {
19 if (IS_INT_TYPE(var_type)) {
20 var->min = ranges[var_type].min;
21 var->max = ranges[var_type].max;
22 var->mask = var->min|var->max;
23 } else if (var_type == tp_long) {
24 var[0].min = 0x80000000;
25 var[0].max = 0x7fffffff;
26 var[0].mask = 0xffffffff;
27 var[1].min = 0;
28 var[1].max = 0xffffffff;
29 var[1].mask = 0xffffffff;
30 } else {
31 var->mask = (var->type == tp_self)
32 ? var_desc::vs_not_null : var_desc::vs_unknown;
33 var->min = 0;
34 var->max = MAX_ARRAY_LENGTH;
35 }
36 }
37 var->type = var_type;
38 var->name = *var_name;
39 var->start_pc = var_start_pc;
40 return sp;
41 }
42
transfer(method_desc * method,vbm_operand * sp,byte,byte &)43 vbm_operand* ctx_pop_var::transfer(method_desc* method, vbm_operand* sp,
44 byte, byte&)
45 {
46 var_desc* var = &method->vars[var_index];
47 for (field_desc* field = method->cls->fields;
48 field != NULL;
49 field = field->next)
50 {
51 // Do not produce message about shadowing of class camponent by local
52 // variable in case when local variable is formal parameter of the
53 // method and programmer explicitly refer class object component
54 // by "this": this.x = x;
55 if (field->name == var->name
56 && (!(field->attr & field_desc::f_used)
57 || var->start_pc != 0 /* not formal parameter*/))
58 {
59 method->message(msg_shadow_local, var->start_pc,
60 &var->name, method->cls);
61 break;
62 }
63 }
64 var->type = tp_void;
65 var->name = utf_string("???");
66 return sp;
67 }
68
69
transfer(method_desc * method,vbm_operand * sp,byte cop,byte & prev_cop)70 vbm_operand* ctx_split::transfer(method_desc* method, vbm_operand* sp,
71 byte cop, byte& prev_cop)
72 {
73 if (n_branches > 0 && cmd == cmd_save_ctx) {
74 vars = new var_desc[method->n_vars];
75 memcpy(vars, method->vars, method->n_vars*sizeof(var_desc));
76 } else {
77 vars = NULL;
78 }
79 switch_var_index = -1;
80 in_monitor = method->in_monitor;
81
82 vbm_operand* left_op = sp-2;
83 vbm_operand* right_op = sp-1;
84
85 switch (cop) {
86 case jsr:
87 case jsr_w:
88 sp->type = tp_object;
89 sp->mask = var_desc::vs_not_null;
90 sp->min = 0;
91 sp->max = MAX_ARRAY_LENGTH;
92 stack_pointer = sp+1;
93 break;
94 case tableswitch:
95 case lookupswitch:
96 stack_pointer = right_op;
97 switch_var_index = right_op->index;
98 break;
99 case ifeq:
100 if (vars != NULL && right_op->index >= 0) {
101 // state at the branch address
102 var_desc* var = &vars[right_op->index];
103 if (prev_cop == iand) {
104 // Operation of form (x & const) == 0
105 if (IS_INT_TYPE(var->type)) {
106 var->mask &= ~right_op->mask;
107 }
108 } else {
109 var->max = var->min = 0;
110 if (IS_INT_TYPE(var->type)) {
111 var->mask = 0;
112 }
113 }
114 }
115 stack_pointer = right_op;
116 break;
117 case ifne:
118 if (right_op->index >= 0) { // value of local var. was pushed on stack
119 // state after if
120 var_desc* var = &method->vars[right_op->index];
121 if (prev_cop == iand) {
122 // Operation of form (x & const) != 0
123 if (IS_INT_TYPE(var->type)) {
124 var->mask &= ~right_op->mask;
125 }
126 } else {
127 var->max = var->min = 0;
128 if (IS_INT_TYPE(var->type)) {
129 var->mask = 0;
130 }
131 }
132 }
133 stack_pointer = right_op;
134 break;
135 case iflt:
136 if (right_op->index >= 0) {
137 // state after if
138 var_desc* var = &method->vars[right_op->index];
139 if (var->min < 0) var->min = 0;
140 if (var->max < 0) var->max = 0;
141 if (IS_INT_TYPE(var->type)) {
142 var->mask &= ~SIGN_BIT;
143 }
144 if (vars != NULL) { // forward branch
145 // state at the branch address
146 var = &vars[right_op->index];
147 if (var->min >= 0) var->min = -1;
148 if (var->max >= 0) var->max = -1;
149 }
150 }
151 stack_pointer = right_op;
152 break;
153 case ifge:
154 if (right_op->index >= 0) {
155 // state after if
156 var_desc* var = &method->vars[right_op->index];
157 if (var->min >= 0) var->min = -1;
158 if (var->max >= 0) var->max = -1;
159 if (vars != NULL) { // forward branch
160 // state at the branch address
161 var = &vars[right_op->index];
162 if (var->min < 0) var->min = 0;
163 if (var->max < 0) var->max = 0;
164 if (IS_INT_TYPE(var->type)) {
165 var->mask &= ~SIGN_BIT;
166 }
167 }
168 }
169 stack_pointer = right_op;
170 break;
171 case ifgt:
172 if (right_op->index >= 0) {
173 // state after if
174 var_desc* var = &method->vars[right_op->index];
175 if (var->min > 0) var->min = 0;
176 if (var->max > 0) var->max = 0;
177 if (vars != NULL) { // forward branch
178 // state at the branch address
179 var = &vars[right_op->index];
180 if (var->min <= 0) var->min = 1;
181 if (var->max <= 0) var->max = 1;
182 if (IS_INT_TYPE(var->type)) {
183 var->mask &= ~SIGN_BIT;
184 }
185 }
186 }
187 stack_pointer = right_op;
188 break;
189 case ifle:
190 if (right_op->index >= 0) {
191 // state after if
192 var_desc* var = &method->vars[right_op->index];
193 if (var->min <= 0) var->min = 1;
194 if (var->max <= 0) var->max = 1;
195 if (IS_INT_TYPE(var->type)) {
196 var->mask &= ~SIGN_BIT;
197 }
198 if (vars != NULL) { // forward branch
199 // state at the branch address
200 var = &vars[right_op->index];
201 if (var->min > 0) var->min = 0;
202 if (var->max > 0) var->max = 0;
203 }
204 }
205 stack_pointer = right_op;
206 break;
207 case if_icmpeq:
208 if (vars != NULL) {
209 // state at the branch address
210 if (right_op->index >= 0) {
211 var_desc* var = &vars[right_op->index];
212 if (var->min < left_op->min) var->min = left_op->min;
213 if (var->max > left_op->max) var->max = left_op->max;
214 if (var->min > var->max) var->min = var->max; // recovery
215 if (IS_INT_TYPE(var->type)) {
216 var->mask &= left_op->mask;
217 }
218 }
219 if (left_op->index >= 0) {
220 var_desc* var = &vars[left_op->index];
221 if (var->min < right_op->min) var->min = right_op->min;
222 if (var->max > right_op->max) var->max = right_op->max;
223 if (var->min > var->max) var->min = var->max; // recovery
224 if (IS_INT_TYPE(var->type)) {
225 var->mask &= right_op->mask;
226 }
227 }
228 }
229 stack_pointer = left_op;
230 break;
231 case if_icmpne:
232 if (right_op->index >= 0) {
233 // state after if
234 var_desc* var = &method->vars[right_op->index];
235 if (var->min < left_op->min) var->min = left_op->min;
236 if (var->max > left_op->max) var->max = left_op->max;
237 if (var->min > var->max) var->min = var->max; // recovery
238 if (IS_INT_TYPE(var->type)) {
239 var->mask &= left_op->mask;
240 }
241 }
242 if (left_op->index >= 0) {
243 var_desc* var = &method->vars[left_op->index];
244 if (var->min < right_op->min) var->min = right_op->min;
245 if (var->max > right_op->max) var->max = right_op->max;
246 if (var->min > var->max) var->min = var->max; // recovery
247 if (IS_INT_TYPE(var->type)) {
248 var->mask &= right_op->mask;
249 }
250 }
251 stack_pointer = left_op;
252 break;
253 case if_icmplt:
254 if (right_op->index >= 0) {
255 // left >= right
256 var_desc* var = &method->vars[right_op->index];
257 if (var->max > left_op->max) {
258 var->max = left_op->max;
259 if (var->min > var->max) var->min = var->max;
260 }
261 if (vars != NULL) {
262 // left < right
263 var = &vars[right_op->index];
264 if (var->min <= left_op->min) {
265 var->min = left_op->min == ranges[tp_int].max
266 ? left_op->min : left_op->min+1;
267 if (var->min > var->max) var->max = var->min;
268 }
269 }
270 }
271 if (left_op->index >= 0) {
272 // left >= right
273 var_desc* var = &method->vars[left_op->index];
274 if (var->min < right_op->min) {
275 var->min = right_op->min;
276 if (var->min > var->max) var->max = var->min;
277 }
278 if (vars != NULL) {
279 // left < right
280 var = &vars[left_op->index];
281 if (var->max >= right_op->max) {
282 var->max = right_op->max == ranges[tp_int].min
283 ? right_op->max : right_op->max-1;
284 if (var->min > var->max) var->min = var->max;
285 }
286 }
287 }
288 stack_pointer = left_op;
289 break;
290 case if_icmple:
291 if (right_op->index >= 0) {
292 // left > right
293 var_desc* var = &method->vars[right_op->index];
294 if (var->max >= left_op->max) {
295 var->max = left_op->max == ranges[tp_int].min
296 ? left_op->max : left_op->max-1;
297 if (var->min > var->max) var->min = var->max;
298 }
299 if (vars != NULL) {
300 // left <= right
301 var = &vars[right_op->index];
302 if (var->min < left_op->min) {
303 var->min = left_op->min;
304 if (var->min > var->max) var->max = var->min;
305 }
306 }
307 }
308 if (left_op->index >= 0) {
309 // left > right
310 var_desc* var = &method->vars[left_op->index];
311 if (var->min <= right_op->min) {
312 var->min = right_op->min == ranges[tp_int].max
313 ? right_op->min : right_op->min+1;
314 if (var->min > var->max) var->max = var->min;
315 }
316 if (vars != NULL) {
317 // left <= right
318 var = &vars[left_op->index];
319 if (var->max > right_op->max) {
320 var->max = right_op->max;
321 if (var->min > var->max) var->min = var->max;
322 }
323 }
324 }
325 stack_pointer = left_op;
326 break;
327 case if_icmpgt:
328 if (right_op->index >= 0) {
329 // left <= right
330 var_desc* var = &method->vars[right_op->index];
331 if (var->min < left_op->min) {
332 var->min = left_op->min;
333 if (var->min > var->max) var->max = var->min;
334 }
335 if (vars != NULL) {
336 // left > right
337 var = &vars[right_op->index];
338 if (var->max >= left_op->max) {
339 var->max = left_op->max == ranges[tp_int].min
340 ? left_op->max : left_op->max-1;
341 if (var->min > var->max) var->min = var->max;
342 }
343 }
344 }
345 if (left_op->index >= 0) {
346 // left <= right
347 var_desc* var = &method->vars[left_op->index];
348 if (var->max > right_op->max) {
349 var->max = right_op->max;
350 if (var->min > var->max) var->min = var->max;
351 }
352 if (vars != NULL) {
353 // left > right
354 var = &vars[left_op->index];
355 if (var->min <= right_op->min) {
356 var->min = right_op->min == ranges[tp_int].max
357 ? right_op->min : right_op->min+1;
358 if (var->min > var->max) var->max = var->min;
359 }
360 }
361 }
362 stack_pointer = left_op;
363 break;
364 case if_icmpge:
365 if (right_op->index >= 0) {
366 // left < right
367 var_desc* var = &method->vars[right_op->index];
368 if (var->min <= left_op->min) {
369 var->min = left_op->min == ranges[tp_int].max
370 ? left_op->min : left_op->min+1;
371 if (var->min > var->max) var->max = var->min;
372 }
373 if (vars != NULL) {
374 // left >= right
375 var = &vars[right_op->index];
376 if (var->max > left_op->max) {
377 var->max = left_op->max;
378 if (var->min > var->max) var->min = var->max;
379 }
380 }
381 }
382 if (left_op->index >= 0) {
383 // left < right
384 var_desc* var = &method->vars[left_op->index];
385 if (var->max >= right_op->max) {
386 var->max = right_op->max == ranges[tp_int].min
387 ? right_op->max : right_op->max-1;
388 if (var->min > var->max) var->min = var->max;
389 }
390 if (vars != NULL) {
391 // left >= right
392 var = &vars[left_op->index];
393 if (var->min < right_op->min) {
394 var->min = right_op->min;
395 if (var->min > var->max) var->max = var->min;
396 }
397 }
398 }
399 stack_pointer = left_op;
400 break;
401 case if_acmpeq:
402 if (vars != NULL) {
403 if (right_op->index >= 0) {
404 vars[right_op->index].mask &= left_op->mask;
405 }
406 if (left_op->index >= 0) {
407 vars[left_op->index].mask &= right_op->mask;
408 }
409 }
410 stack_pointer = left_op;
411 break;
412 case if_acmpne:
413 if (right_op->index >= 0) {
414 method->vars[right_op->index].mask &= left_op->mask;
415 }
416 if (left_op->index >= 0) {
417 method->vars[left_op->index].mask &= right_op->mask;
418 }
419 stack_pointer = left_op;
420 break;
421 case ifnull:
422 if (right_op->index >= 0) {
423 method->vars[right_op->index].mask |= var_desc::vs_not_null;
424 if (vars != NULL) {
425 vars[right_op->index].mask &= ~var_desc::vs_not_null;
426 }
427 }
428 stack_pointer = right_op;
429 break;
430 case ifnonnull:
431 if (right_op->index >= 0) {
432 method->vars[right_op->index].mask &= ~var_desc::vs_not_null;
433 if (vars != NULL) {
434 vars[right_op->index].mask |= var_desc::vs_not_null;
435 }
436 }
437 stack_pointer = right_op;
438 break;
439 default:
440 stack_pointer = sp;
441 }
442 stack_top[1] = stack_pointer[-1];
443 stack_top[0] = stack_pointer[-2];
444 return sp;
445 }
446
447 /*
448 ** merge states after split
449 */
450
transfer(method_desc * method,vbm_operand * sp,byte,byte & prev_cop)451 vbm_operand* ctx_merge::transfer(method_desc* method, vbm_operand* sp,
452 byte, byte& prev_cop)
453 {
454 var_desc save_var;
455 method->in_monitor = come_from->in_monitor;
456 if (cmd == cmd_case_ctx && come_from->switch_var_index >= 0) {
457 // If branch is part of switch and switch expression is local variable,
458 // then we know value of this variable if this branch takes place
459 var_desc* var = &come_from->vars[come_from->switch_var_index];
460 save_var = *var;
461 var->max = var->min = var->mask = case_value;
462 }
463 var_desc* v0 = method->vars;
464 var_desc* v1 = come_from->vars;
465 if (prev_cop == goto_near || prev_cop == goto_w
466 || prev_cop == ret || prev_cop == athrow
467 || prev_cop == lookupswitch || prev_cop == tableswitch
468 || unsigned(prev_cop - ireturn) <= unsigned(vreturn-ireturn))
469 {
470 // Control can be passed to this point only by branch:
471 // no need to merge states
472 for (int i = method->n_vars; --i >= 0; v0++, v1++) {
473 if (v0->type == v1->type) {
474 v0->min = v1->min;
475 v0->max = v1->max;
476 v0->mask = v1->mask;
477 } else if (v1->type == tp_void) {
478 v0->type = tp_void;
479 }
480 }
481 sp = come_from->stack_pointer;
482 sp[-1] = come_from->stack_top[1];
483 sp[-2] = come_from->stack_top[0];
484 // all successive ctx_merge::transfer should merge variables properties
485 prev_cop = nop;
486 } else {
487 // merge states
488 for (int i = method->n_vars; --i >= 0; v0++, v1++) {
489 if (v0->type == v1->type) {
490 if (IS_INT_TYPE(v0->type)) {
491 if (v0->min > v1->min) v0->min = v1->min;
492 if (v0->max < v1->max) v0->max = v1->max;
493 v0->mask |= v1->mask;
494 #ifdef INT8_DEFINED
495 } else if (v0->type == tp_long) {
496 int8 min0 = LOAD_INT8(v0,min);
497 int8 max0 = LOAD_INT8(v0,max);
498 int8 mask0 = LOAD_INT8(v0,mask);
499 int8 min1 = LOAD_INT8(v1,min);
500 int8 max1 = LOAD_INT8(v1,max);
501 int8 mask1 = LOAD_INT8(v1,mask);
502 if (min0 > min1) {
503 STORE_INT8(v0, min, min1);
504 }
505 if (max0 < max1) {
506 STORE_INT8(v0, max, max1);
507 }
508 mask0 |= mask1;
509 STORE_INT8(v0, mask, mask0);
510 v0 += 1;
511 v1 += 1;
512 i -= 1;
513 assert(i >= 0);
514 #endif
515 } else {
516 if (v0->min > v1->min) v0->min = v1->min;
517 if (v0->max < v1->max) v0->max = v1->max;
518 v0->mask &= v1->mask;
519 }
520 } else if (v0->type != tp_void && v1->type == tp_void) {
521 if (IS_INT_TYPE(v0->type)) {
522 v0->min = ranges[tp_int].min;
523 v0->max = ranges[tp_int].max;
524 v0->mask = ALL_BITS;
525 } else if (v0->type == tp_long) {
526 v0[0].min = 0x80000000;
527 v0[0].max = 0x7fffffff;
528 v0[0].mask = 0xffffffff;
529 v0[1].min = 0x00000000;
530 v0[1].max = 0xffffffff;
531 v0[1].mask = 0xffffffff;
532 } else {
533 v0->min = 0;
534 v0->max = MAX_ARRAY_LENGTH;
535 }
536 }
537 }
538 assert(sp == come_from->stack_pointer);
539
540 if (IS_INT_TYPE(come_from->stack_top[1].type)) {
541 if (sp[-1].min > come_from->stack_top[1].min) {
542 sp[-1].min = come_from->stack_top[1].min;
543 }
544 if (sp[-1].max < come_from->stack_top[1].max) {
545 sp[-1].max = come_from->stack_top[1].max;
546 }
547 sp[-1].mask |= come_from->stack_top[1].mask;
548 #ifdef INT8_DEFINED
549 } else if (come_from->stack_top[1].type == tp_long) {
550 int8 min0 = LOAD_INT8(sp-2,min);
551 int8 max0 = LOAD_INT8(sp-2,max);
552 int8 mask0 = LOAD_INT8(sp-2,mask);
553 int8 min1 = LOAD_INT8(come_from->stack_top,min);
554 int8 max1 = LOAD_INT8(come_from->stack_top,max);
555 int8 mask1 = LOAD_INT8(come_from->stack_top,mask);
556 if (min0 > min1) {
557 STORE_INT8(sp-2, min, min1);
558 }
559 if (max0 < max1) {
560 STORE_INT8(sp-2, max, max1);
561 }
562 mask0 |= mask1;
563 STORE_INT8(sp-2, mask, mask0);
564 #endif
565 } else {
566 //raphy
567 sp[-1].min = 0;
568 sp[-1].max = 0;
569 come_from->stack_top[1].min = 0;
570 come_from->stack_top[1].max = 0;
571 //raphy end
572 if (sp[-1].min > come_from->stack_top[1].min) {
573 sp[-1].min = come_from->stack_top[1].min;
574 }
575 if (sp[-1].max < come_from->stack_top[1].max) {
576 sp[-1].max = come_from->stack_top[1].max;
577 }
578 sp[-1].mask &= come_from->stack_top[1].mask;
579 }
580 }
581 if (--come_from->n_branches == 0) {
582 delete[] come_from->vars;
583 } else if (cmd == cmd_case_ctx && come_from->switch_var_index >= 0) {
584 // restore state of switch expression varaible,
585 // because it can be used in other branches
586 come_from->vars[come_from->switch_var_index] = save_var;
587 }
588 return sp;
589 }
590
transfer(method_desc * method,vbm_operand * sp,byte,byte &)591 vbm_operand* ctx_entry_point::transfer(method_desc* method, vbm_operand* sp,
592 byte, byte&)
593 {
594 #if 1
595 //
596 // As far as state of variable is not followed correctly in case of
597 // subroutine execution or catching exception, the obvious approach is
598 // to reset state of all local variables. But in this case we will loose
599 // useful information, so I decide to keep variables state,
600 // hoping that it will not cause confusing Jlint messages.
601 //
602 var_desc* var = method->vars;
603 for (int i = method->n_vars; --i >= 0; var++) {
604 int type = var->type;
605 if (IS_INT_TYPE(type)) {
606 var->min = ranges[type].min;
607 var->max = ranges[type].max;
608 var->mask = var->min | var->max;
609 } else if (type == tp_long) {
610 var->min = 0x80000000;
611 var->max = 0x7fffffff;
612 var->mask = 0xffffffff;
613 var += 1;
614 var->min = 0x00000000;
615 var->max = 0xffffffff;
616 var->mask = 0xffffffff;
617 i -= 1;
618 assert(i >= 0);
619 } else {
620 var->min = 0;
621 var->max = MAX_ARRAY_LENGTH;
622 var->mask = var_desc::vs_unknown;
623 }
624 }
625 #endif
626 sp->type = tp_object;
627 sp->mask = var_desc::vs_not_null;
628 sp->min = 0;
629 sp->max = MAX_ARRAY_LENGTH;
630 return sp+1; // exception object is pushed on stack
631 }
632
633
transfer(method_desc * method,vbm_operand * sp,byte,byte &)634 vbm_operand* ctx_reset::transfer(method_desc* method, vbm_operand* sp,
635 byte, byte&)
636 {
637 var_desc* var = method->vars;
638 for (int n = method->n_vars, i = 0; i < n; i++, var++) {
639 //
640 // Reset vaules of local variables which were modified in region of
641 // code between backward jump label and backward jump intruction
642 //
643 if (method->var_store_count[i] != var_store_count[i]) {
644 int type = var->type;
645 if (IS_INT_TYPE(type)) {
646 var->min = ranges[type].min;
647 var->max = ranges[type].max;
648 var->mask = var->min | var->max;
649 } else if (type == tp_long) {
650 var->min = 0x80000000;
651 var->max = 0x7fffffff;
652 var->mask = 0xffffffff;
653 var += 1;
654 var->min = 0x00000000;
655 var->max = 0xffffffff;
656 var->mask = 0xffffffff;
657 i += 1;
658 assert(i < n);
659 } else {
660 var->mask = var_desc::vs_unknown;
661 var->min = 0;
662 var->max = MAX_ARRAY_LENGTH;
663 }
664 }
665 }
666 delete[] var_store_count;
667 return sp;
668 }
669