* locales.c: Fix some cut and paste errors.
[mono.git] / mono / jit / jit.c
1 /*
2  * jit.c: The mono JIT compiler.
3  *
4  * Author:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  */
9
10 #include <config.h>
11 #include <mono/os/gc_wrapper.h>
12 #include <glib.h>
13 #include <stdlib.h>
14 #include <stdarg.h>
15 #include <string.h>
16 #include <unistd.h>
17
18 #include <mono/metadata/verify.h>
19 #include <mono/metadata/assembly.h>
20 #include <mono/metadata/loader.h>
21 #include <mono/metadata/tabledefs.h>
22 #include <mono/metadata/class.h>
23 #include <mono/metadata/object.h>
24 #include <mono/metadata/debug-helpers.h>
25 #include <mono/metadata/opcodes.h>
26 #include <mono/metadata/mono-endian.h>
27 #include <mono/metadata/tokentype.h>
28 #include <mono/metadata/threads.h>
29 #include <mono/metadata/socket-io.h>
30 #include <mono/metadata/appdomain.h>
31 #include <mono/arch/x86/x86-codegen.h>
32 #include <mono/io-layer/io-layer.h>
33 #include <mono/metadata/profiler-private.h>
34 #include <mono/metadata/marshal.h>
35 #include <mono/metadata/mono-debug.h>
36 #include <mono/metadata/mono-debug-debugger.h>
37
38 #include "jit.h"
39 #include "helpers.h"
40 #include "regset.h"
41 #include "codegen.h"
42 #include "debug-jit.h"
43
44 /* 
45  * if OPT_BOOL is defined we use 32bit to store boolean local variables.  This
46  * gives great speedup for boolean expressions, but unfortunately it changes
47  * semantics, so i disable it until we have a real solution  */
48 /* #define OPT_BOOL */
49
50 #define MAKE_CJUMP(name)                                                      \
51 case CEE_##name:                                                              \
52 case CEE_##name##_S: {                                                        \
53         gint32 target;                                                        \
54         int near_jump = *ip == CEE_##name##_S;                                \
55         ++ip;                                                                 \
56         sp -= 2;                                                              \
57         t1 = mono_ctree_new (mp, MB_TERM_COMPARE, sp [0], sp [1]);            \
58         t1 = mono_ctree_new (mp, MB_TERM_CBRANCH, t1, NULL);                  \
59         if (near_jump)                                                        \
60                 target = cli_addr + 2 + (signed char) *ip;                    \
61         else                                                                  \
62                 target = cli_addr + 5 + (gint32) read32 (ip);                 \
63         g_assert (target >= 0 && target <= header->code_size);                \
64         g_assert (bcinfo [target].is_block_start);                            \
65         tbb = &cfg->bblocks [bcinfo [target].block_id];                       \
66         create_outstack (cfg, bb, stack, sp - stack);                         \
67         mark_reached (cfg, tbb, bb->outstack, bb->outdepth);                  \
68         t1->data.bi.target = tbb;                                             \
69         t1->data.bi.cond = CEE_##name;                                        \
70         ADD_TREE (t1, cli_addr);                                              \
71         ip += near_jump ? 1: 4;                                               \
72         break;                                                                \
73 }
74
75 #define MAKE_BI_ALU(name)                                                     \
76 case CEE_##name: {                                                            \
77         ++ip;                                                                 \
78         sp -= 2;                                                              \
79         t1 = mono_ctree_new (mp, MB_TERM_##name, sp [0], sp [1]);             \
80         PUSH_TREE (t1, sp [0]->svt);                                          \
81         break;                                                                \
82 }
83
84 #ifndef ARCH_X86
85 #define MAKE_SPILLED_BI_ALU1(name, s1, s2) {                                  \
86         t1 = mono_ctree_new (mp, MB_TERM_##name, s1, s2);                     \
87         PUSH_TREE (t1, s1->svt); }                                            
88 #else
89 #define MAKE_SPILLED_BI_ALU1(name, s1, s2)                                    \
90         t1 = mono_ctree_new (mp, MB_TERM_##name, s1, s2);                     \
91         t1->svt = s1->svt;                                                    \
92         t1 = mono_store_tree (cfg, -1, t1, &t2);                              \
93         g_assert (t1);                                                        \
94         ADD_TREE (t1, cli_addr);                                              \
95         PUSH_TREE (t2, t2->svt);                                              
96 #endif
97
98 #define MAKE_CMP(cname)                                                       \
99 case CEE_##cname: {                                                           \
100         ++ip;                                                                 \
101         sp -= 2;                                                              \
102         t1 = mono_ctree_new (mp, MB_TERM_COMPARE, sp [0], sp [1]);            \
103         t1 = mono_ctree_new (mp, MB_TERM_CSET, t1, NULL);                     \
104         t1->data.i = CEE_##cname;                                             \
105         PUSH_TREE (t1, VAL_I32);                                              \
106         break;                                                                \
107 }
108
109 #define MAKE_SPILLED_BI_ALU(name)                                             \
110 case CEE_##name: {                                                            \
111         ++ip;                                                                 \
112         sp -= 2;                                                              \
113         MAKE_SPILLED_BI_ALU1 (name, sp [0], sp [1])                           \
114         break;                                                                \
115 }
116
117 #define MAKE_LDIND(name, op, svt)                                             \
118 case CEE_##name: {                                                            \
119         ++ip;                                                                 \
120         sp--;                                                                 \
121         t1 = mono_ctree_new (mp, op, *sp, NULL);                              \
122         PUSH_TREE (t1, svt);                                                  \
123         break;                                                                \
124 }
125         
126 #define MAKE_LDELEM(name, op, svt, s)                                         \
127 case CEE_##name: {                                                            \
128         ++ip;                                                                 \
129         sp -= 2;                                                              \
130         t1 = mono_ctree_new (mp, MB_TERM_LDELEMA, sp [0], sp [1]);            \
131         t1->data.i = s;                                                       \
132         t1 = mono_ctree_new (mp, op, t1, NULL);                               \
133         PUSH_TREE (t1, svt);                                                  \
134         break;                                                                \
135 }
136
137 #define MAKE_LDELEM_OLD(name, op, svt, s)                                     \
138 case CEE_##name: {                                                            \
139         ++ip;                                                                 \
140         sp -= 2;                                                              \
141         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
142         t1->data.i = s;                                                       \
143         t1 = mono_ctree_new (mp, MB_TERM_MUL, sp [1], t1);                    \
144         t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
145         t2->data.i = G_STRUCT_OFFSET (MonoArray, vector);                     \
146         t2 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t2);                    \
147         t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);                        \
148         t1 = mono_ctree_new (mp, op, t1, NULL);                               \
149         PUSH_TREE (t1, svt);                                                  \
150         break;                                                                \
151 }
152         
153 #define MAKE_STIND(name, op)                                                  \
154 case CEE_##name: {                                                            \
155         ++ip;                                                                 \
156         sp -= 2;                                                              \
157         t1 = mono_ctree_new (mp, op, sp [0], sp [1]);                         \
158         ADD_TREE (t1, cli_addr);                                              \
159         break;                                                                \
160 }
161
162 #define MAKE_STELEM(name, op, s)                                              \
163 case CEE_##name: {                                                            \
164         ++ip;                                                                 \
165         sp -= 3;                                                              \
166         t1 = mono_ctree_new (mp, MB_TERM_LDELEMA, sp [0], sp [1]);            \
167         t1->data.i = s;                                                       \
168         t1 = mono_ctree_new (mp, op, t1, sp [2]);                             \
169         ADD_TREE (t1, cli_addr);                                              \
170         break;                                                                \
171 }
172         
173 #define MAKE_STELEM_OLD(name, op, s)                                          \
174 case CEE_##name: {                                                            \
175         ++ip;                                                                 \
176         sp -= 3;                                                              \
177         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
178         t1->data.i = s;                                                       \
179         t1 = mono_ctree_new (mp, MB_TERM_MUL, sp [1], t1);                    \
180         t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
181         t2->data.i = G_STRUCT_OFFSET (MonoArray, vector);                     \
182         t2 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t2);                    \
183         t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);                        \
184         t1 = mono_ctree_new (mp, op, t1, sp [2]);                             \
185         ADD_TREE (t1, cli_addr);                                              \
186         break;                                                                \
187 }
188
189 typedef struct {
190         MonoMethod *method;
191         MBTree **arg_map;
192         const unsigned char *end, *saved_ip;
193         MonoImage *saved_image;
194 } MonoInlineInfo;
195         
196 /* Whether to dump the assembly code after genreating it */
197 gboolean mono_jit_dump_asm = FALSE;
198
199 /* Whether to dump the forest */
200 gboolean mono_jit_dump_forest = FALSE;
201
202 /* Whether to print function call traces */
203 gboolean mono_jit_trace_calls = FALSE;
204
205 /* Whether to insert in the code profile callbacks */
206 gboolean mono_jit_profile = FALSE;
207
208 /* Force jit to share code between application domains */
209 gboolean mono_jit_share_code = FALSE;
210
211 /* use linear scan register allocation */
212 gboolean mono_use_linear_scan = TRUE;
213
214 /* inline code */
215 gboolean mono_jit_inline_code = TRUE;
216
217 /* generate bound checking */
218 gboolean mono_jit_boundcheck = TRUE;
219
220 /* inline memcpy */
221 gboolean mono_inline_memcpy = TRUE;
222
223 /* Use alternative (faster) sequence to convert FP values to integers */
224 gboolean mono_use_fast_iconv = FALSE;
225
226 /* TLS id to store jit data */
227 guint32  mono_jit_tls_id;
228
229 /* issue a breakpoint on unhandled excepions */
230 gboolean mono_break_on_exc = FALSE;
231
232 MonoJitStats mono_jit_stats;
233
234 /* 
235  * We sometimes need static data, for example the forest generator need it to
236  * store constants or class data.
237  */
238 inline static gpointer
239 mono_alloc_static (int size)
240 {
241         return g_malloc (size);
242
243 inline static gpointer
244 mono_alloc_static0 (int size)
245 {
246         return g_malloc0 (size);
247
248
249 typedef void (*MonoCCtor) (void);
250
251 static int
252 mono_allocate_intvar (MonoFlowGraph *cfg, int slot, MonoValueType type)
253 {
254         int size, align, vnum, pos;
255         
256         g_assert (type != VAL_UNKNOWN);
257
258         /* take care if you modify MonoValueType */
259         g_assert (VAL_DOUBLE == 4);
260
261         /* fixme: machine dependant */
262         if (type == VAL_POINTER)
263                 type = VAL_I32; /* VAL_I32 and VAL_POINTER share the same slot */
264
265         pos = type - 1 + slot * VAL_DOUBLE;
266
267         if ((vnum = cfg->intvars [pos]))                
268                 return vnum;
269         mono_get_val_sizes (type, &size, &align);
270
271         cfg->intvars[pos] = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, type);
272
273         return cfg->intvars[pos];
274 }
275
276 static int
277 mono_allocate_excvar (MonoFlowGraph *cfg)
278 {
279         if (cfg->excvar)
280                 return cfg->excvar;
281
282         cfg->excvar = arch_allocate_var (cfg, 4, 4, MONO_TEMPVAR, VAL_POINTER);
283
284         VARINFO (cfg, cfg->excvar).isvolatile = 1;
285         
286         return cfg->excvar;
287 }
288
289 /**
290  * mono_jit_runtime_invoke:
291  * @method: the method to invoke
292  * @obj: this pointer
293  * @params: array of parameter values.
294  * @exc: used to catch exceptions objects
295  */
296 static MonoObject*
297 mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
298 {
299         MonoMethod *invoke;
300         MonoObject *(*runtime_invoke) (MonoObject *this, void **params, MonoObject **exc);
301
302         invoke = mono_marshal_get_runtime_invoke (method);
303         runtime_invoke = mono_compile_method (invoke);
304         return runtime_invoke (obj, params, exc);
305 }
306
307 /**
308  * ctree_create_load:
309  * @cfg: pointer to the control flow graph
310  * @type: the type of the value to load
311  * @addr: the address of the value
312  *
313  * Creates a tree to load the value at address @addr.
314  */
315 inline static MBTree *
316 ctree_create_load (MonoFlowGraph *cfg, MonoType *type, MBTree *addr, MonoValueType *svt, gboolean arg)
317 {
318         MonoMemPool *mp = cfg->mp;
319         int ldind;
320         MBTree *t;
321
322         if (arg)
323                 ldind = mono_map_ldarg_type (type, svt);
324         else
325                 ldind = mono_map_ldind_type (type, svt);
326
327         t = mono_ctree_new (mp, ldind, addr, NULL);
328
329         return t;
330 }
331
332 /**
333  * ctree_create_store:
334  * @mp: pointer to a memory pool
335  * @s: the value (tree) to store
336  * @type: the type of the value
337  * @addr: the address of the value
338  *
339  * Creates a tree to store the value @s at address @addr.
340  */
341 inline static MBTree *
342 ctree_create_store (MonoFlowGraph *cfg, MonoType *type, MBTree *addr, 
343                     MBTree *s, gboolean arg)
344 {
345         MonoMemPool *mp = cfg->mp;
346         int stind; 
347         MBTree *t;
348         
349         if (arg)
350                 stind = mono_map_starg_type (type);
351         else
352                 stind = mono_map_stind_type (type);
353
354         t = mono_ctree_new (mp, stind, addr, s);
355
356         if (MONO_TYPE_ISSTRUCT (type))
357                 t->data.i = mono_class_value_size (type->data.klass, NULL);
358         
359         return t;
360 }
361
362 inline static MBTree *
363 ctree_dup_address (MonoMemPool *mp, MBTree *s)
364 {
365         MBTree *t;
366
367         switch (s->op) {
368
369         case MB_TERM_ADDR_L:
370         case MB_TERM_ADDR_G:
371                 t = mono_ctree_new_leaf (mp, s->op);
372                 t->data.i = s->data.i;
373                 t->svt = VAL_POINTER;
374                 return t;
375         default:
376                 g_warning ("unknown tree opcode %d", s->op);
377                 g_assert_not_reached ();
378         }
379
380         return NULL;
381 }
382
383 /**
384  * Create a duplicate of the value of a tree. This is
385  * easy for trees starting with LDIND/STIND, since the
386  * duplicate is simple a LDIND tree with the same address.
387  * For other trees we have to split the tree into one tree
388  * storing the value to a new temporary variable, and 
389  * another tree which loads that value back. We can then
390  * duplicate the second tree.
391  */
392 static MBTree *
393 ctree_create_dup (MonoMemPool *mp, MBTree *s)
394 {
395         MBTree *t;
396         
397         switch (s->op) {
398         case MB_TERM_STIND_I1:
399         case MB_TERM_LDIND_I1:
400                 t = ctree_dup_address (mp, s->left);
401                 t = mono_ctree_new (mp, MB_TERM_LDIND_I1, t, NULL);
402                 t->svt = VAL_I32;
403                 break;
404         case MB_TERM_STIND_I2:
405         case MB_TERM_LDIND_I2:
406                 t = ctree_dup_address (mp, s->left);
407                 t = mono_ctree_new (mp, MB_TERM_LDIND_I2, t, NULL);
408                 t->svt = VAL_I32;
409                 break;
410         case MB_TERM_STIND_I4:
411         case MB_TERM_LDIND_I4:
412                 t = ctree_dup_address (mp, s->left);
413                 t = mono_ctree_new (mp, MB_TERM_LDIND_I4, t, NULL);
414                 t->svt = VAL_I32;
415                 break;
416         case MB_TERM_STIND_I8:
417         case MB_TERM_LDIND_I8:
418                 t = ctree_dup_address (mp, s->left);
419                 t = mono_ctree_new (mp, MB_TERM_LDIND_I8, t, NULL);
420                 t->svt = VAL_I64;
421                 break;
422         case MB_TERM_STIND_R4:
423         case MB_TERM_LDIND_R4:
424                 t = ctree_dup_address (mp, s->left);
425                 t = mono_ctree_new (mp, MB_TERM_LDIND_R4, t, NULL);
426                 t->svt = VAL_DOUBLE;
427                 break;
428         case MB_TERM_STIND_R8:
429         case MB_TERM_LDIND_R8:
430                 t = ctree_dup_address (mp, s->left);
431                 t = mono_ctree_new (mp, MB_TERM_LDIND_R8, t, NULL);
432                 t->svt = VAL_DOUBLE;
433                 break;
434         case MB_TERM_STIND_OBJ:
435         case MB_TERM_LDIND_OBJ:
436                 t = ctree_dup_address (mp, s->left);
437                 t = mono_ctree_new (mp, MB_TERM_LDIND_OBJ, t, NULL);
438                 t->svt = VAL_UNKNOWN;
439                 break;
440         default:
441                 g_warning ("unknown op \"%s\"", mono_burg_term_string [s->op]);
442                 g_assert_not_reached ();
443         }
444
445         return t;
446 }
447
448 static MBTree *
449 mono_store_tree (MonoFlowGraph *cfg, int slot, MBTree *s, MBTree **tdup)
450 {
451         MonoMemPool *mp = cfg->mp;
452         MBTree *t;
453         int vnum = 0;
454
455         switch (s->op) {
456         case MB_TERM_STIND_I1:
457         case MB_TERM_LDIND_I1:
458         case MB_TERM_STIND_I2:
459         case MB_TERM_LDIND_I2:
460         case MB_TERM_STIND_I4:
461         case MB_TERM_LDIND_I4:
462         case MB_TERM_STIND_I8:
463         case MB_TERM_LDIND_I8:
464         case MB_TERM_STIND_R4:
465         case MB_TERM_LDIND_R4:
466         case MB_TERM_STIND_R8:
467         case MB_TERM_LDIND_R8: {
468                 if (slot >= 0) {
469                         vnum = mono_allocate_intvar (cfg, slot, s->svt);
470
471                         if (s->left->op == MB_TERM_ADDR_L && s->left->data.i == vnum) {
472                                 if (tdup)
473                                         *tdup = ctree_create_dup (mp, s);
474                                 return NULL;
475                         }
476                         // fall through
477                 } else {
478                         if (tdup)
479                                 *tdup = ctree_create_dup (mp, s);
480                         return NULL;
481                 }
482         }       
483         default: {
484                         g_assert (s->svt != VAL_UNKNOWN);
485
486                         if (slot >= 0) {
487                                 if (!vnum)
488                                         vnum = mono_allocate_intvar (cfg, slot, s->svt);
489                         } else {
490                                 int size, align;
491                                 mono_get_val_sizes (s->svt, &size, &align);
492                                 vnum = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, s->svt);
493                         }
494
495                         t = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
496                         t->data.i = vnum;
497                        
498                         t = mono_ctree_new (mp, mono_map_store_svt_type (s->svt), t, s);
499                         t->svt = s->svt;
500                 }
501         }
502
503         if (tdup) 
504                 *tdup = ctree_create_dup (mp, t);
505
506         return t;
507 }
508
509 static MonoBBlock *
510 mono_find_final_block (MonoFlowGraph *cfg, guint32 ip, guint32 target, int type)
511 {
512         MonoMethod *method = cfg->method;
513         MonoBytecodeInfo *bcinfo = cfg->bcinfo;
514         MonoMethodHeader *header = ((MonoMethodNormal *)method)->header;
515         MonoExceptionClause *clause;
516         int i;
517
518         for (i = 0; i < header->num_clauses; ++i) {
519                 clause = &header->clauses [i];
520
521                 if (MONO_OFFSET_IN_CLAUSE (clause, ip) && 
522                     (!MONO_OFFSET_IN_CLAUSE (clause, target))) {
523                         if (clause->flags & type) {
524                                 g_assert (bcinfo [clause->handler_offset].is_block_start);
525                                 return &cfg->bblocks [bcinfo [clause->handler_offset].block_id];
526                         }
527                 }
528         }
529         return NULL;
530 }
531
532 static void
533 mono_cfg_add_successor (MonoFlowGraph *cfg, MonoBBlock *bb, gint32 target)
534 {
535         MonoBBlock *tbb;
536         GList *l;
537
538         g_assert (cfg->bcinfo [target].is_block_start);
539
540         tbb = &cfg->bblocks [cfg->bcinfo [target].block_id];
541         g_assert (tbb);
542
543         for (l = bb->succ; l; l = l->next) {
544                 MonoBBlock *t = (MonoBBlock *)l->data;
545                 if (t == tbb)
546                         return;
547         }
548
549         bb->succ = g_list_prepend (bb->succ, tbb);
550 }
551
552
553 #define CREATE_BLOCK(t) {if (!bcinfo [t].is_block_start) {block_count++;bcinfo [t].is_block_start = 1; }}
554
555 static void
556 mono_analyze_flow (MonoFlowGraph *cfg)
557 {
558         MonoMethod *method = cfg->method;
559         const unsigned char *ip, *end;
560         MonoMethodHeader *header;
561         MonoBytecodeInfo *bcinfo;
562         MonoExceptionClause *clause;
563         MonoBBlock *bblocks, *bb;
564         const MonoOpcode *opcode;
565         gboolean block_end;
566         int i, block_count;
567
568         header = ((MonoMethodNormal *)method)->header;
569
570         bcinfo = g_malloc0 (header->code_size * sizeof (MonoBytecodeInfo));
571         bcinfo [0].is_block_start = 1;
572         block_count = 1;
573         block_end = FALSE;
574
575         ip = header->code;
576         end = ip + header->code_size;
577
578         mono_jit_stats.cil_code_size += header->code_size;
579
580         for (i = 0; i < header->num_clauses; ++i) {
581                 clause = &header->clauses [i];
582
583                 CREATE_BLOCK (clause->try_offset);
584                 CREATE_BLOCK (clause->handler_offset);
585
586                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
587                         CREATE_BLOCK (clause->token_or_filter);
588         }
589
590         while (ip < end) {
591                 guint32 cli_addr = ip - header->code;
592
593                 //printf ("IL%04x OPCODE %s\n", cli_addr, mono_opcode_names [*ip]);
594                 
595                 if (block_end) {
596                         CREATE_BLOCK (cli_addr);
597                         block_end = FALSE;
598                 }
599
600                 i = mono_opcode_value (&ip);
601
602                 opcode = &mono_opcodes [i];
603
604                 switch (opcode->flow_type) {
605                 case MONO_FLOW_RETURN:
606                 case MONO_FLOW_ERROR:
607                         block_end = 1;
608                         break;
609                 case MONO_FLOW_BRANCH: /* we handle branch when checking the argument type */
610                 case MONO_FLOW_COND_BRANCH:
611                 case MONO_FLOW_CALL:
612                 case MONO_FLOW_NEXT:
613                 case MONO_FLOW_META:
614                         break;
615                 default:
616                         g_assert_not_reached ();
617                 }
618
619                 switch (opcode->argument) {
620                 case MonoInlineNone:
621                         ++ip;
622                         break;
623                 case MonoInlineString:
624                         mono_ldstr (mono_domain_get (), method->klass->image, mono_metadata_token_index (read32 (ip + 1)));
625                         /* fall through */
626                 case MonoInlineType:
627                 case MonoInlineField:
628                 case MonoInlineMethod:
629                 case MonoInlineTok:
630                 case MonoInlineSig:
631                 case MonoShortInlineR:
632                 case MonoInlineI:
633                         ip += 5;
634                         break;
635                 case MonoInlineVar:
636                         ip += 3;
637                         break;
638                 case MonoShortInlineVar:
639                 case MonoShortInlineI:
640                         ip += 2;
641                         break;
642                 case MonoShortInlineBrTarget:
643                         ip++;
644                         i = (signed char)*ip;
645                         ip++;
646                         CREATE_BLOCK (cli_addr + 2 + i);
647                         block_end = 1;
648                        
649                         break;
650                 case MonoInlineBrTarget:
651                         ip++;
652                         i = read32 (ip);
653                         ip += 4;
654                         CREATE_BLOCK (cli_addr + 5 + i);
655                         block_end = 1;
656                         break;
657                 case MonoInlineSwitch: {
658                         gint32 st, target, n;
659                         ++ip;
660                         n = read32 (ip);
661                         ip += 4;
662                         st = cli_addr + 5 + 4 * n;
663                         CREATE_BLOCK (st);
664
665                         for (i = 0; i < n; i++) {
666                                 target = read32 (ip) + st;
667                                 ip += 4;
668                                 CREATE_BLOCK (target);                  
669                         }
670                         /*
671                          * Note: the code didn't set block_end in switch.
672                          */
673                         break;
674                 }
675                 case MonoInlineR:
676                 case MonoInlineI8:
677                         ip += 9;
678                         break;
679                 default:
680                         g_assert_not_reached ();
681                 }
682         }
683
684
685         g_assert (block_count);
686
687         bb = bblocks  = g_malloc0 (sizeof (MonoBBlock) * block_count);
688
689         block_count = 0;
690         bblocks [0].reached = 1;
691
692         for (i = 0; i < header->code_size; i++) {
693                 if (bcinfo [i].is_block_start) {
694                         bb->cli_addr = i;
695                         bb->num = block_count;
696                         bb->forest = g_ptr_array_new ();
697                         if (block_count)
698                                 bb [-1].length = i - bb [-1].cli_addr; 
699                         bcinfo [i].block_id = block_count;
700                         bb++;
701                         block_count++;
702                 }
703         }
704         bb [-1].length = header->code_size - bb [-1].cli_addr; 
705
706         cfg->bcinfo = bcinfo;
707         cfg->bblocks = bblocks;
708         cfg->block_count = block_count;
709
710         mono_jit_stats.basic_blocks += block_count;
711         mono_jit_stats.max_basic_blocks = MAX (block_count, mono_jit_stats.max_basic_blocks);
712        
713         for (i = 0; i < header->num_clauses; ++i) {
714                 MonoBBlock *sbb, *tbb;
715                 clause = &header->clauses [i];
716                 sbb = &cfg->bblocks [bcinfo [clause->try_offset].block_id];
717                 tbb = &cfg->bblocks [bcinfo [clause->handler_offset].block_id];
718                 g_assert (sbb && tbb);
719                 sbb->succ = g_list_prepend (sbb->succ, tbb);
720         }
721
722         ip = header->code;
723         end = ip + header->code_size;
724         bb = NULL;
725
726         while (ip < end) {
727                 guint32 cli_addr = ip - header->code;
728
729                 if (bcinfo [cli_addr].is_block_start) {
730                         MonoBBlock *tbb = &cfg->bblocks [bcinfo [cli_addr].block_id];           
731                         if (bb && !bb->succ)
732                                 bb->succ = g_list_prepend (bb->succ, tbb);
733                         bb = tbb;
734                 }
735                 g_assert (bb);
736
737                 i = mono_opcode_value (&ip);
738
739                 opcode = &mono_opcodes [i];
740
741                 switch (opcode->argument) {
742                 case MonoInlineNone:
743                         ++ip;
744                         break;
745                 case MonoInlineString:
746                 case MonoInlineType:
747                 case MonoInlineField:
748                 case MonoInlineMethod:
749                 case MonoInlineTok:
750                 case MonoInlineSig:
751                 case MonoShortInlineR:
752                 case MonoInlineI:
753                         ip += 5;
754                         break;
755                 case MonoInlineVar:
756                         ip += 3;
757                         break;
758                 case MonoShortInlineVar:
759                 case MonoShortInlineI:
760                         ip += 2;
761                         break;
762                 case MonoShortInlineBrTarget:
763                         ip++;
764                         i = (signed char)*ip;
765                         ip++;
766                         mono_cfg_add_successor (cfg, bb, cli_addr + 2 + i);
767                         if (opcode->flow_type == MONO_FLOW_COND_BRANCH)
768                                 mono_cfg_add_successor (cfg, bb, cli_addr + 2);
769                         break;
770                 case MonoInlineBrTarget:
771                         ip++;
772                         i = read32 (ip);
773                         ip += 4;
774                         mono_cfg_add_successor (cfg, bb, cli_addr + 5 + i);
775                         if (opcode->flow_type == MONO_FLOW_COND_BRANCH)
776                                 mono_cfg_add_successor (cfg, bb, cli_addr + 5);
777                         break;
778                 case MonoInlineSwitch: {
779                         gint32 st, target, n;
780                         ++ip;
781                         n = read32 (ip);
782                         ip += 4;
783                         st = cli_addr + 5 + 4 * n;
784                         mono_cfg_add_successor (cfg, bb, st);
785
786                         for (i = 0; i < n; i++) {
787                                 target = read32 (ip) + st;
788                                 ip += 4;
789                                 mono_cfg_add_successor (cfg, bb, target);
790                         }
791                         break;
792                 }
793                 case MonoInlineR:
794                 case MonoInlineI8:
795                         ip += 9;
796                         break;
797                 default:
798                         g_assert_not_reached ();
799                 }
800         }
801 }
802
803 /**
804  * ves_array_element_address:
805  * @this: a pointer to the array object
806  *
807  * Returns: the address of an array element.
808  */
809 static gpointer 
810 ves_array_element_address (MonoArray *this, ...)
811 {
812         MonoClass *class;
813         va_list ap;
814         int i, ind, esize;
815         gpointer ea;
816
817         MONO_ARCH_SAVE_REGS;
818
819         g_assert (this != NULL);
820
821         va_start(ap, this);
822
823         class = this->obj.vtable->klass;
824
825         ind = va_arg(ap, int);
826         g_assert (this->bounds != NULL);
827
828         ind -= this->bounds [0].lower_bound;
829         for (i = 1; i < class->rank; i++) {
830                 ind = ind*this->bounds [i].length + va_arg(ap, int) -
831                         this->bounds [i].lower_bound;;
832         }
833
834         if (ind >= this->max_length)
835                 mono_raise_exception (mono_get_exception_index_out_of_range ());
836
837         esize = mono_array_element_size (class);
838         ea = (gpointer*)((char*)this->vector + (ind * esize));
839         //printf ("AADDRESS %p %p %d %d %08X\n", this, ea, ind, esize, *(gpointer *)ea);
840
841         va_end(ap);
842
843         return ea;
844 }
845
846 static MonoArray *
847 mono_array_new_va (MonoMethod *cm, ...)
848 {
849         MonoDomain *domain = mono_domain_get ();
850         va_list ap;
851         guint32 *lengths;
852         guint32 *lower_bounds;
853         int pcount = cm->signature->param_count;
854         int rank = cm->klass->rank;
855         int i, d;
856
857         va_start (ap, cm);
858
859         lengths = alloca (sizeof (guint32) * pcount);
860         for (i = 0; i < pcount; ++i)
861                 lengths [i] = d = va_arg(ap, int);
862
863         if (rank == pcount) {
864                 /* Only lengths provided. */
865                 lower_bounds = NULL;
866         } else {
867                 g_assert (pcount == (rank * 2));
868                 /* lower bounds are first. */
869                 lower_bounds = lengths;
870                 lengths += rank;
871         }
872         va_end(ap);
873
874         return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
875 }
876
877 #define ADD_TREE(t,a)   do { t->cli_addr = a; g_ptr_array_add (forest, (t)); } while (0)
878 #define PUSH_TREE(t,k)  do { int tt = k; *sp = t; t->svt = tt; t->cli_addr = cli_addr; sp++; } while (0)
879
880 #define LOCAL_POS(n)    (1 + n)
881
882 #ifdef OPT_BOOL
883 #define LOCAL_TYPE(n)   ((header)->locals [(n)]->type == MONO_TYPE_BOOLEAN && !(header)->locals [(n)]->byref ? &mono_defaults.int32_class->byval_arg : (header)->locals [(n)])
884 #else
885 #define LOCAL_TYPE(n)   ((header)->locals [(n)])
886 #endif
887
888 #define ARG_POS(n)      (firstarg + n)
889 #define ARG_TYPE(n)     ((n) ? (signature)->params [(n) - (signature)->hasthis] : \
890                         (signature)->hasthis ? &method->klass->this_arg: (signature)->params [(0)])
891
892
893 /*
894  * replaces all occurences of variable @varnum in @tree with @copy. 
895  */
896 static void
897 mono_copy_used_var (MonoFlowGraph *cfg, MBTree *tree, int varnum, MBTree **copy)
898 {
899         MBTree *t1, *t2;
900         int v, size, align;
901
902         if (tree->left)
903                 mono_copy_used_var (cfg, tree->left, varnum, copy);
904         if (tree->right)
905                 mono_copy_used_var (cfg, tree->right, varnum, copy);
906
907         switch (tree->op) {
908         case MB_TERM_LDIND_I1:
909         case MB_TERM_LDIND_I2:
910         case MB_TERM_LDIND_I4:
911         case MB_TERM_LDIND_I8:
912         case MB_TERM_LDIND_R4:
913         case MB_TERM_LDIND_R8:
914                 if (tree->left->op == MB_TERM_ADDR_L &&
915                     tree->left->data.i == varnum) {
916                         if (*copy) {
917                                 tree->left->data.i = (*copy)->left->data.i;
918                                 return;
919                         } 
920                         
921                         mono_get_val_sizes (tree->svt, &size, &align);
922                         v = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, tree->svt);
923  
924                         t1 = mono_ctree_new_leaf (cfg->mp, MB_TERM_ADDR_L);
925                         t1->data.i = v;
926                        
927                         t2 = mono_ctree_new_leaf (cfg->mp, MB_TERM_ADDR_L);
928                         t2->data.i = varnum;
929                         t2 = mono_ctree_new (cfg->mp, tree->op, t2, NULL);
930
931                         t2 = mono_ctree_new (cfg->mp, mono_map_store_svt_type (tree->svt), t1, t2);
932                         t2->svt = tree->svt;
933
934                         tree->left->data.i = v;
935
936                         *copy = t2;
937                 }
938         }
939 }
940
941 /* 
942  * if a variable is modified and there are still referencence
943  * to it on the runtime stack we need to store the value into
944  * a temporary variable and use that value instead of the 
945  * modified one.
946  */
947 static MBTree *
948 mono_stack_duplicate_used_var (MonoFlowGraph *cfg, MBTree **stack, MBTree **sp, int varnum)
949 {
950         MBTree *res = NULL;
951
952         while (stack < sp) {
953                 mono_copy_used_var (cfg, *stack, varnum, &res);
954                 stack++;
955         }
956
957         return res;
958 }
959
960 static int
961 check_inlining (MonoMethod *method)
962 {
963         MonoMethodHeader *header;
964         MonoMethodSignature *signature = method->signature;
965         register const unsigned char *ip, *end;
966         gboolean stop;
967         int i, arg_used [256];
968
969         g_assert (method);
970
971         if (method->inline_info)
972                 return method->inline_count;
973
974         method->inline_info = 1;
975         
976         if (method->wrapper_type != MONO_WRAPPER_NONE)
977                 goto fail;
978
979         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
980             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
981             (method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING) ||
982             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
983             (method->klass->marshalbyref) ||
984             MONO_TYPE_ISSTRUCT (signature->ret))
985                 goto fail;;
986        
987         if (!(header = ((MonoMethodNormal *)method)->header) ||
988             header->num_clauses)
989                 goto fail;;
990
991         if (header->num_clauses)
992                 goto fail;
993         
994         ip = header->code;
995         end = ip + header->code_size;
996
997         for (i = 0; i < 256; i++)
998                 arg_used [i] = 0;
999
1000         stop = FALSE;        
1001         while (!stop && ip < end) {
1002
1003                 switch (*ip) {
1004                 case CEE_NOP:
1005                 case CEE_BREAK:
1006                 case CEE_DUP:
1007                 case CEE_POP:
1008                 case CEE_LDIND_I1:
1009                 case CEE_LDIND_U1:
1010                 case CEE_LDIND_I2:
1011                 case CEE_LDIND_U2:
1012                 case CEE_LDIND_I4:
1013                 case CEE_LDIND_U4:
1014                 case CEE_LDIND_I8:
1015                 case CEE_LDIND_I:
1016                 case CEE_LDIND_R4:
1017                 case CEE_LDIND_R8:
1018                 case CEE_LDIND_REF:
1019                 case CEE_STIND_REF:
1020                 case CEE_STIND_I1:
1021                 case CEE_STIND_I2:
1022                 case CEE_STIND_I4:
1023                 case CEE_STIND_I8:
1024                 case CEE_STIND_R4:
1025                 case CEE_STIND_R8:
1026                 case CEE_ADD:
1027                 case CEE_SUB:
1028                 case CEE_MUL:
1029                 case CEE_DIV:
1030                 case CEE_DIV_UN:
1031                 case CEE_REM:
1032                 case CEE_REM_UN:
1033                 case CEE_AND:
1034                 case CEE_OR:
1035                 case CEE_XOR:
1036                 case CEE_SHL:
1037                 case CEE_SHR:
1038                 case CEE_SHR_UN:
1039                 case CEE_NEG:
1040                 case CEE_NOT:
1041                 case CEE_CONV_I1:
1042                 case CEE_CONV_I2:
1043                 case CEE_CONV_I4:
1044                 case CEE_CONV_I8:
1045                 case CEE_CONV_R4:
1046                 case CEE_CONV_R8:
1047                 case CEE_CONV_U4:
1048                 case CEE_CONV_U8:
1049                 case CEE_CONV_R_UN:
1050                 case CEE_CONV_OVF_I1_UN:
1051                 case CEE_CONV_OVF_I2_UN:
1052                 case CEE_CONV_OVF_I4_UN:
1053                 case CEE_CONV_OVF_I8_UN:
1054                 case CEE_CONV_OVF_U1_UN:
1055                 case CEE_CONV_OVF_U2_UN:
1056                 case CEE_CONV_OVF_U4_UN:
1057                 case CEE_CONV_OVF_U8_UN:
1058                 case CEE_CONV_OVF_I_UN:
1059                 case CEE_CONV_OVF_U_UN:
1060                 case CEE_LDLEN:
1061                 case CEE_LDELEM_I1:
1062                 case CEE_LDELEM_U1:
1063                 case CEE_LDELEM_I2:
1064                 case CEE_LDELEM_U2:
1065                 case CEE_LDELEM_I4:
1066                 case CEE_LDELEM_U4:
1067                 case CEE_LDELEM_I8:
1068                 case CEE_LDELEM_I:
1069                 case CEE_LDELEM_R4:
1070                 case CEE_LDELEM_R8:
1071                 case CEE_LDELEM_REF:
1072                 case CEE_STELEM_I:
1073                 case CEE_STELEM_I1:
1074                 case CEE_STELEM_I2:
1075                 case CEE_STELEM_I4:
1076                 case CEE_STELEM_I8:
1077                 case CEE_STELEM_R4:
1078                 case CEE_STELEM_R8:
1079                 case CEE_STELEM_REF:
1080                 case CEE_CONV_OVF_I1:
1081                 case CEE_CONV_OVF_U1:
1082                 case CEE_CONV_OVF_I2:
1083                 case CEE_CONV_OVF_U2:
1084                 case CEE_CONV_OVF_I4:
1085                 case CEE_CONV_OVF_U4:
1086                 case CEE_CONV_OVF_I8:
1087                 case CEE_CONV_OVF_U8:
1088                 case CEE_CKFINITE:
1089                 case CEE_CONV_U2:
1090                 case CEE_CONV_U1:
1091                 case CEE_CONV_I:
1092                 case CEE_CONV_OVF_I:
1093                 case CEE_CONV_OVF_U:
1094                 case CEE_ADD_OVF:
1095                 case CEE_ADD_OVF_UN:
1096                 case CEE_MUL_OVF:
1097                 case CEE_MUL_OVF_UN:
1098                 case CEE_SUB_OVF:
1099                 case CEE_SUB_OVF_UN:
1100                 case CEE_STIND_I:
1101                 case CEE_CONV_U:
1102                 case CEE_LDNULL:
1103                 case CEE_LDC_I4_M1:
1104                 case CEE_LDC_I4_0:
1105                 case CEE_LDC_I4_1:
1106                 case CEE_LDC_I4_2:
1107                 case CEE_LDC_I4_3:
1108                 case CEE_LDC_I4_4:
1109                 case CEE_LDC_I4_5:
1110                 case CEE_LDC_I4_6:
1111                 case CEE_LDC_I4_7:
1112                 case CEE_LDC_I4_8:
1113                         ++ip;
1114                         break;
1115                 case CEE_LDC_I4_S:
1116                         ip += 2;
1117                         break;
1118                 case CEE_LDC_I4:
1119                 case CEE_LDC_R4:
1120                 case CEE_CPOBJ:
1121                 case CEE_LDOBJ:
1122                 case CEE_LDSTR:
1123                 case CEE_CASTCLASS:
1124                 case CEE_ISINST:
1125                 case CEE_UNBOX:
1126                 case CEE_LDFLD:
1127                 case CEE_LDFLDA:
1128                 case CEE_STFLD:
1129                 case CEE_LDSFLD:
1130                 case CEE_LDSFLDA:
1131                 case CEE_STSFLD:
1132                 case CEE_STOBJ:
1133                 case CEE_BOX:
1134                 case CEE_NEWARR:
1135                 case CEE_LDELEMA:
1136                 case CEE_LDTOKEN:
1137                         ip += 5;
1138                         break;
1139                 case CEE_LDC_I8:
1140                 case CEE_LDC_R8:
1141                         ip += 9;
1142                         break;
1143                 case CEE_NEWOBJ:
1144                 case CEE_CALL:
1145                 case CEE_CALLVIRT: {
1146                         MonoMethod *cm;
1147                         guint32 token;
1148                         ++ip;
1149                         token = read32 (ip);
1150                         ip += 4;
1151
1152                         if (method->wrapper_type != MONO_WRAPPER_NONE)
1153                                 cm = mono_method_get_wrapper_data (method, token);
1154                         else
1155                                 cm = mono_get_method (method->klass->image, token, NULL);
1156                         if (!cm)
1157                                 goto fail;
1158
1159                         if (cm == method)
1160                                 goto fail;
1161
1162                         /* we do not inline functions containing calls to 
1163                            stack query functions */ 
1164                         if (cm->klass == mono_defaults.stack_frame_class ||
1165                             cm->klass == mono_defaults.stack_trace_class)
1166                                 goto fail;
1167                                 
1168                         break;
1169                 }
1170                 case CEE_LDARG_0:
1171                 case CEE_LDARG_1:
1172                 case CEE_LDARG_2:
1173                 case CEE_LDARG_3: {
1174                         int an = (*ip) - CEE_LDARG_0;
1175                         if (arg_used [an])
1176                                 goto fail;
1177                         arg_used [an] = TRUE;
1178                         ++ip;
1179                         break;
1180                 }       
1181                 case CEE_LDARG_S:
1182                         ++ip;
1183                         if (arg_used [*ip])
1184                                 goto fail;
1185                         arg_used [*ip] = TRUE;
1186                         ++ip;
1187                         break;
1188         
1189                 case CEE_PREFIX1: {
1190                         ++ip;                   
1191                         switch (*ip) {
1192                         case CEE_LDARG: {
1193                                 guint16 an;
1194                                 ip++;
1195                                 an = read16 (ip);
1196                                 ip += 2;
1197                                 if (an > 255 || arg_used [an])
1198                                         goto fail;
1199                                 arg_used [an] = TRUE;
1200                                 break;
1201                         }       
1202
1203                         case CEE_CEQ:
1204                         case CEE_CGT:
1205                         case CEE_CGT_UN:
1206                         case CEE_CLT:
1207                         case CEE_CLT_UN:
1208                         case CEE_CPBLK:
1209                         case CEE_INITBLK:
1210                                 ip++;
1211                                 break;
1212                         case CEE_LDFTN:
1213                         case CEE_LDVIRTFTN: {
1214                                 MonoMethod *cm;
1215                                 guint32 token;
1216                                 ++ip;
1217                                 token = read32 (ip);
1218                                 ip += 4;
1219
1220                                 cm = mono_get_method (method->klass->image, token, NULL);
1221                                 g_assert (cm);
1222
1223                                 if (cm == method)
1224                                         goto fail;
1225                                 
1226                                 break;
1227                         }
1228                         case CEE_INITOBJ:
1229                         case CEE_SIZEOF:
1230                                 ip += 5;
1231                                 break;
1232                         default:
1233                                 stop = TRUE;
1234                                 break;
1235                         }
1236                 }
1237                 default:
1238                         stop = TRUE;
1239                         break;                  
1240                 }
1241         }
1242
1243         if (ip < end &&
1244             !(ip [0] == CEE_RET ||
1245               ((ip + 4) < end &&
1246                ip [0] == CEE_STLOC_0 &&
1247                ip [1] == CEE_BR_S &&
1248                ip [2] == 0 &&
1249                ip [3] == CEE_LDLOC_0 &&
1250                ip [4] == CEE_RET)))
1251                 goto fail;
1252         
1253         if (signature->hasthis && arg_used [0])
1254                 method->uses_this = 1;
1255
1256         mono_jit_stats.inlineable_methods++;
1257
1258         return method->inline_count = ip - header->code;
1259
1260  fail:
1261         return method->inline_count = -1;
1262 }
1263
1264 static void
1265 create_outstack (MonoFlowGraph *cfg, MonoBBlock *bb, MBTree **stack, int depth)
1266 {
1267         MonoMemPool *mp = cfg->mp;
1268         MBTree **c = stack, *t1, *t2;
1269         GPtrArray *forest = bb->forest;
1270         int i;
1271
1272         g_assert (bb->reached);
1273
1274         if (depth <= 0)
1275                 return;
1276
1277         if (bb->outstack) {
1278                 g_assert (bb->outdepth == depth);
1279                 return;
1280         }
1281
1282         bb->outdepth = depth;
1283         bb->outstack = mono_mempool_alloc (mp, depth * sizeof (MBTree *));
1284         
1285         for (i = 0; i < depth; i++) {
1286                 if ((t1 = mono_store_tree (cfg, i, c [i], &t2)))
1287                         ADD_TREE (t1, -1);
1288                 bb->outstack [i] = t2;
1289         }
1290 }
1291
1292 static void
1293 mark_reached (MonoFlowGraph *cfg, MonoBBlock *target, MBTree **stack, int depth)
1294 {
1295         MonoMemPool *mp = cfg->mp;
1296         int i;
1297
1298         if (target->reached)
1299                 return;
1300
1301         target->reached = 1;
1302
1303         if (depth == 0)
1304                 return;
1305
1306         g_assert (stack);
1307
1308         if (target->instack) {
1309                 g_assert (target->indepth == depth);
1310                 return;
1311         }
1312
1313         target->indepth = depth;
1314         target->instack = mono_mempool_alloc (mp, depth * sizeof (MBTree *));
1315         
1316         for (i = 0; i < depth; i++) {
1317                 target->instack [i] = ctree_create_dup (mp, stack [i]);
1318         }
1319         
1320         
1321 }
1322
1323 #define MARK_REACHED(bb) do { if (!bb->reached) { bb->reached = 1; }} while (0)
1324
1325 /**
1326  * mono_analyze_stack:
1327  * @cfg: control flow graph
1328  *
1329  * This is the architecture independent part of JIT compilation.
1330  * It creates a forest of trees which can then be fed into the
1331  * architecture dependent code generation.
1332  *
1333  * The algorithm is from Andi Krall, the same is used in CACAO
1334  */
1335 static gboolean
1336 mono_analyze_stack (MonoFlowGraph *cfg)
1337 {
1338         MonoMethod *method = cfg->method;
1339         MonoMemPool *mp = cfg->mp;
1340         MonoBytecodeInfo *bcinfo = cfg->bcinfo;
1341         MonoMethodHeader *header;
1342         MonoMethodSignature *signature;
1343         MonoImage *image;
1344         MonoValueType svt;
1345         MBTree **sp, **stack, **arg_sp, **arg_map = NULL, *t1, *t2, *t3;
1346         MonoJitArgumentInfo *arg_info, default_arg_info [10];
1347         register const unsigned char *ip, *end;
1348         GPtrArray *forest;
1349         int i, j, depth, repeat_count;
1350         int varnum = 0, firstarg = 0;
1351         gboolean repeat, superblock_end;
1352         MonoBBlock *bb, *tbb;
1353         int maxstack;
1354         GList *inline_list = NULL;
1355         gboolean tail_recursion;
1356
1357         header = ((MonoMethodNormal *)method)->header;
1358         signature = method->signature;
1359         image = method->klass->image; 
1360
1361         /* we add 10 extra slots for method inlining */
1362         maxstack = header->max_stack + 10;
1363         sp = stack = alloca (sizeof (MBTree *) * (maxstack + 1));
1364
1365         /* allocate local variables */
1366
1367         if (header->num_locals) {
1368                 int size, align;
1369                 
1370                 for (i = 0; i < header->num_locals; ++i) {
1371                         MonoValueType svt;
1372                         size = mono_type_size (LOCAL_TYPE (i), &align);
1373                         mono_map_ldind_type (header->locals [i], &svt);
1374                         varnum = arch_allocate_var (cfg, size, align, MONO_LOCALVAR, svt);
1375                         if (i == 0)
1376                                 cfg->locals_start_index = varnum;
1377                 }
1378         }
1379
1380         cfg->args_start_index = firstarg = varnum + 1;
1381  
1382         /* allocate argument variables */
1383
1384         if (signature->param_count + 1 < 10)
1385                 arg_info = default_arg_info;
1386         else 
1387                 arg_info = g_new (MonoJitArgumentInfo, signature->param_count + 1);
1388
1389         arch_get_argument_info (signature, signature->param_count, arg_info);
1390
1391         if (signature->hasthis) 
1392                 arch_allocate_arg (cfg, &arg_info [0], VAL_POINTER);
1393         
1394         if (signature->param_count)
1395                 for (i = 0; i < signature->param_count; ++i)
1396                         arch_allocate_arg (cfg, &arg_info [i + 1], VAL_UNKNOWN);
1397
1398         if (signature->param_count > 9)
1399                 g_free (arg_info);
1400
1401
1402         for (i = 0; i < header->num_clauses; ++i) {
1403                 MonoExceptionClause *clause = &header->clauses [i];             
1404                 tbb = &cfg->bblocks [bcinfo [clause->handler_offset].block_id];
1405                 if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE ||
1406                     clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1407                         tbb->instack = mono_mempool_alloc (mp, sizeof (MBTree *));
1408                         tbb->indepth = 1;
1409                         tbb->instack [0] = t1 = mono_ctree_new_leaf (mp, MB_TERM_EXCEPTION);
1410                         t1->data.i = mono_allocate_excvar (cfg);
1411                         t1->svt = VAL_POINTER;
1412                         tbb->reached = 1;
1413                         if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
1414                                 tbb = &cfg->bblocks [bcinfo [clause->token_or_filter].block_id];
1415                                 g_assert (tbb);
1416                                 tbb->instack = mono_mempool_alloc (mp, sizeof (MBTree *));
1417                                 tbb->indepth = 1;
1418                                 tbb->instack [0] = t1 = mono_ctree_new_leaf (mp, MB_TERM_EXCEPTION);
1419                                 t1->data.i = mono_allocate_excvar (cfg);
1420                                 t1->svt = VAL_POINTER;
1421                                 tbb->reached = 1;
1422                         }
1423                 } else if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
1424                         mark_reached (cfg, tbb, NULL, 0);
1425                 } else {
1426                         g_warning ("implement me");
1427                         g_assert_not_reached ();
1428                 }
1429         }
1430
1431         repeat_count = 0;
1432
1433         do {
1434                 repeat = FALSE;
1435                 superblock_end = TRUE;
1436                 sp = stack;
1437
1438                 //printf ("START\n");
1439                 for (i = 0; i < cfg->block_count; i++) {
1440                         bb = &cfg->bblocks [i];
1441                         
1442                         //printf ("BBS %d %05x %05x %d %d %d %s\n", i, bb->cli_addr, bb->cli_addr + bb->length, bb->reached, bb->finished, superblock_end, method->name);
1443                         
1444                         if (!bb->reached && !superblock_end) {
1445                                 MonoBBlock *sbb = &cfg->bblocks [i - 1];
1446
1447                                 g_assert (sbb->outdepth == (sp - stack));
1448
1449                                 mark_reached (cfg, bb, sbb->outstack, sbb->outdepth);
1450                         } 
1451                         
1452                         if (bb->reached) {
1453
1454                                 if (!bb->finished) {
1455
1456                                         sp = stack;
1457
1458                                         for (j = 0; j < bb->indepth; j++) {
1459                                                 sp [j] = bb->instack [j];
1460                                         }
1461                                         sp += bb->indepth;
1462
1463                                         bb->finished = 1;
1464                                 
1465                                         ip = header->code + bb->cli_addr;
1466                                         end = ip + bb->length;
1467
1468                                         forest = bb->forest;
1469                                 
1470                                         superblock_end = FALSE;
1471
1472                                         tail_recursion = FALSE;
1473
1474         while (inline_list || ip < end) {
1475                 guint32 cli_addr;
1476
1477                 if (inline_list) {
1478                         MonoInlineInfo *ii = (MonoInlineInfo *)inline_list->data;
1479                         if (ip >= ii->end) {
1480                                 inline_list = g_list_remove_link (inline_list, inline_list);
1481                                 ip = ii->saved_ip;
1482                                 tail_recursion = FALSE;
1483                                 image = ii->saved_image;
1484                                 if (inline_list)
1485                                         arg_map = ((MonoInlineInfo *)inline_list->data)->arg_map;
1486                                 else 
1487                                         arg_map = NULL;
1488                                 continue;
1489                         }
1490                 } else 
1491                         cli_addr = ip - header->code;
1492
1493                 
1494                 //if (inline_list) printf ("INLINE IL%04x OPCODE %s\n", cli_addr, mono_opcode_names [*ip]);
1495
1496                 //printf ("%d IL%04x OPCODE %s %d %d %d\n", i, cli_addr, mono_opcode_names [*ip], 
1497                 //forest->len, superblock_end, sp - stack);
1498
1499                 switch (*ip) {
1500                         case CEE_THROW: {
1501                         --sp;
1502                         ip++;
1503                         
1504                         t1 = mono_ctree_new (mp, MB_TERM_THROW, *sp, NULL);
1505                         ADD_TREE (t1, cli_addr);                
1506                         superblock_end = TRUE;
1507                         break;
1508                 }
1509                 case CEE_BOX: {
1510                         MonoClass *c;
1511                         guint32 token;
1512                         
1513                         --sp;
1514                         ++ip;
1515                         token = read32 (ip);
1516                         ip += 4;
1517                         
1518                         if (method->wrapper_type != MONO_WRAPPER_NONE)
1519                                 c = (MonoClass *)mono_method_get_wrapper_data (method, token);
1520                         else
1521                                 c = mono_class_get (image, token);
1522                         
1523                         t1 = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ);
1524                         t1->data.p = c;
1525                         t1->svt = VAL_POINTER;
1526
1527                         t1 = mono_store_tree (cfg, -1, t1, &t3);
1528                         g_assert (t1);
1529                         ADD_TREE (t1, cli_addr);
1530
1531                         t1 = ctree_create_dup (mp, t3);
1532                         t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1533                         t2->data.i = sizeof (MonoObject);
1534                         t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);
1535
1536                         t1 = ctree_create_store (cfg, &c->byval_arg, t1, *sp, FALSE);
1537                         ADD_TREE (t1, cli_addr);
1538
1539                         PUSH_TREE (t3, VAL_POINTER);
1540
1541                         break;
1542                 }
1543                 case CEE_UNBOX: {
1544                         MonoClass *class;
1545                         guint32 token;
1546
1547                         ++ip;
1548                         token = read32 (ip);
1549                         ip += 4;
1550                         sp--;
1551
1552                         if (method->wrapper_type != MONO_WRAPPER_NONE)
1553                                 class = (MonoClass *)mono_method_get_wrapper_data (method, token);
1554                         else 
1555                                 class = mono_class_get (image, token);
1556
1557                         t1 = mono_ctree_new (mp, MB_TERM_UNBOX, *sp, NULL);
1558                         t1->data.klass = class;
1559
1560                         PUSH_TREE (t1, VAL_POINTER);
1561                         break;
1562                 }
1563                 case CEE_LDLEN: {
1564                         ip++;
1565                         sp--;
1566
1567                         t1 = mono_ctree_new (mp, MB_TERM_LDLEN, *sp, NULL);
1568                         PUSH_TREE (t1, VAL_I32);
1569                         break;
1570                 }
1571
1572                 case CEE_LDOBJ: {
1573                         guint32 token;
1574                         MonoClass *c;
1575
1576                         ++ip;
1577                         token = read32 (ip);
1578                         ip += 4;
1579                         sp--;
1580
1581                         if (method->wrapper_type != MONO_WRAPPER_NONE)
1582                                 c = (MonoClass *)mono_method_get_wrapper_data (method, token);
1583                         else
1584                                 c = mono_class_get (image, token);
1585                         g_assert (c->valuetype);
1586
1587                         t1 = ctree_create_load (cfg, &c->byval_arg, *sp, &svt, FALSE);
1588                         PUSH_TREE (t1, svt);
1589                         break;
1590                 }
1591                 case CEE_STOBJ: {
1592                         guint32 token;
1593                         MonoClass *c;
1594                         int size;
1595
1596                         ++ip;
1597                         token = read32 (ip);
1598                         ip += 4;
1599                         sp -= 2;
1600
1601                         c = mono_class_get (image, token);
1602                         g_assert (c->valuetype);
1603
1604                         size = mono_class_value_size (c, NULL);
1605                         
1606                         t1 = mono_ctree_new (mp, MB_TERM_STIND_OBJ, sp [0], sp [1]);
1607                         t1->data.i = size;
1608                         ADD_TREE (t1, cli_addr);
1609                         break;
1610                 }
1611                 case CEE_LDSTR: {
1612                         MonoObject *o;
1613                         guint32 ind;
1614
1615                         ++ip;
1616                         ind = mono_metadata_token_index (read32 (ip));
1617                         ip += 4;
1618
1619                         if (cfg->share_code) {
1620                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_LDSTR);
1621                                 t1->data.i = ind;
1622                         } else {
1623                                 o = (MonoObject *) mono_ldstr (cfg->domain, image, ind);
1624                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1625                                 t1->data.p = o;
1626                         }
1627
1628                         PUSH_TREE (t1, VAL_POINTER);
1629                         break;
1630                 }
1631                 case CEE_LDSFLD:
1632                 case CEE_LDSFLDA: {
1633                         MonoClass *klass;
1634                         MonoClassField *field;
1635                         guint32 token;
1636                         int load_addr = *ip == CEE_LDSFLDA;
1637
1638                         ++ip;
1639                         token = read32 (ip);
1640                         ip += 4;
1641
1642                         /* need to handle fieldrefs */
1643                         field = mono_field_from_token (image, token, &klass);
1644                         g_assert (field);                       
1645
1646                         if (cfg->share_code) {
1647                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1648                                 t1->data.i = field->offset;
1649                                 t1 = mono_ctree_new (mp, MB_TERM_LDSFLDA, t1, NULL);
1650                                 t1->data.klass = klass;
1651                         } else {
1652                                 MonoVTable *vt = mono_class_vtable (cfg->domain, klass);
1653                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
1654                                 t1->data.p = (char*)(vt->data) + field->offset;
1655                         }
1656                         
1657                         if (load_addr) {
1658                                 svt = VAL_POINTER;
1659                         } else {
1660                                 t1 = ctree_create_load (cfg, field->type, t1, &svt, FALSE);
1661                         }
1662
1663                         PUSH_TREE (t1, svt);
1664                         break;
1665                 }
1666                 case CEE_LDFLD:
1667                 case CEE_LDFLDA: {
1668                         MonoClass *klass;
1669                         MonoClassField *field;
1670                         guint32 token;
1671                         int load_addr = *ip == CEE_LDFLDA;
1672
1673                         ++ip;
1674                         token = read32 (ip);
1675                         ip += 4;
1676                         sp--;
1677
1678                         /* need to handle fieldrefs */
1679                         field = mono_field_from_token (image, token, &klass);
1680                         g_assert (field);
1681                         
1682                         if (klass->marshalbyref) {
1683                                 t1 = mono_ctree_new (mp, MB_TERM_REMOTE_LDFLDA, sp [0], NULL);
1684                                 t1->data.fi.klass = klass;
1685                                 t1->data.fi.field = field;
1686                         } else {
1687                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1688
1689                                 if (klass->valuetype)
1690                                         t1->data.i = field->offset - sizeof (MonoObject);
1691                                 else 
1692                                         t1->data.i = field->offset;
1693
1694                                 t1 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t1);
1695                         }
1696
1697                         if (!load_addr) 
1698                                 t1 = ctree_create_load (cfg, field->type, t1, &svt, FALSE);
1699                         else
1700                                 svt = VAL_POINTER;
1701
1702                         PUSH_TREE (t1, svt);
1703                         break;
1704                 }
1705                 case CEE_STSFLD: {
1706                         MonoClass *klass;
1707                         MonoClassField *field;
1708                         guint32 token;
1709
1710                         ++ip;
1711                         token = read32 (ip);
1712                         ip += 4;
1713                         --sp;
1714
1715                         /* need to handle fieldrefs */
1716                         field = mono_field_from_token (image, token, &klass);
1717                         g_assert (field);
1718
1719                         if (cfg->share_code) {
1720                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1721                                 t1->data.i = field->offset;
1722                                 t1 = mono_ctree_new (mp, MB_TERM_LDSFLDA, t1, NULL);
1723                                 t1->data.klass = klass;
1724                         } else {
1725                                 MonoVTable *vt = mono_class_vtable (cfg->domain, klass);
1726                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
1727                                 t1->data.p = (char*)(vt->data) + field->offset;
1728                         }
1729                         t1 = ctree_create_store (cfg, field->type, t1, *sp, FALSE);
1730
1731                         ADD_TREE (t1, cli_addr);
1732                         break;
1733                 }
1734                 case CEE_STFLD: {
1735                         MonoClass *klass;
1736                         MonoClassField *field;
1737                         guint32 token;
1738
1739                         ++ip;
1740                         token = read32 (ip);
1741                         ip += 4;
1742                         sp -= 2;
1743
1744                         /* need to handle fieldrefs */
1745                         field = mono_field_from_token (image, token, &klass);
1746                         g_assert (field);
1747
1748                         if (klass->marshalbyref) {
1749                                 t1 = mono_ctree_new (mp, mono_map_remote_stind_type (field->type), sp [0], sp [1]);
1750                                 t1->data.fi.klass = klass;
1751                                 t1->data.fi.field = field;
1752                         } else {
1753                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1754                                 t1->data.i = klass->valuetype ? field->offset - sizeof (MonoObject) : field->offset;
1755                                 t1 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t1);
1756                                 t1 = mono_ctree_new (mp, MB_TERM_CHECKTHIS, t1, NULL);
1757                                 t1 = ctree_create_store (cfg, field->type, t1, sp [1], FALSE);
1758                         }
1759
1760                         ADD_TREE (t1, cli_addr);
1761                         break;
1762                 }
1763                 case CEE_LDELEMA: {
1764                         MonoClass *class;
1765                         guint32 esize, token;
1766
1767                         ++ip;
1768                         token = read32 (ip);
1769                         ip += 4;
1770                         sp -= 2;
1771
1772                         class = mono_class_get (image, token);
1773
1774                         mono_class_init (class);
1775
1776                         esize = mono_class_array_element_size (class);
1777
1778                         t1 = mono_ctree_new (mp, MB_TERM_LDELEMA, sp [0], sp [1]);
1779                         t1->data.i = esize;
1780                         PUSH_TREE (t1, VAL_POINTER);
1781                         break;
1782                 }
1783                 case CEE_NOP: { 
1784                         ++ip;
1785                         break;
1786                 }
1787                 case CEE_BREAK: { 
1788                         ++ip;
1789                         t1 = mono_ctree_new_leaf (mp, MB_TERM_BREAK);
1790                         ADD_TREE (t1, cli_addr);
1791                         break;
1792                 } 
1793                 case CEE_SWITCH: {
1794                         guint32 k, n;
1795                         MonoBBlock **jt;
1796                         gint32 st, target;
1797
1798                         ++ip;
1799                         n = read32 (ip);
1800                         ip += 4;
1801                         --sp;
1802
1803                         t1 = mono_ctree_new (mp, MB_TERM_SWITCH, *sp, NULL);
1804                         jt = t1->data.p = mono_alloc_static (sizeof (gpointer) * (n + 2));
1805                         st = cli_addr + 5 + 4 * n;
1806                         
1807                         // hack: we store n at position 0
1808                         jt [0] = (MonoBBlock *)n;
1809
1810                         create_outstack (cfg, bb, stack, sp - stack);
1811
1812                         for (k = 1; k <= (n + 1); k++) {
1813                                 if (k > n)
1814                                         target = st;
1815                                 else {
1816                                         target = read32 (ip) + st;
1817                                         ip += 4;
1818                                 }
1819                                 g_assert (target >= 0 && target <= header->code_size);
1820                                 g_assert (bcinfo [target].is_block_start);
1821                                 tbb = &cfg->bblocks [bcinfo [target].block_id];
1822                                 mark_reached (cfg, tbb, stack, sp - stack);
1823                                 jt [k] = tbb; 
1824                         }
1825
1826                         ADD_TREE (t1, cli_addr);
1827                         break;
1828                 }
1829                 case CEE_LDTOKEN: {
1830                         gpointer handle;
1831                         MonoClass *handle_class;
1832                         MonoMethod *next_method;
1833
1834                         ++ip;
1835                         handle = mono_ldtoken (image, read32 (ip), &handle_class);
1836                         ip += 4;
1837
1838                         if (!cfg->share_code && (*ip == CEE_CALL) && (next_method = mono_get_method (image, read32 (ip+1), NULL)) &&
1839                                         (next_method->klass == mono_defaults.monotype_class->parent) &&
1840                                         (strcmp (next_method->name, "GetTypeFromHandle") == 0)) {
1841                                 MonoClass *tclass = mono_class_from_mono_type (handle);
1842                                 mono_class_init (tclass);
1843                                 ip += 5;
1844                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1845                                 t1->data.p = mono_type_get_object (cfg->domain, handle);
1846                         } else {
1847                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1848                                 t1->data.p = handle;
1849                         }
1850                         PUSH_TREE (t1, VAL_POINTER);
1851
1852                         break;
1853                 }
1854                 case CEE_NEWARR: {
1855                         MonoClass *class;
1856                         guint32 token;
1857
1858                         ip++;
1859                         --sp;
1860                         token = read32 (ip);
1861                         ip += 4;
1862
1863                         if (method->wrapper_type != MONO_WRAPPER_NONE)
1864                                 class = (MonoClass *)mono_method_get_wrapper_data (method, token);
1865                         else
1866                                 class = mono_class_get (image, token);
1867
1868                         if (cfg->share_code) {
1869                                 t1 = mono_ctree_new (mp, MB_TERM_NEWARR, *sp, NULL);
1870                                 t1->data.p = class;
1871                         }
1872                         else {
1873                                 MonoClass  *ac = mono_array_class_get (&class->byval_arg, 1);
1874                                 MonoVTable *vt = mono_class_vtable (cfg->domain, ac);
1875
1876                                 t1 = mono_ctree_new (mp, MB_TERM_NEWARR_SPEC, *sp, NULL);
1877                                 t1->data.p = vt;
1878                         }
1879
1880                         PUSH_TREE (t1, VAL_POINTER);
1881                         break;
1882                 }
1883                 case CEE_CPOBJ: {
1884                         MonoClass *class;
1885                         guint32 token;
1886
1887                         ++ip;
1888                         token = read32 (ip);
1889                         class = mono_class_get (image, token);
1890                         ip += 4;
1891                         sp -= 2;
1892
1893                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1894                         t1->data.i = mono_class_value_size (class, NULL);                       
1895                         t1 = mono_ctree_new (mp, MB_TERM_CPSRC, sp [1], t1);
1896                         t1 = mono_ctree_new (mp, MB_TERM_CPBLK, sp [0], t1);
1897                         ADD_TREE (t1, cli_addr);
1898                         
1899                         break;
1900                 }
1901                 case CEE_NEWOBJ: {
1902                         MonoMethodSignature *csig;
1903                         MonoMethod *cm;
1904                         MBTree *this = NULL;
1905                         guint32 token;
1906                         int k, frame_size;
1907                         int newarr = FALSE;
1908                         int newstr = FALSE;
1909
1910                         ++ip;
1911                         token = read32 (ip);
1912                         ip += 4;
1913
1914                         if (method->wrapper_type != MONO_WRAPPER_NONE)
1915                                 cm = mono_method_get_wrapper_data (method, token);
1916                         else
1917                                 cm = mono_get_method (image, token, NULL);
1918                         g_assert (cm);
1919                         g_assert (!strcmp (cm->name, ".ctor"));
1920                         
1921                         csig = cm->signature;
1922                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
1923                         g_assert (csig->hasthis);
1924                         
1925                         arg_sp = sp -= csig->param_count;
1926
1927                         if (!cm->klass->inited)
1928                                 mono_class_init (cm->klass);
1929
1930                         if (cm->klass->parent == mono_defaults.array_class) {
1931                                 newarr = TRUE;
1932                                 this = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1933                                 this->data.m = cm;
1934                         } else if (cm->string_ctor) {
1935                                 static MonoString *string_dummy = NULL; 
1936
1937                                 if (!string_dummy)
1938                                         string_dummy = mono_string_new_wrapper ("dummy");
1939
1940                                 newstr = TRUE;
1941                                 /* we just pass a dummy as this, it is not used */
1942                                 this = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1943                                 this->data.p = string_dummy;
1944                         } else {                                
1945                                 if (cm->klass->valuetype) {
1946                                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1947                                         t1->data.i = mono_class_value_size (cm->klass, NULL);
1948                                         this = mono_ctree_new (mp, MB_TERM_LOCALLOC, t1, NULL);
1949                                         this->data.i = TRUE;
1950                                 } else if (cfg->share_code) {
1951                                         this = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ);
1952                                         this->data.klass = cm->klass;
1953                                 } else {
1954                                         MonoVTable *vt = mono_class_vtable (cfg->domain, cm->klass);
1955                                         this = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ_SPEC);
1956                                         this->data.p = vt;
1957                                 }
1958
1959                                 this->svt = VAL_POINTER;
1960
1961                                 t1 = mono_store_tree (cfg, -1, this, &this);
1962                                 g_assert (t1);
1963                                 ADD_TREE (t1, cli_addr);
1964                         }
1965                                 
1966                         if (csig->param_count + 1 < 10)
1967                                 arg_info = default_arg_info;
1968                         else 
1969                                 arg_info = g_new (MonoJitArgumentInfo, csig->param_count + 1);
1970
1971                         frame_size = arch_get_argument_info (csig, csig->param_count, arg_info);
1972                                         
1973                         for (k = csig->param_count - 1; k >= 0; k--) {
1974                                 t1 = mono_ctree_new (mp, mono_map_arg_type (csig->params [k]), arg_sp [k], NULL);
1975                                 t1->data.arg_info = arg_info [k + 1];
1976                                 ADD_TREE (t1, cli_addr);
1977                         }
1978
1979                         if (newarr || newstr) {
1980
1981                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
1982                                 t2->data.nonvirt_info.method = cm;
1983                                 if (newarr) {
1984                                         t2->data.nonvirt_info.p = mono_array_new_va;
1985                                 } else {
1986                                         t2->data.nonvirt_info.p = arch_create_jit_trampoline (cm);
1987                                 }
1988
1989                                 t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
1990                                 t1->data.call_info.pad = arg_info [0].pad;
1991                                 t1->data.call_info.frame_size = frame_size;
1992                                 t1->svt = VAL_POINTER;
1993
1994                                 t1 = mono_store_tree (cfg, -1, t1, &t2);
1995                                 g_assert (t1);
1996                                 ADD_TREE (t1, cli_addr);
1997                                 PUSH_TREE (t2, t2->svt);
1998
1999                         } else {
2000
2001                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
2002                                 t2->data.nonvirt_info.p = arch_create_jit_trampoline (cm);
2003                                 t2->data.nonvirt_info.method = cm;
2004
2005                                 t1 = mono_ctree_new (mp, mono_map_call_type (csig->ret, &svt), this, t2);
2006                                 t1->data.call_info.pad = arg_info [0].pad;
2007                                 t1->data.call_info.frame_size = frame_size;
2008                                 t1->svt = svt;
2009
2010                                 ADD_TREE (t1, cli_addr);
2011
2012                                 t1 = ctree_create_dup (mp, this);       
2013                                 
2014                                 if (cm->klass->valuetype) {
2015                                         t2 = ctree_create_load (cfg, &cm->klass->byval_arg, t1, &svt, FALSE);
2016                                         PUSH_TREE (t2, svt);
2017                                 } else {
2018                                         PUSH_TREE (t1, t1->svt);
2019                                 }
2020                         }
2021
2022                         if (csig->param_count > 9)
2023                                 g_free (arg_info);
2024
2025                         break;
2026                 }
2027                 case CEE_CALLI: 
2028                 case CEE_CALL: 
2029                 case CEE_CALLVIRT: {
2030                         MonoMethodSignature *csig;
2031                         MonoMethod *cm;
2032                         MBTree *ftn, *this = NULL;
2033                         guint32 token;
2034                         int k, frame_size;
2035                         int virtual = *ip == CEE_CALLVIRT;
2036                         int calli = *ip == CEE_CALLI;
2037                         int array_rank = 0;
2038                         /* fixme: compute this value */
2039                         gboolean shared_to_unshared_call = FALSE;
2040                         int nargs, vtype_num = 0;
2041
2042                         ++ip;
2043                         token = read32 (ip);
2044                         ip += 4;
2045
2046                         tail_recursion = FALSE;
2047                                         
2048                         if (calli) {
2049                                 ftn = *(--sp);
2050                                 
2051                                 if (method->wrapper_type != MONO_WRAPPER_NONE)
2052                                         csig = (MonoMethodSignature *)mono_method_get_wrapper_data (method, token);
2053                                 else
2054                                         csig = mono_metadata_parse_signature (image, token);
2055       
2056                                 g_assert (csig);
2057                                 arg_sp = sp -= csig->param_count;
2058                         } else {
2059                                 cm = mono_get_method (image, token, NULL);
2060                                 g_assert (cm);
2061
2062                                 if (cm->klass == mono_defaults.math_class &&
2063                                     cm->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
2064
2065                                         if (!strcmp (cm->name, "Sin")) {
2066                                                 --sp;
2067                                                 t1 = mono_ctree_new (mp, MB_TERM_SIN, *sp, NULL);
2068                                                 PUSH_TREE (t1, VAL_DOUBLE);
2069                                                 break;
2070                                         } else if (!strcmp (cm->name, "Cos")) {
2071                                                 --sp;
2072                                                 t1 = mono_ctree_new (mp, MB_TERM_COS, *sp, NULL);
2073                                                 PUSH_TREE (t1, VAL_DOUBLE);
2074                                                 break;
2075                                         } else if (!strcmp (cm->name, "Sqrt")) {
2076                                                 --sp;
2077                                                 t1 = mono_ctree_new (mp, MB_TERM_SQRT, *sp, NULL);
2078                                                 PUSH_TREE (t1, VAL_DOUBLE);
2079                                                 break;
2080                                         }
2081                                 }
2082
2083                                 if (cm->string_ctor)
2084                                         g_assert_not_reached ();
2085
2086                                 arg_sp = sp -= cm->signature->param_count;
2087
2088                                 if ((cm->flags & METHOD_ATTRIBUTE_FINAL && 
2089                                      cm->klass != mono_defaults.object_class) ||
2090                                     !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
2091                                         virtual = 0;
2092                         }
2093
2094                         g_assert (sp >= stack);
2095
2096                         if (!calli && mono_jit_inline_code && !virtual && cm->inline_count != -1 &&
2097                             cm != method && (cm->inline_info || check_inlining (cm) >= 0)) {
2098                                 MonoInlineInfo *ii = alloca (sizeof (MonoInlineInfo));
2099                                 int args;
2100                                 GList *l;
2101
2102                                 /* avoid recursive inlining */
2103                                 for (l = inline_list; l; l = l->next) {
2104                                         if (((MonoInlineInfo *)l->data)->method == cm)
2105                                                 break;
2106                                 }
2107                                 
2108                                 if (!l) {
2109
2110                                         /* make sure runtime_init is called */
2111                                         mono_class_vtable (cfg->domain, cm->klass);
2112
2113                                         mono_jit_stats.inlined_methods++;
2114                                 
2115                                         if (cm->signature->hasthis)
2116                                                 sp--;
2117
2118                                         args = cm->signature->param_count + cm->signature->hasthis;
2119
2120                                         ii->method = cm;
2121                                         ii->saved_ip = ip;
2122                                         ii->saved_image = image;
2123                                         ii->arg_map = alloca (args * sizeof (MBTree *));
2124                                         memcpy (ii->arg_map, sp, args * sizeof (MBTree *));
2125
2126                                         if (cm->signature->hasthis && !cm->uses_this && 
2127                                             (ii->arg_map [0]->op != MB_TERM_CHECKTHIS)) {
2128                                                 ii->arg_map [0] = mono_ctree_new (mp, MB_TERM_CHECKTHIS, 
2129                                                                                   ii->arg_map [0], NULL);
2130                                                 ADD_TREE (ii->arg_map [0], ii->arg_map [0]->cli_addr);
2131                                         }
2132                                 
2133                                         if (cm->inline_count) {
2134                                                 inline_list = g_list_prepend (inline_list, ii);
2135                                                 ip = ((MonoMethodNormal *)cm)->header->code;
2136                                                 ii->end = ip + cm->inline_count;
2137                                                 arg_map = ii->arg_map;
2138                                                 image = cm->klass->image;
2139                                         }
2140                                         continue;
2141                                 }
2142                         }
2143                         
2144                         if (!calli) {
2145                                 MonoMethod *wrapper;
2146                                 if (cm->signature->pinvoke) {
2147 #ifdef MONO_USE_EXC_TABLES
2148                                         if (mono_method_blittable (cm)) {
2149                                                 csig = cm->signature;
2150                                         } else {
2151 #endif
2152                                                 wrapper = mono_marshal_get_native_wrapper (cm);
2153                                                 csig = wrapper->signature;
2154 #ifdef MONO_USE_EXC_TABLES
2155                                         }
2156 #endif
2157                                 } else {
2158                                         csig = cm->signature;
2159                                 }
2160                         }
2161                         nargs = csig->param_count;
2162
2163                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
2164                         g_assert (!virtual || csig->hasthis);
2165
2166                         if (!calli && cm->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
2167                                 if (cm->klass->parent == mono_defaults.array_class) {
2168                                         array_rank = cm->klass->rank;
2169                                      
2170                                         if (cm->name [0] == 'S') /* Set */ 
2171                                                 nargs--;
2172                                 }
2173                         }
2174
2175                         if (csig->param_count + 1 < 10)
2176                                 arg_info = default_arg_info;
2177                         else 
2178                                 arg_info = g_new (MonoJitArgumentInfo, csig->param_count + 1);
2179                         
2180                         frame_size = arch_get_argument_info (csig, nargs, arg_info);
2181
2182                         for (k = nargs - 1; k >= 0; k--) {
2183                                 g_assert (arg_sp [k]);
2184                                 t1 = mono_ctree_new (mp, mono_map_arg_type (csig->params [k]), arg_sp [k], NULL);
2185                                 t1->data.arg_info = arg_info [k + 1];
2186                                 ADD_TREE (t1, arg_sp [k]->cli_addr);
2187                         }
2188
2189                         if (csig->hasthis) 
2190                                 this = *(--sp);         
2191                         else
2192                                 this = mono_ctree_new_leaf (mp, MB_TERM_NOP);
2193                         
2194
2195                         if (MONO_TYPE_ISSTRUCT (csig->ret) && !array_rank) {
2196                                 int size, align;
2197                                 if (csig->pinvoke)
2198                                         size = mono_class_native_size (csig->ret->data.klass, &align);
2199                                 else
2200                                         size = mono_class_value_size (csig->ret->data.klass, &align);
2201
2202                                 vtype_num = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, VAL_UNKNOWN);
2203                         }
2204
2205                         if (array_rank) {
2206
2207                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2208                                 t2->data.p = ves_array_element_address;
2209                                
2210                                 t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
2211                                 t1->data.call_info.vtype_num = vtype_num;
2212                                 t1->data.call_info.frame_size = frame_size;
2213                                 t1->data.call_info.pad = arg_info [0].pad;
2214                                 t1->svt = VAL_POINTER;
2215
2216                                 t1 = mono_store_tree (cfg, -1, t1, &t2);
2217                                 g_assert (t1);
2218                                 ADD_TREE (t1, cli_addr);
2219
2220                                 if (cm->name [0] == 'G') { /* Get */
2221                                         t1 = mono_ctree_new (mp, mono_map_ldind_type (csig->ret, &svt), t2, NULL);
2222                                         t1->svt = svt;          
2223                                         PUSH_TREE (t1, t1->svt);
2224                                 } else if (cm->name [0] == 'S') { /* Set */
2225                                         t1 = ctree_create_store (cfg, csig->params [nargs], t2, arg_sp [nargs], FALSE);
2226                                         ADD_TREE (t1, cli_addr);                        
2227                                 } else if (cm->name [0] == 'A') { /* Address */
2228                                         PUSH_TREE (t2, t1->svt);
2229                                 } else {
2230                                         g_assert_not_reached ();
2231                                 }
2232
2233                         } else {
2234
2235                                 if (calli) {
2236                                         t2 = ftn; 
2237                                 } else if (virtual || (csig->hasthis && 
2238                                                        !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) &&
2239                                                        (cm->klass->marshalbyref || shared_to_unshared_call))) {
2240                                 
2241                                         mono_class_init (cm->klass);
2242
2243                                         if (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2244                                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_INTF_ADDR);
2245                                         else 
2246                                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_VFUNC_ADDR);
2247          
2248                                         t2->data.m = cm;
2249
2250                                 } else {
2251                                         t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
2252                                         t2->data.nonvirt_info.p = arch_create_jit_trampoline (cm);
2253                                         t2->data.nonvirt_info.method = cm;
2254                                 }
2255                
2256
2257                                 t1 = mono_ctree_new (mp, mono_map_call_type (csig->ret, &svt), this, t2);
2258                                 t1->data.call_info.vtype_num = vtype_num;
2259                                 t1->data.call_info.frame_size = frame_size;
2260                                 t1->data.call_info.pad = arg_info [0].pad;
2261                                 t1->svt = svt;
2262
2263                                 if (csig->ret->type != MONO_TYPE_VOID) {
2264
2265                                         if (vtype_num) {
2266                                                 ADD_TREE (t1, cli_addr);
2267                                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2268                                                 t1->data.i = vtype_num;
2269                                                 PUSH_TREE (t1, VAL_POINTER); 
2270                                         } else {
2271                                                 t1 = mono_store_tree (cfg, -1, t1, &t2);
2272                                                 g_assert (t1);
2273                                                 ADD_TREE (t1, cli_addr);
2274                                                 PUSH_TREE (t2, t2->svt);
2275                                         }
2276                                 } else
2277                                         ADD_TREE (t1, cli_addr);
2278                         }
2279
2280                         if (csig->param_count > 9)
2281                                 g_free (arg_info);
2282                         
2283                         break;
2284                 }
2285                 case CEE_ISINST: {
2286                         MonoClass *c;
2287                         guint32 token;
2288                         ++ip;
2289                         token = read32 (ip);
2290                         --sp;
2291
2292                         c = mono_class_get (image, token);
2293                         if (!c->inited)
2294                                 mono_class_init (c);
2295
2296                         t1 = mono_ctree_new (mp, MB_TERM_ISINST, *sp, NULL);
2297                         t1->data.klass = c;
2298                         
2299                         PUSH_TREE (t1, VAL_POINTER);
2300
2301                         ip += 4;
2302                         break;
2303                 }
2304                 case CEE_CASTCLASS: {
2305                         MonoClass *c;
2306                         guint32 token;
2307                         ++ip;
2308                         token = read32 (ip);
2309                         --sp;
2310
2311                         c = mono_class_get (image, token);
2312                         if (!c->inited)
2313                                 mono_class_init (c);
2314
2315                         t1 = mono_ctree_new (mp, MB_TERM_CASTCLASS, *sp, NULL);
2316                         t1->data.klass = c;
2317                         
2318                         PUSH_TREE (t1, VAL_POINTER);
2319
2320                         ip += 4;
2321                         break;
2322                 }
2323                 case CEE_LDC_I4_S: { 
2324                         ++ip;
2325                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2326                         t1->data.i = *(const gint8 *)ip;
2327                         ++ip;
2328                         PUSH_TREE (t1, VAL_I32);
2329                         break;
2330                 }
2331                 case CEE_LDC_I4: { 
2332                         ++ip;
2333                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2334                         t1->data.i = read32 (ip);
2335                         ip += 4;
2336                         PUSH_TREE (t1, VAL_I32);
2337                         break;
2338                 }
2339                 case CEE_LDC_I4_M1:
2340                 case CEE_LDC_I4_0:
2341                 case CEE_LDC_I4_1:
2342                 case CEE_LDC_I4_2:
2343                 case CEE_LDC_I4_3:
2344                 case CEE_LDC_I4_4:
2345                 case CEE_LDC_I4_5:
2346                 case CEE_LDC_I4_6:
2347                 case CEE_LDC_I4_7:
2348                 case CEE_LDC_I4_8: {
2349                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2350                         t1->data.i = (*ip) - CEE_LDC_I4_0;
2351                         ++ip;
2352                         PUSH_TREE (t1, VAL_I32);
2353                         break;
2354                 }
2355                 case CEE_LDNULL: {
2356                         //fixme: don't know if this is portable ?
2357                         ++ip;
2358                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2359                         t1->data.i = 0;
2360                         PUSH_TREE (t1, VAL_POINTER);
2361                         break;
2362                 }
2363                 case CEE_LDC_I8: {
2364                         ++ip;
2365                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I8);
2366                         t1->data.l = read64 (ip);
2367                         ip += 8;
2368                         PUSH_TREE (t1, VAL_I64);                
2369                         break;
2370                 }
2371                 case CEE_LDC_R4: {
2372                         float *f = mono_alloc_static (sizeof (float));
2373                         ++ip;
2374                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_R4);
2375                         readr4 (ip, f);
2376                         t1->data.p = f;
2377                         ip += 4;
2378                         PUSH_TREE (t1, VAL_DOUBLE);             
2379                         break;
2380                 }
2381                 case CEE_LDC_R8: { 
2382                         double *d = mono_alloc_static (sizeof (double));
2383                         ++ip;
2384                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_R8);
2385                         readr8 (ip, d);
2386                         t1->data.p = d;
2387                         ip += 8;
2388                         PUSH_TREE (t1, VAL_DOUBLE);             
2389                         break;
2390                 }
2391                 case CEE_LDLOC_0:
2392                 case CEE_LDLOC_1:
2393                 case CEE_LDLOC_2:
2394                 case CEE_LDLOC_3: {
2395                         int n = (*ip) - CEE_LDLOC_0;
2396                         ++ip;
2397
2398                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2399                         t1->data.i = LOCAL_POS (n);
2400                         if (!MONO_TYPE_ISSTRUCT (LOCAL_TYPE (n))) 
2401                                 t1 = ctree_create_load (cfg, LOCAL_TYPE (n), t1, &svt, FALSE);
2402                         PUSH_TREE (t1, svt);
2403                         break;
2404                 }
2405                 case CEE_LDLOC_S: {
2406                         ++ip;
2407                         
2408                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2409                         t1->data.i = LOCAL_POS (*ip);
2410                         if (!MONO_TYPE_ISSTRUCT (LOCAL_TYPE (*ip))) 
2411                                 t1 = ctree_create_load (cfg, LOCAL_TYPE (*ip), t1, &svt, FALSE);
2412                         ++ip;
2413
2414                         PUSH_TREE (t1, svt);
2415                         break;
2416                 }
2417                 case CEE_LDLOCA_S: {
2418                         ++ip;
2419
2420                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2421                         t1->data.i = LOCAL_POS (*ip);
2422                         VARINFO (cfg, t1->data.i).isvolatile = 1;
2423                         ++ip;
2424                         PUSH_TREE (t1, VAL_POINTER);                    
2425                         break;
2426                 }
2427                 case CEE_STLOC_0:
2428                 case CEE_STLOC_1:
2429                 case CEE_STLOC_2:
2430                 case CEE_STLOC_3: {
2431                         int n = (*ip) - CEE_STLOC_0;
2432                         ++ip;
2433                         --sp;
2434
2435                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2436                         t1->data.i = LOCAL_POS (n);
2437
2438                         if ((t2 = mono_stack_duplicate_used_var (cfg, stack, sp, t1->data.i)))
2439                                 ADD_TREE (t2, cli_addr); 
2440
2441                         t1 = ctree_create_store (cfg, LOCAL_TYPE (n), t1, *sp, FALSE);
2442                         ADD_TREE (t1, cli_addr);                        
2443                         break;
2444                 }
2445                 case CEE_STLOC_S: {
2446                         ++ip;
2447                         --sp;
2448
2449                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2450                         t1->data.i = LOCAL_POS (*ip);
2451                         if ((t2 = mono_stack_duplicate_used_var (cfg, stack, sp, t1->data.i)))
2452                                 ADD_TREE (t2, cli_addr); 
2453
2454                         t1 = ctree_create_store (cfg, LOCAL_TYPE (*ip), t1, *sp, FALSE);
2455                         ++ip;
2456                         ADD_TREE (t1, cli_addr);                        
2457                         break;
2458                 }
2459
2460                 case CEE_ADD: {
2461                         ++ip;
2462                         sp -= 2;
2463                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4)
2464                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i + sp [1]->data.i);
2465                         else
2466                                 t1 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], sp [1]);
2467                         PUSH_TREE (t1, sp [0]->svt);
2468                         break;                        
2469                 }
2470
2471                 case CEE_SUB: {
2472                         ++ip;
2473                         sp -= 2;
2474                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4)
2475                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i - sp [1]->data.i);
2476                         else
2477                                 t1 = mono_ctree_new (mp, MB_TERM_SUB, sp [0], sp [1]);
2478                         PUSH_TREE (t1, sp [0]->svt);
2479                         break;                        
2480                 }
2481
2482                 case CEE_AND: {
2483                         ++ip;
2484                         sp -= 2;
2485                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4)
2486                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i & sp [1]->data.i);
2487                         else
2488                                 t1 = mono_ctree_new (mp, MB_TERM_AND, sp [0], sp [1]);
2489                         PUSH_TREE (t1, sp [0]->svt);
2490                         break;                        
2491                 }
2492
2493                 case CEE_OR: {
2494                         ++ip;
2495                         sp -= 2;
2496                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4)
2497                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i | sp [1]->data.i);
2498                         else
2499                                 t1 = mono_ctree_new (mp, MB_TERM_OR, sp [0], sp [1]);
2500                         PUSH_TREE (t1, sp [0]->svt);
2501                         break;                        
2502                 }
2503
2504                 case CEE_XOR: {
2505                         ++ip;
2506                         sp -= 2;
2507                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4)
2508                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i ^ sp [1]->data.i);
2509                         else
2510                                 t1 = mono_ctree_new (mp, MB_TERM_XOR, sp [0], sp [1]);
2511                         PUSH_TREE (t1, sp [0]->svt);
2512                         break;                        
2513                 }
2514
2515                 case CEE_MUL: {
2516                         ++ip;
2517                         sp -= 2;
2518                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4) {
2519                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i * sp [1]->data.i);
2520                                 PUSH_TREE (t1, sp [0]->svt);
2521                         } else {
2522                                 MAKE_SPILLED_BI_ALU1 (MUL, sp [0], sp [1])
2523                         }
2524                         break;                        
2525                 }
2526
2527                 case CEE_DIV: {
2528                         ++ip;
2529                         sp -= 2;
2530                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4 
2531                             && (sp[1]->data.i != 0) 
2532                             && ((sp[0]->data.i != 0x080000000) || (sp[1]->data.i != -1))) {
2533                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i / sp [1]->data.i);
2534                                 PUSH_TREE (t1, sp [0]->svt);
2535                         } else {
2536                                 MAKE_SPILLED_BI_ALU1 (DIV, sp [0], sp [1])
2537                         }
2538                         break;                        
2539                 }
2540
2541                 case CEE_REM: {
2542                         ++ip;
2543                         sp -= 2;
2544                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4) {
2545                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i % sp [1]->data.i);
2546                                 PUSH_TREE (t1, sp [0]->svt);
2547                         } else {
2548                                 MAKE_SPILLED_BI_ALU1 (REM, sp [0], sp [1])
2549                         }
2550                         break;                        
2551                 }
2552
2553                 case CEE_SHL: {
2554                         ++ip;
2555                         sp -= 2;
2556                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4) {
2557                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i << sp [1]->data.i);
2558                                 PUSH_TREE (t1, sp [0]->svt);
2559                         } else {
2560                                 MAKE_SPILLED_BI_ALU1 (SHL, sp [0], sp [1])
2561                         }
2562                         break;                        
2563                 }
2564
2565                 case CEE_SHR: {
2566                         ++ip;
2567                         sp -= 2;
2568                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4) {
2569                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i >> sp [1]->data.i);
2570                                 PUSH_TREE (t1, sp [0]->svt);
2571                         } else {
2572                                 MAKE_SPILLED_BI_ALU1 (SHR, sp [0], sp [1])
2573                         }
2574                         break;                        
2575                 }
2576
2577                 MAKE_BI_ALU (ADD_OVF)
2578                 MAKE_BI_ALU (ADD_OVF_UN)
2579                 MAKE_BI_ALU (SUB_OVF)
2580                 MAKE_BI_ALU (SUB_OVF_UN)
2581                 MAKE_SPILLED_BI_ALU (SHR_UN)
2582                 MAKE_SPILLED_BI_ALU (MUL_OVF)
2583                 MAKE_SPILLED_BI_ALU (MUL_OVF_UN)
2584                 MAKE_SPILLED_BI_ALU (DIV_UN)
2585                 MAKE_SPILLED_BI_ALU (REM_UN)
2586
2587                 MAKE_LDIND (LDIND_I1,  MB_TERM_LDIND_I1, VAL_I32)
2588                 MAKE_LDIND (LDIND_U1,  MB_TERM_LDIND_U1, VAL_I32)
2589                 MAKE_LDIND (LDIND_I2,  MB_TERM_LDIND_I2, VAL_I32)
2590                 MAKE_LDIND (LDIND_U2,  MB_TERM_LDIND_U2, VAL_I32)
2591                 MAKE_LDIND (LDIND_I,   MB_TERM_LDIND_I4, VAL_I32)
2592                 MAKE_LDIND (LDIND_I4,  MB_TERM_LDIND_I4, VAL_I32)
2593                 MAKE_LDIND (LDIND_REF, MB_TERM_LDIND_REF, VAL_POINTER)
2594                 MAKE_LDIND (LDIND_U4,  MB_TERM_LDIND_U4, VAL_I32)
2595                 MAKE_LDIND (LDIND_I8,  MB_TERM_LDIND_I8, VAL_I64)
2596                 MAKE_LDIND (LDIND_R4,  MB_TERM_LDIND_R4, VAL_DOUBLE)
2597                 MAKE_LDIND (LDIND_R8,  MB_TERM_LDIND_R8, VAL_DOUBLE)
2598
2599                 MAKE_STIND (STIND_I1,  MB_TERM_STIND_I1)
2600                 MAKE_STIND (STIND_I2,  MB_TERM_STIND_I2)
2601                 MAKE_STIND (STIND_I,   MB_TERM_STIND_I4)
2602                 MAKE_STIND (STIND_I4,  MB_TERM_STIND_I4)
2603                 MAKE_STIND (STIND_I8,  MB_TERM_STIND_I8)
2604                 MAKE_STIND (STIND_R4,  MB_TERM_STIND_R4)
2605                 MAKE_STIND (STIND_R8,  MB_TERM_STIND_R8)
2606                 MAKE_STIND (STIND_REF, MB_TERM_STIND_REF)
2607
2608                 MAKE_LDELEM (LDELEM_I1,  MB_TERM_LDIND_I1, VAL_I32, 1)
2609                 MAKE_LDELEM (LDELEM_U1,  MB_TERM_LDIND_U1, VAL_I32, 1)
2610                 MAKE_LDELEM (LDELEM_I2,  MB_TERM_LDIND_I2, VAL_I32, 2)
2611                 MAKE_LDELEM (LDELEM_U2,  MB_TERM_LDIND_U2, VAL_I32, 2)
2612                 MAKE_LDELEM (LDELEM_I,   MB_TERM_LDIND_I4, VAL_I32, 4)
2613                 MAKE_LDELEM (LDELEM_I4,  MB_TERM_LDIND_I4, VAL_I32, 4)
2614                 MAKE_LDELEM (LDELEM_REF, MB_TERM_LDIND_REF, VAL_POINTER, sizeof (gpointer))
2615                 MAKE_LDELEM (LDELEM_U4,  MB_TERM_LDIND_U4, VAL_I32, 4)
2616                 MAKE_LDELEM (LDELEM_I8,  MB_TERM_LDIND_I8, VAL_I64, 8)
2617                 MAKE_LDELEM (LDELEM_R4,  MB_TERM_LDIND_R4, VAL_DOUBLE, 4)
2618                 MAKE_LDELEM (LDELEM_R8,  MB_TERM_LDIND_R8, VAL_DOUBLE, 8)
2619
2620                 MAKE_STELEM (STELEM_I1,  MB_TERM_STIND_I1, 1)
2621                 MAKE_STELEM (STELEM_I2,  MB_TERM_STIND_I2, 2)
2622                 MAKE_STELEM (STELEM_I4,  MB_TERM_STIND_I4, 4)
2623                 MAKE_STELEM (STELEM_I,   MB_TERM_STIND_I4, 4)
2624                 MAKE_STELEM (STELEM_REF, MB_TERM_STIND_REF, sizeof (gpointer))
2625                 MAKE_STELEM (STELEM_I8,  MB_TERM_STIND_I8, 8)
2626                 MAKE_STELEM (STELEM_R4,  MB_TERM_STIND_R4, 4)
2627                 MAKE_STELEM (STELEM_R8,  MB_TERM_STIND_R8, 8)
2628
2629                 case CEE_NEG: {
2630                         ip++;
2631                         sp--;
2632                         if (sp [0]->op == MB_TERM_CONST_I4)
2633                                 t1 = mono_ctree_new_icon4 (mp, -sp [0]->data.i);
2634                         else
2635                                 t1 = mono_ctree_new (mp, MB_TERM_NEG, sp [0], NULL);
2636                         PUSH_TREE (t1, sp [0]->svt);            
2637                         break;
2638                 }
2639                 case CEE_NOT: {
2640                         ip++;
2641                         sp--;
2642                         if (sp [0]->op == MB_TERM_CONST_I4)
2643                                 t1 = mono_ctree_new_icon4 (mp, ~sp [0]->data.i);
2644                         else
2645                                 t1 = mono_ctree_new (mp, MB_TERM_NOT, sp [0], NULL);
2646                         PUSH_TREE (t1, sp [0]->svt);
2647                         break;
2648                 }
2649                 case CEE_BR: 
2650                 case CEE_BR_S: {
2651                         gint32 target;
2652                         int br_s = (*ip == CEE_BR_S);
2653
2654                         ++ip;
2655                         if (br_s)
2656                                 target = cli_addr + 2 + (signed char) *ip;
2657                         else
2658                                 target = cli_addr + 5 + (gint32) read32(ip);
2659
2660                         g_assert (target >= 0 && target <= header->code_size);
2661                         g_assert (bcinfo [target].is_block_start);
2662                         tbb = &cfg->bblocks [bcinfo [target].block_id];
2663                         create_outstack (cfg, bb, stack, sp - stack);
2664                         mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
2665
2666                         t1 = mono_ctree_new_leaf (mp, MB_TERM_BR);
2667                         t1->data.p = tbb;
2668                         ADD_TREE (t1, cli_addr);
2669
2670                         if (br_s)
2671                                 ++ip;
2672                         else
2673                                 ip += 4;
2674
2675                         superblock_end = TRUE;
2676                         break;
2677                 }
2678                 case CEE_JMP: {
2679                         MonoMethod *cm;
2680                         guint32 token;
2681                         ++ip;
2682                         token = read32 (ip);
2683                         ip += 4;
2684
2685                         cm = mono_get_method (method->klass->image, token, NULL);
2686                         g_assert (cm);
2687
2688                         t1 = mono_ctree_new_leaf (mp, MB_TERM_JMP);
2689                         /* fixme: our magic trampoline code does not work in this case,
2690                          * so I need to compile the method immediately */
2691                         t1->data.p = mono_compile_method (cm);;
2692
2693                         ADD_TREE (t1, cli_addr);
2694                         break;
2695                 }
2696                 case CEE_LEAVE:
2697                 case CEE_LEAVE_S: {
2698                         gint32 target;
2699                         MonoBBlock *hb;
2700                         int leave_s = (*ip == CEE_LEAVE_S);
2701                         int k;
2702                         ++ip;
2703                         if (leave_s)
2704                                 target = cli_addr + 2 + (signed char) *ip;
2705                         else
2706                                 target = cli_addr + 5 + (gint32) read32(ip);
2707
2708                         g_assert (target >= 0 && target <= header->code_size);
2709                         g_assert (bcinfo [target].is_block_start);
2710                         tbb = &cfg->bblocks [bcinfo [target].block_id];
2711
2712                         /* empty the stack */
2713                         while (sp != stack) {
2714                                 sp--;
2715                                 t1 = mono_ctree_new (mp, MB_TERM_POP, *sp, NULL);
2716                                 ADD_TREE (t1, cli_addr);
2717                         }
2718
2719                         mark_reached (cfg, tbb, NULL, 0);
2720
2721                         /* fixme: fault handler */
2722
2723                         if ((hb = mono_find_final_block (cfg, cli_addr, target, MONO_EXCEPTION_CLAUSE_FINALLY))) {
2724                                 mark_reached (cfg, hb, NULL, 0);
2725                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_HANDLER);
2726                                 t1->data.p = hb;
2727                                 ADD_TREE (t1, cli_addr);
2728                         } 
2729
2730                         /* check if we leave a catch handler, if so we have to
2731                          * rethrow ThreadAbort exceptions */
2732                         for (k = 0; k < header->num_clauses; ++k) {
2733                                 MonoExceptionClause *clause = &header->clauses [k];
2734                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE &&
2735                                     MONO_OFFSET_IN_HANDLER (clause, cli_addr)) {
2736                                         t1 = mono_ctree_new_leaf (mp, MB_TERM_RETHROW_ABORT);
2737                                         t1->data.i = mono_allocate_excvar (cfg);
2738                                         ADD_TREE (t1, cli_addr);
2739                                         break;
2740                                 }
2741                         }
2742
2743                         t1 = mono_ctree_new_leaf (mp, MB_TERM_BR);
2744                         t1->data.p = tbb;
2745                         ADD_TREE (t1, cli_addr);
2746                         
2747                         if (leave_s)
2748                                 ++ip;
2749                         else
2750                                 ip += 4;
2751
2752                         superblock_end = TRUE;
2753                         break;
2754                 }
2755                 
2756
2757                 MAKE_CJUMP(BGT)
2758                 MAKE_CJUMP(BGT_UN)
2759                 MAKE_CJUMP(BLT)
2760                 MAKE_CJUMP(BLT_UN)
2761                 MAKE_CJUMP(BNE_UN)
2762                 MAKE_CJUMP(BEQ)
2763                 MAKE_CJUMP(BGE)
2764                 MAKE_CJUMP(BGE_UN)
2765                 MAKE_CJUMP(BLE)
2766                 MAKE_CJUMP(BLE_UN)
2767
2768                 case CEE_BRTRUE:
2769                 case CEE_BRTRUE_S: {
2770                         gint32 target;
2771                         int near_jump = *ip == CEE_BRTRUE_S;
2772                         ++ip;
2773                         --sp;
2774
2775                         t1 = mono_ctree_new (mp, MB_TERM_BRTRUE, sp [0], NULL);
2776
2777                         if (near_jump)
2778                                 target = cli_addr + 2 + (signed char) *ip;
2779                         else 
2780                                 target = cli_addr + 5 + (gint32) read32 (ip);
2781
2782                         g_assert (target >= 0 && target <= header->code_size);
2783                         g_assert (bcinfo [target].is_block_start);
2784                         tbb = &cfg->bblocks [bcinfo [target].block_id];
2785                         create_outstack (cfg, bb, stack, sp - stack);
2786                         mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
2787   
2788                         t1->data.p = tbb;
2789                         ip += near_jump ? 1: 4;
2790                         ADD_TREE (t1, cli_addr);
2791                         break;
2792                 }
2793                 case CEE_BRFALSE:
2794                 case CEE_BRFALSE_S: {
2795                         gint32 target;
2796                         int near_jump = *ip == CEE_BRFALSE_S;
2797                         ++ip;
2798                         --sp;
2799
2800                         t1 = mono_ctree_new (mp, MB_TERM_BRFALSE, sp [0], NULL);
2801
2802                         if (near_jump)
2803                                 target = cli_addr + 2 + (signed char) *ip;
2804                         else 
2805                                 target = cli_addr + 5 + (gint32) read32 (ip);
2806
2807                         g_assert (target >= 0 && target <= header->code_size);
2808                         g_assert (bcinfo [target].is_block_start);
2809                         tbb = &cfg->bblocks [bcinfo [target].block_id];
2810                         create_outstack (cfg, bb, stack, sp - stack);
2811                         mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
2812                     
2813                         t1->data.p = tbb;
2814                         ip += near_jump ? 1: 4;
2815                         ADD_TREE (t1, cli_addr);
2816                         break;
2817                 }
2818                 case CEE_RET: {
2819                         MonoType *ret = signature->ret;
2820
2821                         ip++;
2822
2823                         if (ret->type != MONO_TYPE_VOID) {
2824                                 --sp;
2825                                 if (MONO_TYPE_ISSTRUCT (ret)) {
2826                                         int align;
2827                                         t1 = mono_ctree_new (mp, MB_TERM_RET_OBJ, *sp, NULL);
2828                                         t1->data.i = mono_class_value_size (ret->data.klass, &align);
2829                                 } else {
2830                                         t1 = mono_ctree_new (mp, MB_TERM_RET, *sp, NULL);
2831                                 }
2832                         } else {
2833                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_RET_VOID);
2834                         }
2835
2836                         t1->last_instr = (ip == (header->code + header->code_size));
2837
2838                         ADD_TREE (t1, cli_addr);
2839
2840                         if (sp > stack) {
2841                                 g_warning ("more values on stack at %s IL_%04x: %d",  
2842                                            mono_method_full_name (method, TRUE), 
2843                                            ip - header->code, sp - stack);
2844                                 mono_print_ctree (cfg, sp [-1]);
2845                                 printf ("\n");
2846                         }
2847                         superblock_end = TRUE;
2848                         break;
2849                 }
2850                 case CEE_ENDFINALLY: {
2851                         ip++;
2852
2853                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ENDFINALLY);
2854                         ADD_TREE (t1, cli_addr);
2855                         t1->last_instr = FALSE;
2856
2857                         g_assert (sp == stack);
2858                         superblock_end = TRUE;
2859                         break;
2860                 }
2861                 case CEE_LDARG_0:
2862                 case CEE_LDARG_1:
2863                 case CEE_LDARG_2:
2864                 case CEE_LDARG_3: {
2865                         int n = (*ip) - CEE_LDARG_0;
2866                         ++ip;
2867
2868                         if (arg_map) {
2869                                 *sp = arg_map [n];
2870                                 sp++;
2871                         } else {
2872                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2873                                 t1->data.i = ARG_POS (n);
2874                                 if (!MONO_TYPE_ISSTRUCT (ARG_TYPE (n))) 
2875                                         t1 = ctree_create_load (cfg, ARG_TYPE (n), t1, &svt, TRUE);
2876                         
2877                                 PUSH_TREE (t1, svt);
2878                         }
2879
2880                         break;
2881                 }
2882                 case CEE_LDARG_S: {
2883                         ++ip;
2884
2885                         if (arg_map) {
2886                                 *sp = arg_map [*ip];
2887                                 sp++;
2888                         } else {
2889                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2890                                 t1->data.i = ARG_POS (*ip);
2891                                 if (!MONO_TYPE_ISSTRUCT (ARG_TYPE (*ip))) 
2892                                         t1 = ctree_create_load (cfg, ARG_TYPE (*ip), t1, &svt, TRUE);
2893                                 PUSH_TREE (t1, svt);
2894                         }
2895                         ++ip;
2896                         break;
2897                 }
2898                 case CEE_LDARGA_S: {
2899                         ++ip;
2900                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2901                         t1->data.i = ARG_POS (*ip);
2902                         PUSH_TREE (t1, VAL_POINTER);
2903                         ++ip;
2904                         break;
2905                 }
2906                 case CEE_STARG_S: {
2907                         ++ip;
2908                         --sp;
2909
2910                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2911                         t1->data.i = ARG_POS (*ip);
2912                         t1 = ctree_create_store (cfg, ARG_TYPE (*ip), t1, *sp, TRUE);
2913                         ++ip;
2914                         ADD_TREE (t1, cli_addr);                        
2915                         break;
2916                 }
2917                 case CEE_DUP: {
2918                         int vnum;
2919
2920                         ++ip; 
2921
2922                         /* fixme: maybe we should add more of these optimisations */
2923                         if (sp [-1]->op == MB_TERM_CONST_I4) {
2924
2925                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2926                                 t1->data.i = sp [-1]->data.i;
2927                                 PUSH_TREE (t1, VAL_I32);
2928                               
2929                         } else {
2930                                 sp--;
2931
2932                                 vnum = mono_allocate_intvar (cfg, sp - stack, sp [0]->svt);
2933                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2934                                 t1->data.i = vnum;
2935                        
2936                                 t2 = mono_ctree_new (mp, mono_map_store_svt_type (sp [0]->svt), t1, sp [0]);
2937                                 t2->svt = sp [0]->svt;
2938                                 ADD_TREE (t2, cli_addr);
2939
2940                                 t1 = ctree_create_dup (mp, t2);         
2941                                 PUSH_TREE (t1, t1->svt);
2942                                 t1 = ctree_create_dup (mp, t1);         
2943                                 PUSH_TREE (t1, t1->svt);
2944                         }
2945                         break;
2946                 }
2947                 case CEE_POP: {
2948                         ++ip;
2949                         --sp;
2950
2951                         t1 = mono_ctree_new (mp, MB_TERM_POP, *sp, NULL);
2952                         ADD_TREE (t1, cli_addr);
2953
2954                         break;
2955                 }
2956                 case CEE_CKFINITE: {
2957                         int vnum;
2958                         ++ip;
2959                         sp--;
2960
2961                         /* this instr. can throw exceptions as side effect,
2962                          * so we cant eliminate dead code which contains CKFINITE opdodes.
2963                          * Spilling to memory makes sure that we always perform
2964                          * this check */
2965                         vnum = mono_allocate_intvar (cfg, sp - stack, sp [0]->svt);
2966                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2967                         t1->data.i = vnum;
2968                        
2969                         t2 = mono_ctree_new (mp, MB_TERM_CKFINITE, *sp, NULL);
2970
2971                         t2 = mono_ctree_new (mp, mono_map_store_svt_type (sp [0]->svt), t1, t2);
2972                         t2->svt = sp [0]->svt;
2973                         ADD_TREE (t2, cli_addr);
2974
2975                         t1 = ctree_create_dup (mp, t2);         
2976                         PUSH_TREE (t1, t1->svt);
2977                         break;
2978                 }
2979                 case CEE_CONV_U1: 
2980                         ++ip;
2981                         sp--;
2982                         if (sp [0]->op == MB_TERM_CONST_I4)
2983                                 t1 = mono_ctree_new_icon4 (mp, (guint8)sp [0]->data.i);
2984                         else
2985                                 t1 = mono_ctree_new (mp, MB_TERM_CONV_U1, *sp, NULL);
2986                         PUSH_TREE (t1, VAL_I32);                
2987                         break;
2988                 case CEE_CONV_I1:
2989                         ++ip;
2990                         sp--;
2991                         if (sp [0]->op == MB_TERM_CONST_I4)
2992                                 t1 = mono_ctree_new_icon4 (mp, (gint8)sp [0]->data.i);
2993                         else
2994                                 t1 = mono_ctree_new (mp, MB_TERM_CONV_I1, *sp, NULL);
2995                         PUSH_TREE (t1, VAL_I32);                
2996                         break;
2997                 case CEE_CONV_U2: 
2998                         ++ip;
2999                         sp--;
3000                         if (sp [0]->op == MB_TERM_CONST_I4)
3001                                 t1 = mono_ctree_new_icon4 (mp, (guint16)sp [0]->data.i);
3002                         else
3003                                 t1 = mono_ctree_new (mp, MB_TERM_CONV_U2, *sp, NULL);
3004                         PUSH_TREE (t1, VAL_I32);                
3005                         break;
3006                 case CEE_CONV_I2:
3007                         ++ip;
3008                         sp--;
3009                         if (sp [0]->op == MB_TERM_CONST_I4)
3010                                 t1 = mono_ctree_new_icon4 (mp, (gint16)sp [0]->data.i);
3011                         else
3012                                 t1 = mono_ctree_new (mp, MB_TERM_CONV_I2, *sp, NULL);
3013                         PUSH_TREE (t1, VAL_I32);                
3014                         break;
3015                 case CEE_CONV_I: 
3016                 case CEE_CONV_I4:
3017                         ++ip;
3018                         sp--;
3019                         if (sp [0]->op == MB_TERM_CONST_I4)
3020                                 t1 = *sp;
3021                         else
3022                                 t1 = mono_ctree_new (mp, MB_TERM_CONV_I4, *sp, NULL);
3023                         PUSH_TREE (t1, VAL_I32);                
3024                         break;
3025                 case CEE_CONV_U: 
3026                 case CEE_CONV_U4: 
3027                         ++ip;
3028                         sp--;
3029                         if (sp [0]->op == MB_TERM_CONST_I4)
3030                                 t1 = *sp;
3031                         else
3032                                 t1 = mono_ctree_new (mp, MB_TERM_CONV_U4, *sp, NULL);
3033                         PUSH_TREE (t1, VAL_I32);                
3034                         break;
3035                 case CEE_CONV_I8:
3036                         ++ip;
3037                         sp--;
3038                         t1 = mono_ctree_new (mp, MB_TERM_CONV_I8, *sp, NULL);
3039                         PUSH_TREE (t1, VAL_I64);                
3040                         break;
3041                 case CEE_CONV_U8:
3042                         ++ip;
3043                         sp--;
3044                         t1 = mono_ctree_new (mp, MB_TERM_CONV_U8, *sp, NULL);
3045                         PUSH_TREE (t1, VAL_I64);                
3046                         break;
3047                 case CEE_CONV_R8:
3048                         ++ip;
3049                         sp--;
3050                         t1 = mono_ctree_new (mp, MB_TERM_CONV_R8, *sp, NULL);
3051                         PUSH_TREE (t1, VAL_DOUBLE);             
3052                         break;
3053                 case CEE_CONV_R4:
3054                         ++ip;
3055                         sp--;
3056                         t1 = mono_ctree_new (mp, MB_TERM_CONV_R4, *sp, NULL);
3057                         PUSH_TREE (t1, VAL_DOUBLE);             
3058                         break;
3059                 case CEE_CONV_R_UN:
3060                         ++ip;
3061                         sp--;
3062                         t1 = mono_ctree_new (mp, MB_TERM_CONV_R_UN, *sp, NULL);
3063                         PUSH_TREE (t1, VAL_DOUBLE);             
3064                         break;
3065                 case CEE_CONV_OVF_I:
3066                 case CEE_CONV_OVF_I4:
3067                         ++ip;
3068                         sp--;
3069                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I4, *sp, NULL);
3070                         PUSH_TREE (t1, VAL_I32);
3071                         break;
3072                 case CEE_CONV_OVF_I_UN:
3073                 case CEE_CONV_OVF_I4_UN:
3074                         ++ip;
3075                         sp--;
3076                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I4_UN, *sp, NULL);
3077                         PUSH_TREE (t1, VAL_I32);                
3078                         break;
3079                 case CEE_CONV_OVF_U:
3080                 case CEE_CONV_OVF_U4:
3081                         ++ip;
3082                         sp--;
3083                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U4, *sp, NULL);
3084                         PUSH_TREE (t1, VAL_I32);                
3085                         break;
3086                 case CEE_CONV_OVF_I1:
3087                         ++ip;
3088                         sp--;
3089                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I1, *sp, NULL);
3090                         PUSH_TREE (t1, VAL_I32);
3091                         break;
3092                 case CEE_CONV_OVF_I1_UN:
3093                         ++ip;
3094                         sp--;
3095                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I1_UN, *sp, NULL);
3096                         PUSH_TREE (t1, VAL_I32);
3097                         break;
3098                 case CEE_CONV_OVF_U1_UN:
3099                         ++ip;
3100                         sp--;
3101                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U1_UN, *sp, NULL);
3102                         PUSH_TREE (t1, VAL_I32);
3103                         break;
3104                 case CEE_CONV_OVF_U1:
3105                         ++ip;
3106                         sp--;
3107                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U1, *sp, NULL);
3108                         PUSH_TREE (t1, VAL_I32);
3109                         break;
3110                 case CEE_CONV_OVF_I2:
3111                         ++ip;
3112                         sp--;
3113                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I2, *sp, NULL);
3114                         PUSH_TREE (t1, VAL_I32);
3115                         break;
3116                 case CEE_CONV_OVF_U2_UN:
3117                         ++ip;
3118                         sp--;
3119                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U2_UN, *sp, NULL);
3120                         PUSH_TREE (t1, VAL_I32);
3121                         break;
3122                 case CEE_CONV_OVF_U2:
3123                         ++ip;
3124                         sp--;
3125                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U2, *sp, NULL);
3126                         PUSH_TREE (t1, VAL_I32);
3127                         break;
3128                 case CEE_CONV_OVF_I2_UN:
3129                         ++ip;
3130                         sp--;
3131                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I2_UN, *sp, NULL);
3132                         PUSH_TREE (t1, VAL_I32);
3133                         break;
3134                 case CEE_CONV_OVF_U8:
3135                         ++ip;
3136                         sp--;
3137                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U8, *sp, NULL);
3138                         PUSH_TREE (t1, VAL_I32);
3139                         break;
3140                 case CEE_CONV_OVF_U_UN:
3141                 case CEE_CONV_OVF_U4_UN:
3142                         // fixme: raise exceptions ?
3143                         ++ip;
3144                         sp--;
3145                         t1 = mono_ctree_new (mp, MB_TERM_CONV_I4, *sp, NULL);
3146                         PUSH_TREE (t1, VAL_I32);                
3147                         break;
3148                 case CEE_CONV_OVF_I8_UN:
3149                 case CEE_CONV_OVF_U8_UN: /* FIXME: slightly incorrect, but non worth fixing the corner cases in the old jit */
3150                         ++ip;
3151                         sp--;
3152                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I8_UN, *sp, NULL);
3153                         PUSH_TREE (t1, VAL_I64);
3154                         break;
3155                 case MONO_CUSTOM_PREFIX: {
3156                         ++ip;                   
3157                         switch (*ip) {
3158                                 
3159                         case CEE_MONO_FUNC1: {
3160                                 MonoMarshalConv conv;
3161                                 ++ip;
3162
3163                                 conv = *ip;
3164
3165                                 ++ip;
3166
3167                                 sp--;
3168                                 t1 = mono_ctree_new (mp, MB_TERM_FUNC1, *sp, NULL);
3169
3170                                 switch (conv) {
3171                                 case MONO_MARSHAL_CONV_STR_LPWSTR:
3172                                         t1->data.p = mono_string_to_utf16;
3173                                         break;
3174                                 case MONO_MARSHAL_CONV_LPWSTR_STR:
3175                                         t1->data.p = mono_string_from_utf16;
3176                                         break;
3177                                 case MONO_MARSHAL_CONV_LPSTR_STR:
3178                                         t1->data.p = mono_string_new_wrapper;
3179                                         break;
3180                                 case MONO_MARSHAL_CONV_STR_LPTSTR:
3181                                 case MONO_MARSHAL_CONV_STR_LPSTR:
3182                                         t1->data.p = mono_string_to_utf8;
3183                                         break;
3184                                 case MONO_MARSHAL_CONV_STR_BSTR:
3185                                         t1->data.p = mono_string_to_bstr;
3186                                         break;
3187                                 case MONO_MARSHAL_CONV_STR_TBSTR:
3188                                 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
3189                                         t1->data.p = mono_string_to_ansibstr;
3190                                         break;
3191                                 case MONO_MARSHAL_CONV_SB_LPSTR:
3192                                         t1->data.p = mono_string_builder_to_utf8;
3193                                         break;
3194                                 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
3195                                         t1->data.p = mono_array_to_savearray;
3196                                         break;
3197                                 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
3198                                         t1->data.p = mono_array_to_lparray;
3199                                         break;
3200                                 case MONO_MARSHAL_CONV_DEL_FTN:
3201                                         t1->data.p = mono_delegate_to_ftnptr;
3202                                         break;
3203                                 case MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY:
3204                                         t1->data.p = mono_marshal_string_array;
3205                                         break;
3206                                 default:
3207                                         g_assert_not_reached ();
3208                                 }
3209                                 PUSH_TREE (t1, VAL_POINTER); 
3210                                 break;
3211                         }
3212                         case CEE_MONO_PROC2: {
3213                                 MonoMarshalConv conv;
3214                                 ++ip;
3215                                 conv = *ip;
3216                                 ++ip;
3217
3218                                 sp -= 2;
3219                                 t1 = mono_ctree_new (mp, MB_TERM_PROC2, sp [0], sp [1]);
3220
3221                                 switch (conv) {
3222                                 case MONO_MARSHAL_CONV_LPSTR_SB:
3223                                         t1->data.p = mono_string_utf8_to_builder;
3224                                         break;
3225                                 case MONO_MARSHAL_FREE_ARRAY:
3226                                         t1->data.p = mono_marshal_free_array;
3227                                         break;
3228                                 default:
3229                                         g_assert_not_reached ();
3230                                 }
3231                                 ADD_TREE (t1, cli_addr); 
3232                                 break;
3233                         }
3234                         case CEE_MONO_PROC3: {
3235                                 MonoMarshalConv conv;
3236                                 ++ip;
3237                                 conv = *ip;
3238                                 ++ip;
3239
3240                                 sp -= 3;
3241
3242                                 t1 = mono_ctree_new (mp, MB_TERM_CPSRC, sp [1], sp [2]);
3243                                 t1 = mono_ctree_new (mp, MB_TERM_PROC3, sp [0], t1);
3244
3245                                 switch (conv) {
3246                                 case MONO_MARSHAL_CONV_STR_BYVALSTR:
3247                                         t1->data.p = mono_string_to_byvalstr;
3248                                         break;
3249                                 case MONO_MARSHAL_CONV_STR_BYVALWSTR:
3250                                         t1->data.p = mono_string_to_byvalwstr;
3251                                         break;
3252                                 default:
3253                                         g_assert_not_reached ();
3254                                 }
3255
3256                                 ADD_TREE (t1, cli_addr);
3257                                 break;
3258                         }
3259                         case CEE_MONO_LDNATIVEOBJ: {
3260                                 guint32 token;
3261                                 MonoClass *c;
3262
3263                                 ++ip;
3264                                 token = read32 (ip);
3265                                 ip += 4;
3266                                 sp--;
3267
3268                                 g_assert (method->wrapper_type != MONO_WRAPPER_NONE);
3269                                 c = (MonoClass *)mono_method_get_wrapper_data (method, token);
3270                                 g_assert (c->valuetype);
3271                                 
3272                                 t1 = ctree_create_load (cfg, &c->byval_arg, *sp, &svt, FALSE);
3273                                 PUSH_TREE (t1, svt);
3274                                 break;
3275                         }
3276                         case CEE_MONO_FREE: {
3277                                 ++ip;
3278
3279                                 sp -= 1;
3280                                 t1 = mono_ctree_new (mp, MB_TERM_FREE, *sp, NULL);
3281                                 ADD_TREE (t1, cli_addr);
3282                                 break;
3283                         }
3284                         case CEE_MONO_OBJADDR: {
3285                                 ++ip;
3286
3287                                 sp -= 1;
3288                                 t1 = mono_ctree_new (mp, MB_TERM_OBJADDR, *sp, NULL);
3289                                 PUSH_TREE (t1, VAL_POINTER);
3290                                 break;
3291                         }
3292                         case CEE_MONO_VTADDR: {
3293                                 ++ip;
3294
3295                                 sp -= 1;
3296                                 t1 = mono_ctree_new (mp, MB_TERM_VTADDR, *sp, NULL);
3297                                 PUSH_TREE (t1, VAL_POINTER);
3298                                 break;
3299                         }
3300                         case CEE_MONO_LDPTR: {
3301                                 guint32 token;
3302                                 ++ip;
3303                                 
3304                                 token = read32 (ip);
3305                                 ip += 4;
3306                                 
3307                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
3308                                 t1->data.p = mono_method_get_wrapper_data (method, token);
3309                                 
3310                                 PUSH_TREE (t1, VAL_POINTER);
3311                                 break;
3312                         }
3313                         case CEE_MONO_NEWOBJ: {
3314                                 MonoClass *class;
3315                                 guint32 token;
3316
3317                                 ++ip;
3318                                 token = read32 (ip);
3319                                 ip += 4;
3320
3321                                 class = (MonoClass *)mono_method_get_wrapper_data (method, token);
3322
3323                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ);
3324                                 t1->data.p = class;
3325                                 PUSH_TREE (t1, VAL_POINTER);
3326
3327                                 break;
3328                         }
3329                         case CEE_MONO_RETOBJ: {
3330                                 MonoType *ret = signature->ret;
3331                                 MonoClass *class;
3332                                 guint32 token;
3333
3334                                 ++ip;
3335                                 token = read32 (ip);
3336                                 ip += 4;
3337
3338                                 class = (MonoClass *)mono_method_get_wrapper_data (method, token);
3339
3340                                 sp--;
3341
3342                                 g_assert (MONO_TYPE_ISSTRUCT (ret));
3343
3344                                 t1 = ctree_create_load (cfg, &class->byval_arg, *sp, &svt, FALSE);
3345                                 t1 = mono_ctree_new (mp, MB_TERM_RET_OBJ, t1, NULL);
3346                                 t1->data.i = mono_class_native_size (ret->data.klass, NULL);
3347                                 t1->last_instr = (ip == (header->code + header->code_size));
3348
3349                                 ADD_TREE (t1, cli_addr);
3350
3351                                 if (sp > stack) {
3352                                         g_warning ("more values on stack at %s IL_%04x: %d",  
3353                                                    mono_method_full_name (method, TRUE), 
3354                                                    ip - header->code, sp - stack);
3355                                         mono_print_ctree (cfg, sp [-1]);
3356                                         printf ("\n");
3357                                 }
3358                                 superblock_end = TRUE;
3359                                 break;
3360                         }
3361                         default:
3362                                 g_error ("Unimplemented opcode at IL_%04x "
3363                                          "%02x %02x", ip - header->code, MONO_CUSTOM_PREFIX, *ip);
3364                         }
3365                         break;
3366                 }
3367                 case CEE_PREFIX1: {
3368                         ++ip;                   
3369                         switch (*ip) {
3370                                 
3371                         case CEE_ENDFILTER: {
3372                                 ip++;
3373                                 
3374                                 sp--;
3375                                 t1 = mono_ctree_new (mp, MB_TERM_ENDFILTER, *sp, NULL);
3376                                 ADD_TREE (t1, cli_addr);
3377                                 t1->last_instr = FALSE;
3378                                 
3379                                 g_assert (sp == stack);
3380                                 superblock_end = TRUE;
3381                                 break;
3382                         }
3383
3384                         case CEE_LDLOC: {
3385                                 int n;
3386                                 ++ip;
3387                                 n = read16 (ip);
3388
3389                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
3390                                 t1->data.i = LOCAL_POS (n);
3391                                 if (!MONO_TYPE_ISSTRUCT (LOCAL_TYPE (n))) 
3392                                         t1 = ctree_create_load (cfg, LOCAL_TYPE (n), t1, &svt, FALSE);
3393                                 ip += 2;
3394
3395                                 PUSH_TREE (t1, svt);
3396                                 break;
3397                         }
3398                         case CEE_LDLOCA: {
3399                                 ++ip;
3400
3401                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
3402                                 t1->data.i = LOCAL_POS (read16 (ip));
3403                                 VARINFO (cfg, t1->data.i).isvolatile = 1;
3404                                 ip += 2;
3405                                 PUSH_TREE (t1, VAL_POINTER);                    
3406                                 break;
3407                         }
3408                         case CEE_STLOC: {
3409                                 ++ip;
3410                                 --sp;
3411
3412                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
3413                                 t1->data.i = LOCAL_POS (read16 (ip));
3414                                 if ((t2 = mono_stack_duplicate_used_var (cfg, stack, sp, t1->data.i)))
3415                                         ADD_TREE (t2, cli_addr); 
3416
3417                                 t1 = ctree_create_store (cfg, LOCAL_TYPE (read16 (ip)), t1, *sp, FALSE);
3418                                 ip += 2;
3419                                 ADD_TREE (t1, cli_addr);                        
3420                                 break;
3421                         }
3422                         case CEE_STARG: {
3423                                 guint32 arg_pos;
3424                                 ++ip;
3425                                 --sp;
3426
3427                                 arg_pos = read16 (ip);
3428                                 ip += 2;
3429
3430                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
3431                                 t1->data.i = ARG_POS (arg_pos);
3432                                 t1 = ctree_create_store (cfg, ARG_TYPE (arg_pos), t1, *sp, TRUE);
3433                                 ADD_TREE (t1, cli_addr);                        
3434                                 break;
3435                         }
3436
3437                         MAKE_CMP (CEQ)
3438                         MAKE_CMP (CLT)
3439                         MAKE_CMP (CLT_UN)
3440                         MAKE_CMP (CGT)
3441                         MAKE_CMP (CGT_UN)
3442
3443                         case CEE_RETHROW: {
3444                                 ++ip;
3445                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_RETHROW);
3446                                 t1->data.i = mono_allocate_excvar (cfg);
3447                                 ADD_TREE (t1, cli_addr);
3448                                 break;
3449                         }
3450                         case CEE_LDFTN: {
3451                                 MonoMethod *cm;
3452                                 guint32 token;
3453                                 ++ip;
3454                                 token = read32 (ip);
3455                                 ip += 4;
3456
3457                                 if (method->wrapper_type != MONO_WRAPPER_NONE)
3458                                         cm = (MonoMethod *)mono_method_get_wrapper_data (method, token);
3459                                 else 
3460                                         cm = mono_get_method (image, token, NULL);
3461
3462                                 g_assert (cm);
3463                                 
3464                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_LDFTN);
3465                                 t1->data.m = cm;
3466                                 PUSH_TREE (t1, VAL_POINTER);
3467                                 break;
3468                         }
3469                         case CEE_LDVIRTFTN: {
3470                                 MonoMethod *cm;
3471                                 guint32 token;
3472                                 ++ip;
3473                                 token = read32 (ip);
3474                                 ip += 4;
3475                                 --sp;
3476
3477                                 cm = mono_get_method (image, token, NULL);
3478                                 g_assert (cm);
3479
3480                                 if (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
3481                                         t2 = mono_ctree_new_leaf (mp, MB_TERM_INTF_ADDR);
3482                                 else 
3483                                         t2 = mono_ctree_new_leaf (mp, MB_TERM_VFUNC_ADDR);
3484
3485                                 t2->data.m = cm;
3486
3487                                 t1 = mono_ctree_new (mp, MB_TERM_LDVIRTFTN, *sp, t2);
3488
3489                                 PUSH_TREE (t1, VAL_POINTER);
3490
3491                                 break;
3492                         }
3493                         case CEE_INITOBJ: {
3494                                 MonoClass *class;
3495                                 guint32 token;
3496                                 
3497                                 ++ip;
3498                                 token = read32 (ip);
3499                                 class = mono_class_get (image, token);
3500                                 ip += 4;
3501                                 sp--;
3502                                 
3503                                 t1 = mono_ctree_new (mp, MB_TERM_INITOBJ, *sp, NULL);
3504                                 t1->data.i = mono_class_value_size (class, NULL);
3505                                 ADD_TREE (t1, cli_addr);
3506
3507                                 break;
3508                         }
3509                         case CEE_LDARG: {
3510                                 guint16 n;
3511                                 ++ip;
3512                                 n = read16 (ip);
3513                                 ip += 2;
3514
3515                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
3516                                 t1->data.i = ARG_POS (n);
3517                                 if (!MONO_TYPE_ISSTRUCT (ARG_TYPE (n))) 
3518                                         t1 = ctree_create_load (cfg, ARG_TYPE (n), t1, &svt, TRUE);
3519                                 PUSH_TREE (t1, svt);
3520                                 break;
3521                         }
3522                         case CEE_LDARGA: {
3523                                 guint16 n;
3524                                 ++ip;
3525                                 n = read16 (ip);
3526                                 ip += 2;
3527
3528                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
3529                                 t1->data.i = ARG_POS (n);
3530                                 PUSH_TREE (t1, svt);
3531                                 break;
3532                         }
3533                         case CEE_SIZEOF: {
3534                                 guint32 token;
3535                                 int align;
3536                                 ++ip;
3537                                 token = read32 (ip);
3538                                 ip += 4;
3539
3540                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
3541                                 if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC) {
3542                                         MonoType *type = mono_type_create_from_typespec (image, token);
3543                                         t1->data.i = mono_type_size (type, &align);
3544                                         mono_metadata_free_type (type);
3545                                 } else {
3546                                         MonoClass *szclass = mono_class_get (image, token);
3547                                         mono_class_init (szclass);
3548                                         g_assert (szclass->valuetype);
3549                                         t1->data.i = mono_class_value_size (szclass, &align);
3550                                 }
3551
3552                                 PUSH_TREE (t1, VAL_I32);
3553                                 break;
3554                         }
3555                         case CEE_CPBLK: {
3556                                 ++ip;
3557                                 sp -= 3;
3558
3559                                 t1 = mono_ctree_new (mp, MB_TERM_CPSRC, sp [1], sp [2]);
3560                                 t1 = mono_ctree_new (mp, MB_TERM_CPBLK, sp [0], t1);
3561                                 ADD_TREE (t1, cli_addr);
3562                                 break;
3563                         }
3564                         case CEE_UNALIGNED_: {
3565                                 ++ip;
3566                                 /* fixme: implement me */
3567                                 break;
3568                         }
3569                         case CEE_VOLATILE_: {
3570                                 ++ip;
3571                                 /* fixme: implement me */       
3572                                 break;
3573                         }
3574                         case CEE_TAIL_:
3575                                 ++ip;
3576                                 tail_recursion = TRUE;
3577                                 break;
3578                         case CEE_LOCALLOC: {
3579                                 ++ip;
3580                                 --sp;
3581
3582                                 t1 = mono_ctree_new (mp, MB_TERM_LOCALLOC, *sp, NULL);
3583                                 t1->data.i = header->init_locals;
3584                                 PUSH_TREE (t1, VAL_POINTER);
3585                                 break;
3586                         }
3587                         case CEE_INITBLK: {
3588                                 ++ip;
3589                                 sp -= 3;
3590
3591                                 t1 = mono_ctree_new (mp, MB_TERM_CPSRC, sp [1], sp [2]);
3592                                 t1 = mono_ctree_new (mp, MB_TERM_INITBLK, sp [0], t1);
3593                                 ADD_TREE (t1, cli_addr);
3594                                 break;
3595                         }
3596                         default:
3597                                 g_error ("Unimplemented opcode at IL_%04x "
3598                                          "0xFE %02x", ip - header->code, *ip);
3599                         }
3600                         break;
3601                 }       
3602                 default:
3603                         g_warning ("unknown instruction `%s' at IL_%04X", 
3604                                    mono_opcode_names [*ip], ip - header->code);
3605                         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE) {
3606                                 return FALSE;
3607                         }
3608                         mono_print_forest (cfg, forest);
3609                         g_assert_not_reached ();
3610                 }
3611         }               
3612
3613         if ((depth = sp - stack)) {
3614                 //printf ("DEPTH %d %d\n",  depth, sp [0]->op);
3615                 //mono_print_forest (cfg, forest);
3616                 create_outstack (cfg, bb, stack, sp - stack);
3617         }
3618
3619                                 } else 
3620                                         superblock_end = TRUE;
3621
3622                         } else {
3623                                 superblock_end = TRUE;
3624                                 //printf ("unreached block %d\n", i);
3625                                 repeat = TRUE;
3626                                 if (repeat_count >= 10) {
3627                                         /*mono_print_forest (cfg, forest);
3628                                         g_warning ("repeat count exceeded at ip: 0x%04x in %s\n", bb->cli_addr, cfg->method->name);*/
3629                                         repeat = FALSE;
3630                                 }
3631                         }
3632                                 //printf ("BBE %d %d %d %d\n", i, bb->reached, bb->finished, superblock_end);
3633                 }
3634
3635                 repeat_count++;
3636                 //printf ("REPEAT %d\n", repeat);
3637                 mono_jit_stats.analyze_stack_repeat++;
3638
3639
3640         } while (repeat);
3641
3642         return TRUE;
3643 }
3644
3645 static void
3646 mono_cfg_free (MonoFlowGraph *cfg)
3647 {
3648         int i;
3649
3650         for (i = 0; i < cfg->block_count; i++) {
3651                 if (!cfg->bblocks [i].reached)
3652                         continue;
3653                 g_ptr_array_free (cfg->bblocks [i].forest, TRUE);
3654                 g_list_free (cfg->bblocks [i].succ);
3655         }
3656
3657         if (cfg->bcinfo)
3658                 g_free (cfg->bcinfo);
3659
3660         if (cfg->bblocks)
3661                 g_free (cfg->bblocks);
3662                 
3663         g_array_free (cfg->varinfo, TRUE);
3664
3665         mono_mempool_destroy (cfg->mp);
3666 }
3667
3668 int mono_exc_esp_offset = 0;
3669
3670 static MonoFlowGraph *
3671 mono_cfg_new (MonoMethod *method)
3672 {
3673         MonoVarInfo vi;
3674         MonoFlowGraph *cfg;
3675         MonoMemPool *mp = mono_mempool_new ();
3676
3677         g_assert (((MonoMethodNormal *)method)->header);
3678
3679         cfg = mono_mempool_alloc0 (mp, sizeof (MonoFlowGraph));
3680
3681         cfg->domain = mono_domain_get ();
3682         cfg->method = method;
3683         cfg->mp = mp;
3684
3685         /* reserve space to save LMF */
3686         cfg->locals_size = sizeof (MonoLMF);
3687         
3688         cfg->locals_size += sizeof (gpointer);
3689         mono_exc_esp_offset = - cfg->locals_size;
3690
3691         cfg->locals_size += sizeof (gpointer);
3692
3693         /* aligment check */
3694         g_assert (!(cfg->locals_size & 0x7));
3695
3696         /* fixme: we should also consider loader optimisation attributes */
3697         cfg->share_code = mono_jit_share_code;
3698
3699         cfg->varinfo = g_array_new (FALSE, TRUE, sizeof (MonoVarInfo));
3700         
3701         SET_VARINFO (vi, 0, 0, 0, 0);
3702         g_array_append_val (cfg->varinfo, vi); /* add invalid value at position 0 */
3703
3704         cfg->intvars = mono_mempool_alloc0 (mp, sizeof (guint16) * VAL_DOUBLE * 
3705                                             ((MonoMethodNormal *)method)->header->max_stack);
3706
3707         mono_analyze_flow (cfg);
3708
3709         if (!mono_analyze_stack (cfg)) {
3710                 mono_cfg_free (cfg);
3711                 return NULL;
3712         }
3713         
3714         return cfg;
3715 }
3716
3717 static gpointer 
3718 mono_get_runtime_method (MonoMethod* method)
3719 {
3720         MonoMethod *nm;
3721         const char *name = method->name;
3722
3723         if (method->klass->parent == mono_defaults.multicastdelegate_class) {
3724                 if (*name == '.' && (strcmp (name, ".ctor") == 0)) {
3725                         return (gpointer)mono_delegate_ctor;
3726                 } else if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
3727                         nm = mono_marshal_get_delegate_invoke (method);
3728                         return mono_compile_method (nm);
3729                 } else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0)) {
3730                         nm = mono_marshal_get_delegate_begin_invoke (method);
3731                         return mono_compile_method (nm);
3732                 } else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0)) {
3733                         nm = mono_marshal_get_delegate_end_invoke (method);
3734                         return mono_compile_method (nm);
3735                 }
3736         }
3737         return NULL;
3738 }
3739
3740 #ifdef MONO_USE_EXC_TABLES
3741 static gboolean
3742 mono_type_blittable (MonoType *type)
3743 {
3744         if (type->byref)
3745                 return FALSE;
3746
3747         switch (type->type){
3748         case MONO_TYPE_VOID:
3749         case MONO_TYPE_I1:
3750         case MONO_TYPE_U1:
3751         case MONO_TYPE_I2:
3752         case MONO_TYPE_U2:
3753         case MONO_TYPE_I4:
3754         case MONO_TYPE_U4:
3755         case MONO_TYPE_I8:
3756         case MONO_TYPE_U8:
3757         case MONO_TYPE_R4:
3758         case MONO_TYPE_R8:
3759         case MONO_TYPE_I:
3760         case MONO_TYPE_U:
3761                 return TRUE;
3762         case MONO_TYPE_VALUETYPE:
3763         case MONO_TYPE_CLASS:
3764                 return type->data.klass->blittable;
3765                 break;
3766         default:
3767                 break;
3768         }
3769
3770         return FALSE;
3771 }
3772
3773 gboolean
3774 mono_method_blittable (MonoMethod *method)
3775 {
3776         MonoMethodSignature *sig;
3777         int i;
3778
3779         if (!method->addr)
3780                 return FALSE;
3781
3782         if (!mono_has_unwind_info (method)) {
3783                 return FALSE;
3784         }
3785
3786         if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
3787                 return TRUE;
3788
3789         sig = method->signature;
3790
3791         if (!mono_type_blittable (sig->ret))
3792                 return FALSE;
3793
3794         for (i = 0; i < sig->param_count; i++)
3795                 if (!mono_type_blittable (sig->params [i]))
3796                         return FALSE;
3797
3798         return TRUE;
3799 }
3800 #endif
3801
3802 /**
3803  * mono_jit_compile_method:
3804  * @method: pointer to the method info
3805  *
3806  * JIT compilation of a single method. 
3807  *
3808  * Returns: a pointer to the newly created code.
3809  */
3810 static gpointer
3811 mono_jit_compile_method (MonoMethod *method)
3812 {
3813         MonoDomain *target_domain, *domain = mono_domain_get ();
3814         MonoJitInfo *ji;
3815         guint8 *addr;
3816         GHashTable *jit_code_hash;
3817
3818         if (mono_jit_share_code)
3819                 target_domain = mono_root_domain;
3820         else 
3821                 target_domain = domain;
3822
3823         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
3824             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
3825
3826                 if (!method->info) {
3827                         MonoMethod *nm;
3828
3829                         if (!method->addr && (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
3830                                 mono_lookup_pinvoke_call (method);
3831 #ifdef MONO_USE_EXC_TABLES
3832                         if (mono_method_blittable (method)) {
3833                                 method->info = method->addr;
3834                         } else {
3835 #endif
3836                                 nm = mono_marshal_get_native_wrapper (method);
3837                                 method->info = mono_compile_method (nm);
3838
3839                                 if (mono_debug_format != MONO_DEBUG_FORMAT_NONE) 
3840                                         mono_debug_add_wrapper (method, nm, target_domain);
3841 #ifdef MONO_USE_EXC_TABLES
3842                         }
3843 #endif
3844                 }
3845
3846                 return method->info;
3847         }
3848
3849         jit_code_hash = target_domain->jit_code_hash;
3850
3851         if ((addr = g_hash_table_lookup (jit_code_hash, method))) {
3852                 mono_jit_stats.methods_lookups++;
3853
3854                 return addr;
3855         }
3856
3857         mono_jit_stats.methods_compiled++;
3858         
3859         if (mono_jit_trace_calls || mono_jit_dump_asm || mono_jit_dump_forest) {
3860                 printf ("Start JIT compilation of %s, domain '%s'\n",
3861                         mono_method_full_name (method, TRUE), target_domain->friendly_name);
3862         }
3863
3864         if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
3865                 if (!(addr = mono_get_runtime_method (method))) {       
3866                         mono_profiler_method_end_jit (method, MONO_PROFILE_FAILED);
3867                         if (mono_debug_format != MONO_DEBUG_FORMAT_NONE) 
3868                                 return NULL;
3869
3870                         g_error ("Don't know how to exec runtime method %s", mono_method_full_name (method, TRUE));
3871                 }
3872         } else {
3873                 MonoMethodHeader *header = ((MonoMethodNormal *)method)->header;
3874                 MonoFlowGraph *cfg;
3875                 gulong code_size_ratio;
3876         
3877                 mono_profiler_method_jit (method);
3878         
3879                 if (!(cfg = mono_cfg_new (method))) {
3880                         mono_profiler_method_end_jit (method, MONO_PROFILE_FAILED);
3881                         return NULL;
3882                 }
3883                         
3884                 cfg->code_size = MAX (header->code_size * 5, 256);
3885                 cfg->start = cfg->code = g_malloc (cfg->code_size);
3886
3887                 if (mono_debugger_method_has_breakpoint (method))
3888                         x86_breakpoint (cfg->code);
3889
3890                 if (!(ji = arch_jit_compile_cfg (target_domain, cfg))) {
3891                         mono_profiler_method_end_jit (method, MONO_PROFILE_FAILED);
3892                         return NULL;
3893                 }
3894                 
3895                 addr = cfg->start;
3896
3897                 mono_jit_stats.allocated_code_size += cfg->code_size;
3898
3899                 code_size_ratio = cfg->code - cfg->start;
3900                 if (code_size_ratio > mono_jit_stats.biggest_method_size) {
3901                         mono_jit_stats.biggest_method_size = code_size_ratio;
3902                         mono_jit_stats.biggest_method = method;
3903                 }
3904                 code_size_ratio = (code_size_ratio * 100) / header->code_size;
3905                 if (code_size_ratio > mono_jit_stats.max_code_size_ratio) {
3906                         mono_jit_stats.max_code_size_ratio = code_size_ratio;
3907                         mono_jit_stats.max_ratio_method = method;
3908                 }
3909
3910                 
3911                 if (mono_jit_dump_asm) {
3912                         char *id = g_strdup_printf ("%s.%s_%s", method->klass->name_space,
3913                                                     method->klass->name, method->name);
3914                         mono_disassemble_code (cfg->start, cfg->code - cfg->start, id);
3915                         g_free (id);
3916                 }
3917                 if (mono_debug_format != MONO_DEBUG_FORMAT_NONE)
3918                         mono_debug_jit_add_method (cfg);
3919
3920
3921                 mono_jit_stats.native_code_size += ji->code_size;
3922
3923                 ji->num_clauses = header->num_clauses;
3924
3925                 if (header->num_clauses) {
3926                         int i, start_block, end_block, filter_block;
3927
3928                         ji->clauses = mono_mempool_alloc0 (target_domain->mp, 
3929                                 sizeof (MonoJitExceptionInfo) * header->num_clauses);
3930
3931                         for (i = 0; i < header->num_clauses; i++) {
3932                                 MonoExceptionClause *ec = &header->clauses [i];
3933                                 MonoJitExceptionInfo *ei = &ji->clauses [i];
3934                         
3935                                 ei->flags = ec->flags;
3936
3937                                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
3938                                         g_assert (cfg->bcinfo [ec->token_or_filter].is_block_start);
3939                                         filter_block = cfg->bcinfo [ec->token_or_filter].block_id;
3940                                         ei->data.filter = cfg->start + cfg->bblocks [filter_block].addr;
3941                                 } else {
3942                                         ei->data.token = ec->token_or_filter;
3943                                 }
3944
3945                                 g_assert (cfg->bcinfo [ec->try_offset].is_block_start);
3946                                 start_block = cfg->bcinfo [ec->try_offset].block_id;
3947                                 end_block = cfg->bcinfo [ec->try_offset + ec->try_len].block_id;
3948                                 g_assert (cfg->bcinfo [ec->try_offset + ec->try_len].is_block_start);
3949                                 
3950                                 ei->try_start = cfg->start + cfg->bblocks [start_block].addr;
3951                                 ei->try_end = cfg->start + cfg->bblocks [end_block].addr;
3952                                 
3953                                 g_assert (cfg->bcinfo [ec->handler_offset].is_block_start);
3954                                 start_block = cfg->bcinfo [ec->handler_offset].block_id;
3955                                 ei->handler_start = cfg->start + cfg->bblocks [start_block].addr;       
3956                         }
3957                 }
3958                 
3959                 mono_jit_info_table_add (target_domain, ji);
3960
3961                 mono_regset_free (cfg->rs);
3962
3963                 mono_cfg_free (cfg);
3964
3965                 mono_profiler_method_end_jit (method, MONO_PROFILE_OK);
3966         }
3967
3968         if (mono_jit_trace_calls || mono_jit_dump_asm || mono_jit_dump_forest) {
3969                 printf ("END JIT compilation of %s %p %p, domain '%s'\n",
3970                                  mono_method_full_name (method, FALSE),
3971                                  method,
3972                                  addr,
3973                                  target_domain->friendly_name);
3974         }
3975
3976         g_hash_table_insert (jit_code_hash, method, addr);
3977
3978         /* make sure runtime_init is called */
3979         mono_class_vtable (target_domain, method->klass);
3980
3981         return addr;
3982 }
3983
3984 /* mono_jit_create_remoting_trampoline:
3985  * @method: pointer to the method info
3986  *
3987  * Creates a trampoline which calls the remoting functions. This
3988  * is used in the vtable of transparent proxies.
3989  * 
3990  * Returns: a pointer to the newly created code 
3991  */
3992 gpointer
3993 mono_jit_create_remoting_trampoline (MonoMethod *method)
3994 {
3995         MonoMethod *nm;
3996         guint8 *addr = NULL;
3997
3998         nm = mono_marshal_get_remoting_invoke (method);
3999         addr = mono_compile_method (nm);
4000
4001         return addr;
4002 }
4003
4004 /* this function is never called */
4005 static void
4006 ves_array_set (MonoArray *this, ...)
4007 {
4008         g_assert_not_reached ();
4009 }
4010
4011 /* this function is never called */
4012 static void
4013 ves_array_get (MonoArray *this, ...)
4014 {
4015         g_assert_not_reached ();
4016 }
4017
4018 /**
4019  * mono_jit_exec:
4020  * @assembly: reference to an assembly
4021  * @argc: argument count
4022  * @argv: argument vector
4023  *
4024  * Start execution of a program.
4025  */
4026 int 
4027 mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
4028 {
4029         MonoImage *image = assembly->image;
4030         MonoMethod *method;
4031
4032         method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
4033
4034         return mono_runtime_run_main (method, argc, argv, NULL);
4035 }
4036
4037 #ifdef PLATFORM_WIN32
4038 #define GET_CONTEXT \
4039         struct sigcontext *ctx = (struct sigcontext*)_dummy;
4040 #else
4041 #define GET_CONTEXT \
4042         void **_p = (void **)&_dummy; \
4043         struct sigcontext *ctx = (struct sigcontext *)++_p;
4044 #endif
4045
4046 static void
4047 sigfpe_signal_handler (int _dummy)
4048 {
4049         MonoException *exc;
4050         GET_CONTEXT
4051
4052         exc = mono_get_exception_divide_by_zero ();
4053         
4054         arch_handle_exception (ctx, exc, FALSE);
4055 }
4056
4057 static void
4058 sigill_signal_handler (int _dummy)
4059 {
4060         MonoException *exc;
4061         GET_CONTEXT
4062         exc = mono_get_exception_execution_engine ("SIGILL");
4063         
4064         arch_handle_exception (ctx, exc, FALSE);
4065 }
4066
4067 static void
4068 sigsegv_signal_handler (int _dummy)
4069 {
4070         MonoException *exc;
4071         GET_CONTEXT
4072
4073         exc = mono_get_exception_null_reference ();
4074         
4075         arch_handle_exception (ctx, exc, FALSE);
4076 }
4077
4078 static void
4079 sigusr1_signal_handler (int _dummy)
4080 {
4081         MonoThread *thread;
4082         GET_CONTEXT
4083         
4084         thread = mono_thread_current ();
4085
4086         g_assert (thread->abort_exc);
4087
4088         arch_handle_exception (ctx, thread->abort_exc, FALSE);
4089 }
4090
4091 gpointer 
4092 mono_get_lmf_addr (void)
4093 {
4094         MonoJitTlsData *jit_tls;        
4095
4096         if ((jit_tls = TlsGetValue (mono_jit_tls_id)))
4097                 return &jit_tls->lmf;
4098
4099         g_assert_not_reached ();
4100         return NULL;
4101 }
4102
4103 /**
4104  * mono_thread_abort:
4105  * @obj: exception object
4106  *
4107  * abort the thread, print exception information and stack trace
4108  */
4109 static void
4110 mono_thread_abort (MonoObject *obj)
4111 {
4112         MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
4113         
4114         g_free (jit_tls);
4115
4116         ExitThread (-1);
4117 }
4118
4119 static void
4120 mono_thread_start_cb (guint32 tid, gpointer stack_start, gpointer func)
4121 {
4122         MonoJitTlsData *jit_tls;
4123         MonoLMF *lmf;
4124
4125         jit_tls = g_new0 (MonoJitTlsData, 1);
4126
4127         TlsSetValue (mono_jit_tls_id, jit_tls);
4128
4129         jit_tls->abort_func = mono_thread_abort;
4130         jit_tls->end_of_stack = stack_start;
4131
4132         lmf = g_new0 (MonoLMF, 1);
4133         lmf->ebp = -1;
4134
4135         jit_tls->lmf = lmf;
4136 }
4137
4138 void (*mono_thread_attach_aborted_cb ) (MonoObject *obj) = NULL;
4139
4140 static void
4141 mono_thread_abort_dummy (MonoObject *obj)
4142 {
4143   if (mono_thread_attach_aborted_cb)
4144     mono_thread_attach_aborted_cb (obj);
4145   else
4146     mono_thread_abort (obj);
4147 }
4148
4149 static void
4150 mono_thread_attach_cb (guint32 tid, gpointer stack_start)
4151 {
4152         MonoJitTlsData *jit_tls;
4153         MonoLMF *lmf;
4154
4155         jit_tls = g_new0 (MonoJitTlsData, 1);
4156
4157         TlsSetValue (mono_jit_tls_id, jit_tls);
4158
4159         jit_tls->abort_func = mono_thread_abort_dummy;
4160         jit_tls->end_of_stack = stack_start;
4161
4162         lmf = g_new0 (MonoLMF, 1);
4163         lmf->ebp = -1;
4164
4165         jit_tls->lmf = lmf;
4166 }
4167
4168 static CRITICAL_SECTION ms;
4169
4170 static void
4171 mono_runtime_install_handlers (void)
4172 {
4173 #ifndef PLATFORM_WIN32
4174         struct sigaction sa;
4175 #endif
4176
4177 #ifdef PLATFORM_WIN32
4178         win32_seh_init();
4179         win32_seh_set_handler(SIGFPE, sigfpe_signal_handler);
4180         win32_seh_set_handler(SIGILL, sigill_signal_handler);
4181         win32_seh_set_handler(SIGSEGV, sigsegv_signal_handler);
4182 #else /* !PLATFORM_WIN32 */
4183
4184         /* libpthreads has its own implementation of sigaction(),
4185          * but it seems to work well with our current exception
4186          * handlers. If not we must call syscall directly instead 
4187          * of sigaction */
4188         
4189         /* catch SIGFPE */
4190         sa.sa_handler = sigfpe_signal_handler;
4191         sigemptyset (&sa.sa_mask);
4192         sa.sa_flags = 0;
4193         //g_assert (syscall (SYS_sigaction, SIGFPE, &sa, NULL) != -1);
4194         g_assert (sigaction (SIGFPE, &sa, NULL) != -1);
4195
4196         /* catch SIGILL */
4197         sa.sa_handler = sigill_signal_handler;
4198         sigemptyset (&sa.sa_mask);
4199         sa.sa_flags = 0;
4200         //g_assert (syscall (SYS_sigaction, SIGILL, &sa, NULL) != -1);
4201         g_assert (sigaction (SIGILL, &sa, NULL) != -1);
4202
4203         /* catch the thread abort signal */
4204         sa.sa_handler = sigusr1_signal_handler;
4205         sigemptyset (&sa.sa_mask);
4206         sa.sa_flags = 0;
4207         //g_assert (syscall (SYS_sigaction, SIGILL, &sa, NULL) != -1);
4208 #ifdef __NetBSD__
4209         g_assert (sigaction (mono_thread_get_abort_signal (), &sa, NULL) != -1);
4210 #else
4211         g_assert (syscall (SYS_sigaction, mono_thread_get_abort_signal (), &sa, NULL) != -1);
4212         //g_assert (sigaction (mono_thread_get_abort_signal (), &sa, NULL) != -1);
4213 #endif
4214
4215 #if 1
4216         /* catch SIGSEGV */
4217         sa.sa_handler = sigsegv_signal_handler;
4218         sigemptyset (&sa.sa_mask);
4219         sa.sa_flags = 0;
4220         //g_assert (syscall (SYS_sigaction, SIGSEGV, &sa, NULL) != -1);
4221         g_assert (sigaction (SIGSEGV, &sa, NULL) != -1);
4222 #endif
4223 #endif /* PLATFORM_WIN32 */
4224 }
4225
4226 MonoDomain*
4227 mono_jit_init (const char *file) {
4228         MonoDomain *domain;
4229
4230         mono_cpu_detect ();
4231
4232         mono_runtime_install_handlers ();
4233
4234         mono_init_icall ();
4235         mono_add_internal_call ("System.Array::Set", ves_array_set);
4236         mono_add_internal_call ("System.Array::Get", ves_array_get);
4237         mono_add_internal_call ("System.Array::Address", ves_array_element_address);
4238         mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info", 
4239                                 ves_icall_get_frame_info);
4240         mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace", 
4241                                 ves_icall_get_trace);
4242         mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers", mono_runtime_install_handlers);
4243
4244         metadata_section = &ms;
4245         InitializeCriticalSection (metadata_section);
4246
4247         mono_jit_tls_id = TlsAlloc ();
4248
4249         /* Don't set up the main thread for managed code execution -
4250          * this will give a handy assertion fail in
4251          * mono_get_lmf_addr() if any buggy runtime code tries to run
4252          * managed code in this thread.
4253          *
4254          * Note, adding static initializer/objects to thread.cs will 
4255          *       also cause mon_get_lmf_addr assertion
4256          *
4257          */
4258         /* mono_thread_start_cb (GetCurrentThreadId (), (gpointer)-1, NULL); */
4259
4260         mono_install_compile_method (mono_jit_compile_method);
4261         mono_install_trampoline (arch_create_jit_trampoline);
4262         mono_install_remoting_trampoline (mono_jit_create_remoting_trampoline);
4263         mono_install_handler (arch_get_throw_exception ());
4264         mono_install_runtime_invoke (mono_jit_runtime_invoke);
4265         mono_install_stack_walk (mono_jit_walk_stack);
4266         mono_install_get_config_dir ();
4267
4268         domain = mono_init (file);
4269         mono_runtime_init (domain, mono_thread_start_cb, mono_thread_attach_cb);
4270
4271         return domain;
4272 }
4273
4274 void
4275 mono_jit_cleanup (MonoDomain *domain)
4276 {
4277         mono_domain_finalize (domain);
4278
4279         mono_runtime_cleanup (domain);
4280
4281         mono_debug_cleanup ();
4282
4283 #ifdef PLATFORM_WIN32
4284         win32_seh_cleanup();
4285 #endif
4286
4287         mono_domain_unload (domain, TRUE);
4288
4289         if (mono_jit_stats.enabled) {
4290                 g_print ("Mono Jit statistics\n");
4291                 g_print ("Compiled methods:       %ld\n", mono_jit_stats.methods_compiled);
4292                 g_print ("Methods cache lookup:   %ld\n", mono_jit_stats.methods_lookups);
4293                 g_print ("Method trampolines:     %ld\n", mono_jit_stats.method_trampolines);
4294                 g_print ("Basic blocks:           %ld\n", mono_jit_stats.basic_blocks);
4295                 g_print ("Max basic blocks:       %ld\n", mono_jit_stats.max_basic_blocks);
4296                 g_print ("Allocated vars:         %ld\n", mono_jit_stats.allocate_var);
4297                 g_print ("Analyze stack repeat:   %ld\n", mono_jit_stats.analyze_stack_repeat);
4298                 g_print ("Compiled CIL code size: %ld\n", mono_jit_stats.cil_code_size);
4299                 g_print ("Native code size:       %ld\n", mono_jit_stats.native_code_size);
4300                 g_print ("Max code size ratio:    %.2f (%s::%s)\n", mono_jit_stats.max_code_size_ratio/100.0,
4301                                 mono_jit_stats.max_ratio_method->klass->name, mono_jit_stats.max_ratio_method->name);
4302                 g_print ("Biggest method:         %ld (%s::%s)\n", mono_jit_stats.biggest_method_size,
4303                                 mono_jit_stats.biggest_method->klass->name, mono_jit_stats.biggest_method->name);
4304                 g_print ("Code reallocs:          %ld\n", mono_jit_stats.code_reallocs);
4305                 g_print ("Allocated code size:    %ld\n", mono_jit_stats.allocated_code_size);
4306                 g_print ("Inlineable methods:     %ld\n", mono_jit_stats.inlineable_methods);
4307                 g_print ("Inlined methods:        %ld\n", mono_jit_stats.inlined_methods);
4308                 
4309                 g_print ("\nCreated object count:   %ld\n", mono_stats.new_object_count);
4310                 g_print ("Initialized classes:    %ld\n", mono_stats.initialized_class_count);
4311                 g_print ("Used classes:           %ld\n", mono_stats.used_class_count);
4312                 g_print ("Static data size:       %ld\n", mono_stats.class_static_data_size);
4313                 g_print ("VTable data size:       %ld\n", mono_stats.class_vtable_size);
4314         }
4315
4316         DeleteCriticalSection (metadata_section);
4317
4318 }
4319
4320 /**
4321  * mono_jit_image:
4322  * @image: reference to an image
4323  * @verbose: If true, print debugging information on stdout.
4324  *
4325  * JIT compilation of all methods in the image.
4326  */
4327 void
4328 mono_jit_compile_image (MonoImage *image, int verbose)
4329 {
4330         MonoMethod *method;
4331         MonoTableInfo *t = &image->tables [MONO_TABLE_METHOD];
4332         int i;
4333
4334         for (i = 0; i < t->rows; i++) {
4335
4336                 method = mono_get_method (image, 
4337                                           (MONO_TABLE_METHOD << 24) | (i + 1), 
4338                                           NULL);
4339
4340                 if (verbose)
4341                         g_print ("Compiling: %s:%s\n\n", image->assembly_name, method->name);
4342
4343                 if (method->flags & METHOD_ATTRIBUTE_ABSTRACT) {
4344                         if (verbose)
4345                                 printf ("ABSTARCT\n");
4346                 } else
4347                         mono_compile_method (method);
4348
4349         }
4350
4351 }
4352