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