CACAO
escape.cpp
Go to the documentation of this file.
1 /* src/vm/jit/optimizing/escape.cpp
2 
3  Copyright (C) 2008-2013
4  CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 
26 #include "config.h"
27 
28 #include "mm/dumpmemory.hpp"
29 
30 #include "vm/class.hpp"
31 #include "vm/classcache.hpp"
32 
33 #include "vm/field.hpp"
34 #include "vm/jit/builtin.hpp"
35 #include "vm/jit/jit.hpp"
36 #include "vm/jit/show.hpp"
38 
39 #include <stdarg.h>
40 
41 #if defined(ENABLE_ESCAPE_REASON)
42 #define ENABLE_REASON
43 #endif
44 
45 #if defined(ENABLE_REASON)
46 #define I2(why, tov, es) escape_analysis_record_reason(e, why, iptr, tov, es);
47 #else
48 #define I2(why, tov, es)
49 #endif
50 #define I(why, to, from) I2(why, instruction_ ## to (iptr), escape_analysis_get_state(e, instruction_ ## from (iptr)))
51 #define E2(why, var) I2(why, var, ESCAPE_GLOBAL)
52 #define E(why, which) E2(why, instruction_ ## which (iptr))
53 
54 typedef enum {
55  RED = 31,
63 } color_t;
64 
65 #define ENABLE_COLOR
66 
67 static void color_start(color_t color) {
68 #if defined(ENABLE_COLOR)
69  if (RED <= color && color < COLOR_END) {
70  printf("\033[%dm", color);
71  }
72 #endif
73 }
74 
75 static void color_end() {
76 #if defined(ENABLE_COLOR)
77  printf("\033[m");
78  fflush(stdout);
79 #endif
80 }
81 
82 static void color_printf(color_t color, const char *fmt, ...) {
83  va_list ap;
84  color_start(color);
85  va_start(ap, fmt);
86  vprintf(fmt, ap);
87  va_end(ap);
88  color_end();
89 }
90 
91 
92 /*** escape_state *************************************************************/
93 
94 const char *escape_state_to_string(escape_state_t escape_state) {
95 # define str(x) case x: return #x;
96  switch (escape_state) {
102  default: return "???";
103  }
104 # undef str
105 }
106 
107 /*** instruction **************************************************************/
108 
109 static inline s2 instruction_get_opcode(const instruction *iptr) {
110  if (iptr->opc == ICMD_BUILTIN) {
111  return iptr->sx.s23.s3.bte->opcode;
112  } else {
113  return iptr->opc;
114  }
115 }
116 
117 static inline bool instruction_is_unresolved(const instruction *iptr) {
118  return iptr->flags.bits & INS_FLAG_UNRESOLVED;
119 }
120 
121 static inline s4 instruction_field_type(const instruction *iptr) {
122  if (instruction_is_unresolved(iptr)) {
123  return iptr->sx.s23.s3.uf->fieldref->parseddesc.fd->type;
124  } else {
125  return iptr->sx.s23.s3.fmiref->p.field->type;
126  }
127 }
128 
129 static inline s4 instruction_s1(const instruction *iptr) {
130  return iptr->s1.varindex;
131 }
132 
133 static inline s4 instruction_s2(const instruction *iptr) {
134  return iptr->sx.s23.s2.varindex;
135 }
136 
137 static inline s4 instruction_s3(const instruction *iptr) {
138  return iptr->sx.s23.s3.varindex;
139 }
140 
141 static inline s4 instruction_dst(const instruction *iptr) {
142  return iptr->dst.varindex;
143 }
144 
145 static inline s4 instruction_arg(const instruction *iptr, int arg) {
146  return iptr->sx.s23.s2.args[arg];
147 }
148 
149 static inline bool instruction_is_class_constant(const instruction *iptr) {
150  return iptr->flags.bits & INS_FLAG_CLASS;
151 }
152 
153 static inline classinfo *instruction_classinfo(const instruction *iptr) {
154  return iptr->sx.val.c.cls;
155 }
156 
158  if (instruction_is_unresolved(iptr)) {
159  return NULL;
160  } else {
161  return iptr->sx.s23.s3.fmiref->p.method;
162  }
163 }
164 
165 static inline int instruction_dst_type(const instruction *iptr, jitdata *jd) {
166  return VAROP(iptr->dst)->type;
167 }
168 
169 static inline int instruction_return_type(const instruction *iptr) {
170  return instruction_call_site(iptr)->returntype.type;
171 }
172 
173 static inline s4 instruction_arg_type(const instruction *iptr, int arg) {
174  methoddesc *md = instruction_call_site(iptr);
175  assert(0 <= arg && arg < md->paramcount);
176  return md->paramtypes[arg].type;
177 }
178 
179 static inline int instruction_arg_count(const instruction *iptr) {
180  return instruction_call_site(iptr)->paramcount;
181 }
182 
183 /*** instruction_list ********************************************************/
184 
185 typedef struct instruction_list_item {
189 
190 typedef struct {
193 
195  list->first = NULL;
196 }
197 
200  item->instr = instr;
201  item->next = list->first;
202  list->first = item;
203 }
204 
205 #define FOR_EACH_INSTRUCTION_LIST(list, it) \
206  for ((it) = (list)->first; (it) != NULL; (it) = (it)->next)
207 
208 /*** escape_analysis *********************************************************/
209 
210 struct var_extra;
211 
212 typedef struct {
214 
219 
220  struct var_extra **var;
221 
222  unsigned adr_args_count;
223 
224  bool verbose;
225 
227 
228 /*** dependency_list_item ****************************************************/
229 
230 typedef struct dependency_list_item {
234 
236 
237  instruction *store = item->store;
238  Utf8String storen;
239  Utf8String loadn;
240 
241  if (load->opc == ICMD_AALOAD) {
242 
243  if (store->opc != ICMD_AASTORE) {
244  return false;
245  }
246 
247  return true;
248 
249  } else {
250 
251  if (store->opc != ICMD_PUTFIELD) {
252  return false;
253  }
254 
255  if (
256  instruction_is_unresolved(store) !=
258  ) {
259  return false;
260  }
261 
262  if (instruction_is_unresolved(store)) {
263  storen = store->sx.s23.s3.uf->fieldref->name;
264  loadn = load->sx.s23.s3.uf->fieldref->name;
265  } else {
266  storen = store->sx.s23.s3.fmiref->name;
267  loadn = load->sx.s23.s3.fmiref->name;
268  }
269 
270  return storen == loadn;
271  }
272 }
273 
274 /* TODO rename */
276  switch (item->store->opc) {
277  case ICMD_AASTORE:
278  return instruction_s3(item->store);
279  case ICMD_PUTFIELD:
280  return instruction_s2(item->store);
281  default:
282  assert(0);
283  return 0;
284  }
285 }
286 
287 /*** dependency_list *********************************************************/
288 
289 typedef struct {
293 
295  dl->first = NULL;
296  dl->last = NULL;
297 }
298 
301 
302  item->store = store;
303  item->next = NULL;
304 
305  if (dl->first == NULL) {
306  dl->first = item;
307  dl->last = item;
308  } else {
309  dl->last->next = item;
310  dl->last = item;
311  }
312 }
313 
315 
316  if (other == NULL) {
317  return;
318  }
319 
320  if (dl->first == NULL) {
321  *dl = *other;
322  } else {
323  dl->last->next = other->first;
324  dl->last = other->last;
325  }
326 
327  other->first = NULL;
328  other->last = NULL;
329 
330 }
331 
332 #define FOR_EACH_DEPENDENCY_LIST(dl, it) \
333  for ((it) = (dl)->first; (it) != NULL; (it) = (it)->next)
334 
335 /*** var_extra ***************************************************************/
336 
337 #if defined(ENABLE_REASON)
338 typedef struct reason {
339  const char *why;
340  instruction *iptr;
341  struct reason *next;
342 } reason_t;
343 #endif
344 
345 typedef struct var_extra {
350  unsigned contains_arg:1;
351  unsigned contains_only_args:1;
352  /*signed adr_arg_num:30;*/
353 #if defined(ENABLE_REASON)
354  reason_t *reasons;
355 #endif
356 } var_extra_t;
357 
358 static void var_extra_init(var_extra_t *ve) {
359  ve->allocation = NULL;
361  ve->representant = -1;
362  ve->dependency_list = NULL;
363  ve->contains_arg = false;
364  ve->contains_only_args = false;
365  /*ve->adr_arg_num = -1;*/
366 #if defined(ENABLE_REASON)
367  ve->reasons = NULL;
368 #endif
369 }
370 
372  return e->var[var];
373 }
374 
376  var_extra_t *ve;
377 
378  assert(0 <= var && var <= e->jd->vartop);
379 
380  ve = var_extra_get_no_alloc(e, var);
381 
382  if (ve == NULL) {
383  ve = DNEW(var_extra_t);
384  var_extra_init(ve);
385  e->var[var] = ve;
386  }
387 
388  return ve;
389 }
390 
392  var_extra_t *ve;
393 #if !defined(NDEBUG)
394  int ctr = 0;
395 #endif
396 
397  ve = var_extra_get(e, var);
398 
399  while (ve->representant != -1) {
400  assert(ctr++ < 10000);
401  var = ve->representant;
402  ve = var_extra_get_no_alloc(e, var);
403  assert(ve);
404  }
405 
406  return var;
407 }
408 
410  var_extra_t *ve;
411 
412  var = var_extra_get_representant(e, var);
413  ve = var_extra_get(e, var);
414 
415  return ve->escape_state;
416 }
417 
419  var_extra_t *ve;
420 
421  var = var_extra_get_representant(e, var);
422  ve = var_extra_get(e, var);
423 
424  ve->escape_state = escape_state;
425 }
426 
428  var_extra_t *ve;
429 
430  var = var_extra_get_representant(e, var);
431  ve = var_extra_get(e, var);
432 
433  if (ve->dependency_list == NULL) {
436  }
437 
438  return ve->dependency_list;
439 }
440 
441 /*** escape_analysis *********************************************************/
442 
444  e->jd = jd;
445 
448 
451 
454 
457 
458  e->var = DMNEW(var_extra_t *, jd->vartop);
459  MZERO(e->var, var_extra_t *, jd->vartop);
460 
461  e->adr_args_count = 0;
462 
463  e->verbose = 1;
464  e->verbose = strcmp(jd->m->name.begin(), "<init>") == 0;
465  e->verbose = getenv("EV") != NULL;
466 }
467 
468 #if defined(ENABLE_REASON)
469 static void escape_analysis_record_reason(escape_analysis_t *e, const char *why, instruction *iptr, s4 var, escape_state_t es) {
470  var_extra_t *ve;
471  reason_t *re;
472  if (es == ESCAPE_GLOBAL || es == ESCAPE_METHOD_RETURN) {
473  var = var_extra_get_representant(e, var);
474  ve = var_extra_get(e, var);
475  re = NEW(reason_t);
476  re->why = why;
477  re->iptr= iptr;
478  re->next = ve->reasons;
479  ve->reasons = re;
480  if (e->verbose) {
481  printf("%d escapes because %s\n", var, why);
482  }
483  }
484 }
485 #endif
486 
488  var_extra_get(e, var)->allocation = iptr;
489 }
490 
492  var_extra_t *ve = var_extra_get_no_alloc(e, var);
493 
494  assert(ve != NULL);
495  assert(ve->allocation != NULL);
496 
497  return ve->allocation;
498 }
499 
501  var = var_extra_get_representant(e, var);
502  var_extra_get(e, var)->contains_arg = true;
503 }
504 
506  var = var_extra_get_representant(e, var);
507  return var_extra_get(e, var)->contains_arg;
508 }
509 
511  var = var_extra_get_representant(e, var);
512  var_extra_get(e, var)->contains_only_args = true;
513 }
514 
516  var = var_extra_get_representant(e, var);
517  return var_extra_get(e, var)->contains_only_args;
518 }
519 
520 /*
521 static void escape_analysis_set_adr_arg_num(escape_analysis_t *e, s4 var, s4 num) {
522  var_extra_get(e, var)->adr_arg_num = num;
523 }
524 
525 static s4 escape_analysis_get_adr_arg_num(escape_analysis_t *e, s4 var) {
526  return var_extra_get(e, var)->adr_arg_num;
527 }
528 */
529 
530 static bool escape_analysis_in_same_set(escape_analysis_t *e, s4 var1, s4 var2) {
531  return var_extra_get_representant(e, var1) == var_extra_get_representant(e, var2);
532 }
533 
535 
536  var_extra_t *ve;
538 
539  var = var_extra_get_representant(e, var);
540  ve = var_extra_get(e, var);
541 
542  if (ve->escape_state < escape_state) {
543  if (e->verbose) {
544  printf(
545  "escape state of %d %s => %s\n",
546  var,
548  escape_state_to_string(escape_state)
549  );
550  }
551  ve->escape_state = escape_state;
552  if (ve->dependency_list != NULL) {
554  if (e->verbose) {
555  printf("propagating to %s@%d\n", icmd_table[it->store->opc].name, it->store->line);
556  }
558  e,
560  escape_state
561  );
562  {
563  instruction *iptr = NULL;
564  I2("propagated by dependency", dependency_list_item_get_dependency(it), escape_state);
565  }
566  }
567  }
568  }
569 }
570 
572  return var_extra_get_escape_state(e, var);
573 }
574 
577 
578  if (iptr == NULL) {
579  return NULL;
580  }
581 
582  if (! instruction_is_class_constant(iptr)) {
583  return NULL;
584  }
585 
586  if (instruction_dst(iptr) != var) {
587  return NULL;
588  }
589 
590  if (instruction_is_unresolved(iptr)) {
591  return NULL;
592  }
593 
594  return instruction_classinfo(iptr);
595 }
596 
597 static void escape_analysis_merge(escape_analysis_t *e, s4 var1, s4 var2) {
598 
599  var_extra_t *ve1, *ve2;
601  bool has_become_arg;
602 
603  var1 = var_extra_get_representant(e, var1);
604  var2 = var_extra_get_representant(e, var2);
605 
606  /* Don't merge the same escape sets. */
607 
608  if (var1 == var2) {
609  return;
610  }
611 
612  if (e->verbose) printf("Merging (%d,%d)\n", var1, var2);
613 
614  ve1 = var_extra_get(e, var1);
615  ve2 = var_extra_get(e, var2);
616 
617  /* Adjust escape state to maximal escape state. */
618 
621 
622  /* Representant of var1 becomes the representant of var2. */
623 
624  ve2->representant = var1;
625 
626  /* Adjust is_arg to logical or. */
627 
628  has_become_arg = ve1->contains_arg != ve2->contains_arg;
629  ve1->contains_arg = ve1->contains_arg || ve2->contains_arg;
630 
631  if (e->verbose && has_become_arg) printf("(%d,%d) has become arg.\n", var1, var2);
632 
633  /* Merge list of dependencies. */
634 
635  if (ve1->dependency_list == NULL) {
636  ve1->dependency_list = ve2->dependency_list;
637  } else {
639  }
640 
641  /* If one of the merged values is an argument but the other not,
642  all dependencies of the newly created value escape globally. */
643 
644  if (has_become_arg && ve1->dependency_list != NULL) {
647  e,
650  );
651  {
652  instruction *iptr = NULL;
653  E2("has become arg", dependency_list_item_get_dependency(itd));
654  }
655  }
656  }
657 
658  /* Adjust contains_only_args to logical and. */
659 
661 
662  /* Adjust address argument number contained in this var. */
663 
664  /*
665  if (ve1->adr_arg_num != ve2->adr_arg_num) {
666  ve1->adr_arg_num = -1;
667  }
668  */
669 #if defined(ENABLE_REASON)
670  if (ve1->reasons) {
671  reason_t *re = ve1->reasons;
672  while (re->next != NULL) {
673  re = re->next;
674  }
675  re->next = ve2->reasons;
676  } else {
677  ve1->reasons = ve2->reasons;
678  }
679 #endif
680 }
681 
683  s4 obj = instruction_s1(store);
685 
686  assert(store->opc == ICMD_PUTFIELD || store->opc == ICMD_AASTORE);
687 
688  dependency_list_add(dl, store);
689 
690  if (e->verbose) {
691  printf("dependency_list_add: %d.dependency_list.add( { ", obj);
692  show_icmd(e->jd, store, 0, 3);
693  printf(" } )\n");
694  }
695 }
696 
698  jitdata *jd = e->jd;
699  classinfo *c;
700  s4 count;
701  u1 *paramescape;
702  unsigned i;
703  instruction **iarg;
704  methodinfo *mi;
705  escape_state_t es;
706  const char *why;
707 
708  if (e->verbose) {
709  color_start(CYAN);
710  printf("%d: ", iptr->line);
711  show_icmd(e->jd, iptr, 0, 3);
712  color_end();
713  printf("\n");
714  }
715 
716  switch (instruction_get_opcode(iptr)) {
717  case ICMD_ACONST:
718 
721 
722  break;
723 
724  case ICMD_NEW:
726 
728 
729  if (c == NULL) {
731  E("unresolved class", dst)
732  } else if (c->finalizer != NULL) {
734  E("finalizer", dst)
735  } else {
737  }
738 
740 
741  break;
742 
743  case ICMD_MONITORENTER:
744  case ICMD_MONITOREXIT:
745 
746  instruction_list_add(e->monitors, iptr);
747 
748  break;
749 
750  case ICMD_NEWARRAY:
751  case ICMD_ANEWARRAY:
752 
756  E("untracked array", dst)
757  break;
758 
759  case ICMD_PUTSTATIC:
760  if (instruction_field_type(iptr) == TYPE_ADR) {
762  E("putstatic", s1)
763  }
764  break;
765 
766  case ICMD_PUTFIELD:
767  if (instruction_field_type(iptr) == TYPE_ADR) {
770  /* If s1 is currently not an argument, but can contain one later because
771  of a phi function, the merge function takes care to make all
772  dependencies escape globally. */
773  E("putfield into argument", s2)
774  } else {
775  I("putfield inherit", s2, s1);
778  }
779  }
780  break;
781 
782  case ICMD_AASTORE:
784  if (e->verbose) printf("Contains argument.\n");
786  E("aastore into argument", s3)
787  } else {
788  if (e->verbose) printf("Contains no argument.\n");
789  I("aastore", s3, s1)
792  }
793  break;
794 
795  case ICMD_GETSTATIC:
796  if (instruction_field_type(iptr) == TYPE_ADR) {
798  E("loaded from static var", dst)
800  }
801  break;
802 
803  case ICMD_GETFIELD:
804  if (instruction_field_type(iptr) == TYPE_ADR) {
805 
807  /* Fields loaded from arguments escape globally.
808  x = arg.foo;
809  x.bar = y;
810  => y escapes globally. */
812  E("loaded from arg", dst)
813  } else {
815  }
816 
818 
820  }
821  break;
822 
823  case ICMD_ARRAYLENGTH:
825  break;
826 
827  case ICMD_AALOAD:
828 
830  /* If store into argument, escapes globally. See ICMD_GETFIELD. */
832  E("aaload from argument", dst)
833  } else {
835  }
836 
838 
840  break;
841 
842  case ICMD_IF_ACMPEQ:
843  case ICMD_IF_ACMPNE:
846  break;
847 
848  case ICMD_IFNULL:
849  case ICMD_IFNONNULL:
851  break;
852 
853  case ICMD_CHECKNULL:
856  break;
857 
858  case ICMD_CHECKCAST:
862  break;
863 
864  case ICMD_INSTANCEOF:
866  break;
867 
868  case ICMD_INVOKESPECIAL:
869  case ICMD_INVOKEVIRTUAL:
871  case ICMD_INVOKESTATIC:
872  count = instruction_arg_count(iptr);
873  mi = instruction_local_methodinfo(iptr);
874  paramescape = NULL;
875  why = "???";
876 
877  if (mi != NULL) {
878  /* If the method could be resolved, it already is. */
879  paramescape = mi->paramescape;
880 
881  if (e->verbose) {
882  if (paramescape) {
883  printf("Paramescape for callee available.\n");
884  }
885  }
886 
887  if (paramescape) why = "Available param escape";
888 
889  if (paramescape == NULL) {
890  if (e->verbose) {
891  printf("BC escape analyzing callee.\n");
892  }
893  why = "BC param escape";
895  paramescape = mi->paramescape;
896  }
897  } else {
898  if (e->verbose) {
899  printf("Unresolved callee.\n");
900  }
901  why = "Unresolved callee";
902  }
903 
904  if (iptr->opc == ICMD_INVOKEVIRTUAL || iptr->opc == ICMD_INVOKEINTERFACE) {
905  if (mi != NULL && !escape_is_monomorphic(e->jd->m, mi)) {
906  if (e->verbose) {
907  printf("Not monomorphic.\n");
908  }
909  why = "Polymorphic";
910  paramescape = NULL;
911  }
912  }
913 
914  /* Set the escape state of the return value.
915  This is: global if we down have information of the callee, or the callee
916  supplied escape state. */
917 
918  if (instruction_return_type(iptr) == TYPE_ADR) {
919  if (paramescape == NULL) {
921  E(why, dst);
922  } else {
923  es = escape_state_from_u1(paramescape[-1]);
924  I2(why, instruction_dst(iptr), es)
926  }
928  }
929 
930  for (i = 0; i < count; ++i) {
931  if (instruction_arg_type(iptr, i) == TYPE_ADR) {
932 
933  if (paramescape == NULL) {
935  e,
936  instruction_arg(iptr, i),
938  );
939  E2(why, instruction_arg(iptr, i));
940  } else if (escape_state_from_u1(*paramescape) <= ESCAPE_METHOD) {
941  es = escape_state_from_u1(*paramescape);
942 
943  if (es < ESCAPE_METHOD) {
944  es = ESCAPE_METHOD;
945  }
946 
947  I2(why, instruction_arg(iptr, i), es);
949 
950  if (*paramescape & 0x80) {
951  /* Parameter can be returned from method.
952  This creates an alias to the retur value.
953  If the return value escapes, the ES of the parameter needs
954  to be adjusted. */
956  I2("return alias", instruction_arg(iptr, i), instruction_dst(iptr));
957  }
958  } else {
960  E2(why, instruction_arg(iptr, i));
961  }
962 
963  if (paramescape != NULL) {
964  ++paramescape;
965  }
966  }
967  }
968 
969  break;
970 
971  case ICMD_ATHROW:
973  E("throw", s1)
974  break;
975 
976  case ICMD_ARETURN:
977  /* If we return only arguments, the return value escapes only the method.
978  ESCAPE_METHOD for now, and check later, if a different value than an
979  argument is possibly returned. */
981  E("return", s1)
982  instruction_list_add(e->returns, iptr);
983  break;
984 
985  case ICMD_ALOAD:
986  case ICMD_ASTORE:
987  case ICMD_MOVE:
988  case ICMD_COPY:
989  if (instruction_dst_type(iptr, jd) == TYPE_ADR) {
992  }
993  break;
994 
995  case ICMD_PHI:
996  for (
997  iarg = iptr->sx.s23.s2.iargs;
998  iarg != iptr->sx.s23.s2.iargs + iptr->s1.argcount;
999  ++iarg
1000  ) {
1002  }
1003  break;
1004 
1005  case ICMD_GETEXCEPTION:
1007  break;
1008  }
1009 }
1010 
1012  basicblock *bptr;
1013  instruction *iptr;
1014 
1015  FOR_EACH_BASICBLOCK(e->jd, bptr) {
1016 
1017  if (e->verbose) {
1018  color_printf(CYAN, "=== BB %d ===\n", bptr->nr);
1019  }
1020 
1021  for (iptr = bptr->phis; iptr != bptr->phis + bptr->phicount; ++iptr) {
1023  }
1024 
1025  FOR_EACH_INSTRUCTION(bptr, iptr) {
1027  }
1028 
1029  }
1030 }
1031 
1034  instruction *iptr;
1035 
1036  if (e->verbose) printf("Post processing returns:\n");
1037 
1039  iptr = iti->instr;
1040 
1043  E("return of not argument", s1)
1044  }
1045  }
1046 }
1047 
1051  instruction *iptr;
1052  dependency_list_t *dl;
1053 
1054  if (e->verbose) printf("Post processing getfields:\n");
1055 
1057 
1058  iptr = iti->instr;
1059 
1060  /* Get the object the field/element is loaded from. */
1061 
1063 
1064  /* Adjust escape state of all objects in the dependency list,
1065  referenced via the field of this getfield/arraystore. */
1066 
1067  if (dl != NULL) {
1068  FOR_EACH_DEPENDENCY_LIST(dl, itd) {
1069  if (dependency_list_item_compare(itd, iptr)) {
1070 
1071  /* Fields match. Adjust escape state. */
1072 
1074  e,
1077  );
1078  I2("post process getfield", dependency_list_item_get_dependency(itd), escape_analysis_get_state(e, instruction_dst(iptr)));
1079  }
1080  }
1081  }
1082 
1083  }
1084 }
1085 
1088  instruction *iptr;
1089 
1091  iptr = iti->instr;
1092 
1093  /* TODO if argument does not escape, mark. */
1095  if (e->verbose) {
1096  printf("Monitor on thread local object!\n");
1097  }
1098  }
1099  }
1100 }
1101 
1104  instruction *iptr;
1105  escape_state_t es;
1107  iptr = iti->instr;
1109 
1110 #if defined(ENABLE_REASON)
1111  if (instruction_get_opcode(iptr) == ICMD_NEW) {
1112  var_extra_t *ve;
1113  iptr->sx.s23.s3.bte = builtintable_get_internal(BUILTIN_escape_reason_new);
1115  iptr->escape_reasons = ve->reasons;
1116  if (es < ESCAPE_METHOD_RETURN) {
1117  assert(!ve->reasons);
1118  reason_t *r = NEW(reason_t);
1119  r->why = "No escape\n";
1120  r->iptr = NULL;
1121  r->next = NULL;
1122  iptr->escape_reasons = r;
1123  } else {
1124  assert(iptr->escape_reasons);
1125  }
1126  }
1127 #endif
1128 
1129 /*
1130  if (instruction_get_opcode(iptr) == ICMD_NEW) {
1131  es = escape_analysis_get_state(e, instruction_dst(iptr));
1132  if (es < ESCAPE_METHOD_RETURN) {
1133  iptr->sx.s23.s3.bte = builtintable_get_internal(BUILTIN_tlh_new);
1134  e->jd->code->flags |= CODE_FLAG_TLH;
1135  }
1136  }
1137 */
1138  }
1139 }
1140 
1142  s4 p;
1143  s4 t;
1144  s4 l;
1145  s4 varindex;
1146  methoddesc *md;
1147 
1148  md = e->jd->m->parseddesc;
1149 
1150  for (p = 0, l = 0; p < md->paramcount; ++p) {
1151  t = md->paramtypes[p].type;
1152  varindex = e->jd->local_map[l * 5 + t];
1153  if (t == TYPE_ADR) {
1154  if (varindex != jitdata::UNUSED) {
1158  /*escape_analysis_set_adr_arg_num(e, varindex, e->adr_args_count);*/
1159  }
1160  e->adr_args_count += 1;
1161  }
1162  l += IS_2_WORD_TYPE(t) ? 2 : 1;
1163  }
1164 }
1165 
1167  s4 p;
1168  s4 t;
1169  s4 l;
1170  s4 varindex;
1171  methoddesc *md;
1172  u1 *paramescape;
1174  instruction *iptr;
1175  escape_state_t es, re;
1176  int ret_val_is_adr;
1177 
1178  md = e->jd->m->parseddesc;
1179 
1180  ret_val_is_adr = (md->returntype.type == TYPE_ADR) ? 1 : 0;
1181 
1182  paramescape = MNEW(u1, e->adr_args_count + ret_val_is_adr);
1183 
1184  e->jd->m->paramescape = paramescape + ret_val_is_adr;
1185 
1186  for (p = 0, l = 0; p < md->paramcount; ++p) {
1187  t = md->paramtypes[p].type;
1188  varindex = e->jd->local_map[l * 5 + t];
1189  if (t == TYPE_ADR) {
1190  if (varindex == jitdata::UNUSED) {
1191  *paramescape = (u1)ESCAPE_NONE;
1192  } else {
1193  es = escape_analysis_get_state(e, varindex);
1194 
1195  if (es == ESCAPE_METHOD_RETURN) {
1196  *paramescape = escape_state_to_u1(ESCAPE_METHOD) | 0x80;
1197  if (e->verbose) {
1198  printf("non-escaping adr parameter returned: %d\n", p);
1199  }
1200  } else {
1201  *paramescape = escape_state_to_u1(es);
1202  }
1203 
1204  }
1205  paramescape += 1;
1206  }
1207  l += IS_2_WORD_TYPE(t) ? 2 : 1;
1208  }
1209 
1210  if (ret_val_is_adr) {
1211  /* Calculate escape state of return value as maximum escape state of all
1212  values returned. */
1213 
1214  re = ESCAPE_NONE;
1215 
1217  iptr = iti->instr;
1219 
1220  if (es > re) {
1221  re = es;
1222  }
1223  }
1224 
1225  e->jd->m->paramescape[-1] = escape_state_to_u1(re);
1226  }
1227 }
1228 
1229 #if defined(ENABLE_REASON)
1230 void print_escape_reasons() {
1231  reason_t *re = THREADOBJECT->escape_reasons;
1232 
1233  fprintf(stderr, "DYN_REASON");
1234 
1235  for (; re; re = re->next) {
1236  fprintf(stderr,":%s", re->why);
1237  }
1238 
1239  fprintf(stderr, "\n");
1240 }
1241 
1242 void set_escape_reasons(void *vp) {
1243  THREADOBJECT->escape_reasons = vp;
1244 }
1245 #endif
1246 
1249  var_extra_t *ve;
1250  instruction *iptr;
1251 
1253  iptr = iti->instr;
1255  show_icmd(e->jd, iptr-1, 0, 3);
1256  printf("\n");
1257  show_icmd(e->jd, iptr, 0, 3);
1258  printf("\n");
1259  printf(
1260  "%s@%d: --%s-- %d\n\n",
1261  icmd_table[iptr->opc].name,
1262  iptr->line,
1264  ve->representant
1265  );
1266 #if defined(ENABLE_REASON)
1267  {
1268  reason_t *re;
1269  for (re = ve->reasons; re; re = re->next) {
1270  printf("ESCAPE_REASON: %s\n", re->why);
1271  }
1272  }
1273 #endif
1274  }
1275 }
1276 
1279 
1280  jd->m->flags |= ACC_METHOD_EA;
1281 
1282  e = DNEW(escape_analysis_t);
1283  escape_analysis_init(e, jd);
1284 
1285  if (e->verbose)
1286  color_printf(RED, "\n\n==== %s/%s ====\n\n", e->jd->m->clazz->name.begin(), e->jd->m->name.begin());
1287 
1292 
1294  if (e->verbose) escape_analysis_display(e);
1295 
1296  if (e->verbose) {
1297  int i, j, r;
1298  for (i = 0; i < jd->vartop; ++i) {
1299  r = var_extra_get_representant(e, i);
1300  if (i == r) {
1301  printf("EES of %d: ", i);
1302  for (j = 0; j < jd->vartop; ++j) {
1303  if (var_extra_get_representant(e, j) == r) {
1304  printf("%d, ", j);
1305  }
1306  }
1307  printf("\n");
1308  }
1309  }
1310  printf("\n");
1311  }
1312 
1315 
1316  jd->m->flags &= ~ACC_METHOD_EA;
1317 }
1318 
1320 }
1321 
1322 /*** monomorphic *************************************************************/
1323 
1325 
1326  /* Non-speculative case */
1327 
1328  if (callee->flags & (ACC_STATIC | ACC_FINAL | ACC_PRIVATE)) {
1329  return true;
1330  }
1331 
1332  if (
1335  ) {
1336 
1337  /* Mark that we have used the information about monomorphy. */
1338 
1339  callee->flags |= ACC_METHOD_MONOMORPHY_USED;
1340 
1341  /* We assume the callee is monomorphic. */
1342 
1343  method_add_assumption_monomorphic(caller, callee);
1344 
1345  return true;
1346  }
1347 
1348  return false;
1349 }
1350 
1351 
1352 /*
1353  * These are local overrides for various environment variables in Emacs.
1354  * Please do not remove this and leave it at the end of the file, where
1355  * Emacs will automagically detect them.
1356  * ---------------------------------------------------------------------
1357  * Local variables:
1358  * mode: c++
1359  * indent-tabs-mode: t
1360  * c-basic-offset: 4
1361  * tab-width: 4
1362  * End:
1363  * vim:noexpandtab:sw=4:ts=4:
1364  */
bool dependency_list_item_compare(const dependency_list_item_t *item, const instruction *load)
Definition: escape.cpp:235
val_operand_t val
static s4 instruction_arg_type(const instruction *iptr, int arg)
Definition: escape.cpp:173
Utf8String name
Definition: method.hpp:71
static void escape_analysis_display(escape_analysis_t *e)
Definition: escape.cpp:1247
Definition: escape.cpp:60
struct dependency_list_item * next
Definition: escape.cpp:232
instruction * store
Definition: escape.cpp:231
Definition: jit.hpp:126
#define NEW(type)
Definition: memory.hpp:93
instruction * allocation
Definition: escape.cpp:346
static void var_extra_set_escape_state(escape_analysis_t *e, s4 var, escape_state_t escape_state)
Definition: escape.cpp:418
static void color_end()
Definition: escape.cpp:75
static bool instruction_is_class_constant(const instruction *iptr)
Definition: escape.cpp:149
struct instruction_list_item * next
Definition: escape.cpp:187
static void escape_analysis_process_arguments(escape_analysis_t *e)
Definition: escape.cpp:1141
void dependency_list_add(dependency_list_t *dl, instruction *store)
Definition: escape.cpp:299
static void escape_analysis_init(escape_analysis_t *e, jitdata *jd)
Definition: escape.cpp:443
#define E(why, which)
Definition: escape.cpp:52
struct var_extra ** var
Definition: escape.cpp:220
Definition: escape.cpp:58
static s4 instruction_arg(const instruction *iptr, int arg)
Definition: escape.cpp:145
static s4 instruction_s3(const instruction *iptr)
Definition: escape.cpp:137
static void escape_analysis_process_instructions(escape_analysis_t *e)
Definition: escape.cpp:1011
static int instruction_arg_count(const instruction *iptr)
Definition: escape.cpp:179
int32_t argcount
Definition: instruction.hpp:64
void dependenCy_list_import(dependency_list_t *dl, dependency_list_t *other)
Definition: escape.cpp:314
Definition: escape.cpp:56
struct instruction_list_item instruction_list_item_t
static escape_state_t escape_analysis_get_state(escape_analysis_t *e, s4 var)
Definition: escape.cpp:571
jitdata * jd
Definition: escape.cpp:213
int32_t varindex
Definition: instruction.hpp:63
static s4 var_extra_get_representant(escape_analysis_t *e, s4 var)
Definition: escape.cpp:391
const char * name
Definition: icmd.hpp:393
s4 vartop
Definition: jit.hpp:149
static escape_state_t var_extra_get_escape_state(escape_analysis_t *e, s4 var)
Definition: escape.cpp:409
struct dependency_list_item dependency_list_item_t
static var_extra_t * var_extra_get(escape_analysis_t *e, s4 var)
Definition: escape.cpp:375
instruction_list_item_t * first
Definition: escape.cpp:191
const char * escape_state_to_string(escape_state_t escape_state)
Definition: escape.cpp:94
unsigned adr_args_count
Definition: escape.cpp:222
s4 dependency_list_item_get_dependency(const dependency_list_item_t *item)
Definition: escape.cpp:275
uint8_t u1
Definition: types.hpp:40
void escape_analysis_perform(jitdata *jd)
Definition: escape.cpp:1277
instruction_list_t * returns
Definition: escape.cpp:218
static void escape_analysis_set_allocation(escape_analysis_t *e, s4 var, instruction *iptr)
Definition: escape.cpp:487
static bool escape_analysis_in_same_set(escape_analysis_t *e, s4 var1, s4 var2)
Definition: escape.cpp:530
methodinfo * finalizer
Definition: class.hpp:123
static void escape_analysis_mark_monitors(escape_analysis_t *e)
Definition: escape.cpp:1086
dependency_list_item_t * last
Definition: escape.cpp:291
static void escape_analysis_post_process_returns(escape_analysis_t *e)
Definition: escape.cpp:1032
instruction_list_t * allocations
Definition: escape.cpp:215
void instruction_list_add(instruction_list_t *list, instruction *instr)
Definition: escape.cpp:198
#define MZERO(ptr, type, num)
Definition: memory.hpp:105
instruction * instr
Definition: escape.cpp:186
#define DNEW(type)
Definition: dumpmemory.hpp:370
static bool instruction_is_unresolved(const instruction *iptr)
Definition: escape.cpp:117
bool escape_is_monomorphic(methodinfo *caller, methodinfo *callee)
Definition: escape.cpp:1324
methoddesc * instruction_call_site(const instruction *iptr)
Definition: instruction.cpp:31
typedesc paramtypes[1]
Definition: descriptor.hpp:167
dependency_list_item_t * first
Definition: escape.cpp:290
#define IS_2_WORD_TYPE(a)
Definition: global.hpp:132
static s4 instruction_dst(const instruction *iptr)
Definition: escape.cpp:141
static bool escape_analysis_get_contains_only_arguments(escape_analysis_t *e, s4 var)
Definition: escape.cpp:515
static s4 instruction_s1(const instruction *iptr)
Definition: escape.cpp:129
classref_or_classinfo c
JNIEnv void * arg
Definition: jvmti.h:405
builtintable_entry * builtintable_get_internal(functionptr fp)
Definition: builtin.cpp:275
static methodinfo * instruction_local_methodinfo(const instruction *iptr)
Definition: escape.cpp:157
s4 representant
Definition: escape.cpp:348
dst_operand_t dst
#define FOR_EACH_DEPENDENCY_LIST(dl, it)
Definition: escape.cpp:332
flags_operand_t flags
static void escape_analysis_process_instruction(escape_analysis_t *e, instruction *iptr)
Definition: escape.cpp:697
classinfo * clazz
Definition: method.hpp:80
Utf8String name
Definition: class.hpp:91
void escape_analysis_escape_check(void *vp)
Definition: escape.cpp:1319
static var_extra_t * var_extra_get_no_alloc(const escape_analysis_t *e, s4 var)
Definition: escape.cpp:371
static int instruction_dst_type(const instruction *iptr, jitdata *jd)
Definition: escape.cpp:165
#define I2(why, tov, es)
Definition: escape.cpp:48
s4 * local_map
Definition: jit.hpp:153
static u1 escape_state_to_u1(escape_state_t x)
Definition: escape.hpp:43
MIIterator i
typedesc returntype
Definition: descriptor.hpp:166
Definition: escape.cpp:55
#define FOR_EACH_BASICBLOCK(jd, it)
Definition: jit.hpp:181
int32_t s4
Definition: types.hpp:45
dependency_list_t * dependency_list
Definition: escape.cpp:349
static void escape_analysis_set_contains_only_arguments(escape_analysis_t *e, s4 var)
Definition: escape.cpp:510
static bool escape_analysis_get_contains_argument(escape_analysis_t *e, s4 var)
Definition: escape.cpp:505
union instruction::@12 sx
static void escape_analysis_export_arguments(escape_analysis_t *e)
Definition: escape.cpp:1166
static int instruction_return_type(const instruction *iptr)
Definition: escape.cpp:169
int32_t varindex
icmdtable_entry_t icmd_table[256]
Definition: icmd.cpp:60
MIIterator e
static s2 instruction_get_opcode(const instruction *iptr)
Definition: escape.cpp:109
s1_operand_t s1
unsigned contains_only_args
Definition: escape.cpp:351
static dependency_list_t * var_extra_get_dependency_list(escape_analysis_t *e, s4 var)
Definition: escape.cpp:427
instruction_list_t * monitors
Definition: escape.cpp:217
byte_iterator begin() const
Definition: utf8.hpp:106
void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage)
Definition: show.cpp:917
methoddesc * parseddesc
Definition: method.hpp:78
escape_state_t
Definition: escape.hpp:31
#define I(value)
Definition: codegen.c:279
#define VAROP(v)
Definition: jit.hpp:251
static classinfo * escape_analysis_classinfo_in_var(escape_analysis_t *e, s4 var)
Definition: escape.cpp:575
Definition: escape.cpp:61
static escape_state_t escape_state_from_u1(u1 x)
Definition: escape.hpp:39
#define MNEW(type, num)
Definition: memory.hpp:96
methodinfo * m
Definition: jit.hpp:127
static void escape_analysis_mark_allocations(escape_analysis_t *e)
Definition: escape.cpp:1102
static void color_start(color_t color)
Definition: escape.cpp:67
struct var_extra var_extra_t
#define s3
Definition: md-asm.hpp:71
static void escape_analysis_set_contains_argument(escape_analysis_t *e, s4 var)
Definition: escape.cpp:500
static s4 instruction_field_type(const instruction *iptr)
Definition: escape.cpp:121
static void escape_analysis_post_process_getfields(escape_analysis_t *e)
Definition: escape.cpp:1048
#define FOR_EACH_INSTRUCTION(bptr, it)
Definition: jit.hpp:384
s4 nr
Definition: jit.hpp:312
int8_t s1
Definition: types.hpp:39
static void escape_analysis_merge(escape_analysis_t *e, s4 var1, s4 var2)
Definition: escape.cpp:597
#define E2(why, var)
Definition: escape.cpp:51
#define DMNEW(type, num)
Definition: dumpmemory.hpp:371
int16_t s2
Definition: types.hpp:42
void bc_escape_analysis_perform(methodinfo *m)
static s4 instruction_s2(const instruction *iptr)
Definition: escape.cpp:133
color_t
Definition: escape.cpp:54
struct instruction::@12::@13 s23
static void escape_analysis_add_dependency(escape_analysis_t *e, instruction *store)
Definition: escape.cpp:682
static java_object_t * next
Definition: copy.c:43
static instruction * escape_analysis_get_allocation(const escape_analysis_t *e, s4 var)
Definition: escape.cpp:491
void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
Definition: method.cpp:1085
static void escape_analysis_ensure_state(escape_analysis_t *e, s4 var, escape_state_t escape_state)
Definition: escape.cpp:534
#define str(x)
s4 flags
Definition: method.hpp:70
escape_state_t escape_state
Definition: escape.cpp:347
#define printf(...)
Definition: ssa2.cpp:40
#define THREADOBJECT
Definition: thread-none.hpp:47
void instruction_list_init(instruction_list_t *list)
Definition: escape.cpp:194
static classinfo * instruction_classinfo(const instruction *iptr)
Definition: escape.cpp:153
#define FOR_EACH_INSTRUCTION_LIST(list, it)
Definition: escape.cpp:205
static void var_extra_init(var_extra_t *ve)
Definition: escape.cpp:358
instruction_list_t * getfields
Definition: escape.cpp:216
void dependency_list_init(dependency_list_t *dl)
Definition: escape.cpp:294
unsigned contains_arg
Definition: escape.cpp:350
static void color_printf(color_t color, const char *fmt,...)
Definition: escape.cpp:82