Sat Aug 18 12:40:32 CEST 2001 Paolo Molaro <lupus@ximian.com>
authorPaolo Molaro <lupus@oddwiz.org>
Sat, 18 Aug 2001 06:55:29 +0000 (06:55 -0000)
committerPaolo Molaro <lupus@oddwiz.org>
Sat, 18 Aug 2001 06:55:29 +0000 (06:55 -0000)
* x86/x86-codegen.h: fix a couple of buglets and add x86_regp_emit().

Sat Aug 18 12:42:26 CEST 2001 Paolo Molaro <lupus@ximian.com>

* class.c, class.h: load also the methods when loading a class.

Sat Aug 18 12:43:38 CEST 2001 Paolo Molaro <lupus@ximian.com>

* interp.c, interp.h: added support code to create exceptions.
Changed interncal calling convnetion over to MonoInvocation, to support
exceptions, walking the stack back and forward and passing the 'this'
pointer separately (remove the cludges required before to pass this on the
stack). Use alloca heavily for both local vars and a copy of the incoming
arguments. Init local vars to zero.
Simplify stackval_from_data() and stackval_to_data() to only take a pointer
instead of pointer + offset.
Implement a few exceptions-related opcodes and the code to run finally, fault and
catch blocks as well as a stack trace if no handler is found.

Sat Aug 18 12:51:28 CEST 2001 Paolo Molaro <lupus@ximian.com>

* metadata.c, metadata.h: in the signature and method header store
only the space required for holding the loca vars and incoming arguments.

svn path=/trunk/mono/; revision=493

18 files changed:
mono/arch/ChangeLog
mono/arch/x86/test.c
mono/arch/x86/x86-codegen.h
mono/cli/ChangeLog
mono/cli/class.c
mono/cli/class.h
mono/interpreter/ChangeLog
mono/interpreter/hacks.h
mono/interpreter/icall.c
mono/interpreter/interp.c
mono/interpreter/interp.h
mono/metadata/ChangeLog
mono/metadata/class.c
mono/metadata/class.h
mono/metadata/icall.c
mono/metadata/image.c
mono/metadata/metadata.c
mono/metadata/metadata.h

index 57f43d2afde0be3ab8345a04ad07e5db7f735e84..31eecbfec394941784794642ccc356077f452482 100644 (file)
@@ -1,3 +1,8 @@
+
+Sat Aug 18 12:40:32 CEST 2001 Paolo Molaro <lupus@ximian.com>
+
+       * x86/x86-codegen.h: fix a couple of buglets and add x86_regp_emit().
+
 Wed Aug 8 15:30:05 CEST 2001 Paolo Molaro <lupus@ximian.com>
 
        * x86/x86-codegen.h, x86/test.c: added x86 code emitter with
index 0ae82fea92e9da405c23373f2eee814c1b7b97f0..231b7f665e71d80a98b78d446f3d975706eab704 100644 (file)
@@ -202,7 +202,7 @@ int main() {
        x86_cmov_membase (p, X86_CC_GT, 0, X86_EAX, X86_EDX, -4);
 
        x86_nop (p);
-       x86_epilog (p, X86_CALLEE_REGS);
+       x86_epilog (p, X86_CALLER_REGS);
 
        size = p-code;
        for (i = 0; i < size; ++i)
index 4cf568f39c53342c82ee26e49ca2ab3d2fa35c4c..166030eb957b384a439dfb5fc6e518e1a2d85802 100644 (file)
@@ -1,7 +1,7 @@
 /* Copyright (C)  2000 Intel Corporation.  All rights reserved.
    Copyright (C)  2001 Ximian, Inc. 
 //
-// $Header: /home/miguel/third-conversion/public/mono/mono/arch/x86/x86-codegen.h,v 1.3 2001/08/08 17:21:29 lupus Exp $
+// $Header: /home/miguel/third-conversion/public/mono/mono/arch/x86/x86-codegen.h,v 1.4 2001/08/18 06:55:29 lupus Exp $
 */
 
 #ifndef X86_H
@@ -39,7 +39,7 @@ typedef enum {
 // opcodes for shift instructions
 */
 typedef enum {
-        X86_SHLD,
+       X86_SHLD,
        X86_SHLR,
        X86_SHL = 4,
        X86_SHR = 5,
@@ -122,16 +122,21 @@ x86_cc_signed_map [X86_NCC] = {
        0x7b, // np
 };
 
+typedef union {
+       int val;
+       unsigned char b [4];
+} x86_imm_buf;
+
 /*
 // bitvector mask for callee-saved registers
 */
-#define X86_CALLEE_ESI_MASK (1<<X86_ESI)
-#define X86_CALLEE_EDI_MASK (1<<X86_EDI)
-#define X86_CALLEE_EBX_MASK (1<<X86_EBX)
-#define X86_CALLEE_EBP_MASK (1<<X86_EBP)
+#define X86_ESI_MASK (1<<X86_ESI)
+#define X86_EDI_MASK (1<<X86_EDI)
+#define X86_EBX_MASK (1<<X86_EBX)
+#define X86_EBP_MASK (1<<X86_EBP)
 
-#define X86_CALLER_REGS ((1<<X86_EAX) | (1<<X86_ECX) | (1<<X86_EDX))
-#define X86_CALLEE_REGS ((1<<X86_EBX) | (1<<X86_EBP) | (1<<X86_ESI) | (1<<X86_EDI))
+#define X86_CALLEE_REGS ((1<<X86_EAX) | (1<<X86_ECX) | (1<<X86_EDX))
+#define X86_CALLER_REGS ((1<<X86_EBX) | (1<<X86_EBP) | (1<<X86_ESI) | (1<<X86_EDI))
 #define X86_BYTE_REGS   ((1<<X86_EAX) | (1<<X86_ECX) | (1<<X86_EDX) | (1<<X86_EBX))
 
 #define X86_IS_SCRATCH(reg) (X86_CALLER_REGS & (1 << (reg))) /* X86_EAX, X86_ECX, or X86_EDX */
@@ -181,13 +186,21 @@ x86_cc_signed_map [X86_NCC] = {
  * useful building blocks
  */
 #define x86_address_byte(inst,m,o,r) do { *(inst)++ = ((((m)&0x03)<<6)|(((o)&0x07)<<3)|(((r)&0x07))); } while (0)
-#define x86_imm_emit32(inst,imm)     do { *(int*)(inst) = (imm); (inst) += 4; } while (0)
+#define x86_imm_emit32(inst,imm)     \
+       do {    \
+                       x86_imm_buf imb; imb.val = (int) (imm); \
+                       *(inst)++ = imb.b [0];  \
+                       *(inst)++ = imb.b [1];  \
+                       *(inst)++ = imb.b [2];  \
+                       *(inst)++ = imb.b [3];  \
+       } while (0)
 #define x86_imm_emit16(inst,imm)     do { *(short*)(inst) = (imm); (inst) += 2; } while (0)
 #define x86_imm_emit8(inst,imm)      do { *(inst) = (unsigned char)((imm) & 0xff); ++(inst); } while (0)
 #define x86_is_imm8(imm)             (((int)(imm) >= -128 && (int)(imm) <= 127))
 #define x86_is_imm16(imm)            (((int)(imm) >= -(1<<16) && (int)(imm) <= ((1<<16)-1)))
 
 #define x86_reg_emit(inst,r,regno)   do { x86_address_byte ((inst), 3, (r), (regno)); } while (0)
+#define x86_regp_emit(inst,r,regno)  do { x86_address_byte ((inst), 0, (r), (regno)); } while (0)
 #define x86_mem_emit(inst,r,disp)    do { x86_address_byte ((inst), 0, (r), 5); x86_imm_emit32((inst), (disp)); } while (0)
 
 #define x86_membase_emit(inst,r,basereg,disp)  do {\
@@ -668,7 +681,7 @@ x86_cc_signed_map [X86_NCC] = {
                x86_mem_emit ((inst), (reg), (mem));    \
        } while (0)
 
-#define x86_mov_reg_membase(inst,reg,regbase,disp,size)        \
+#define x86_mov_reg_membase(inst,reg,basereg,disp,size)        \
        do {    \
                switch ((size)) {       \
                case 1: *(inst)++ = (unsigned char)0x8a; break; \
@@ -940,6 +953,12 @@ x86_cc_signed_map [X86_NCC] = {
                *(inst)++ = (unsigned char)0x50 + (reg);        \
        } while (0)
 
+#define x86_push_regp(inst,reg)        \
+       do {    \
+               *(inst)++ = (unsigned char)0xff;        \
+               x86_regp_emit ((inst), 6, (reg));       \
+       } while (0)
+
 #define x86_push_mem(inst,mem) \
        do {    \
                *(inst)++ = (unsigned char)0xff;        \
@@ -1076,10 +1095,10 @@ x86_cc_signed_map [X86_NCC] = {
                }       \
        } while (0)
 
-#define x86_call_imm(inst,imm) \
+#define x86_call_imm(inst,disp)        \
        do {    \
                *(inst)++ = (unsigned char)0xe8;        \
-               x86_imm_emit32 ((inst), (imm)); \
+               x86_imm_emit32 ((inst), (int)(disp));   \
        } while (0)
 
 #define x86_call_reg(inst,reg) \
index 1f52bb7e3a6038d992e6c1f4270ba4f4a812f412..dc0795f339df60a84db9932b3c51da783b9e97e3 100644 (file)
@@ -1,3 +1,7 @@
+Sat Aug 18 12:42:26 CEST 2001 Paolo Molaro <lupus@ximian.com>
+
+       * class.c, class.h: load also the methods when loading a class.
+
 2001-08-10  Dietmar Maurer  <dietmar@ximian.com>
 
        * object.c (mono_object_clone): impl.
index 300975441e5e426932fdca3f8b2967d5e9e4530d..fbafd5f54f9c550bf83b2508e4025249aee53ac6 100644 (file)
@@ -234,6 +234,14 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
                g_assert (class->instance_size == sizeof (MonoArrayObject));
        }
 
+       if (class->method.count > 0) {
+               int i;
+               class->methods = g_new (MonoMethod*, class->method.count);
+               for (i = class->method.first; i < class->method.last; ++i)
+                       class->methods [i - class->method.first] = mono_get_method (image,
+                                                       MONO_TOKEN_METHOD_DEF | (i + 1));
+       }
+       
        class = g_malloc0 (class->class_size);
        *class = stack_class;
        return class;
index 501f2db876fdd6cce6308a40a889a70c8ab84d27..8928f7e3c196565620bb1aa7fb38111f21d5fee0 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <mono/metadata/metadata.h>
 #include <mono/metadata/image.h>
+#include <mono/cli/cli.h>
 
 #define MONO_CLASS_IS_ARRAY(c) (c->type_token == 0)
 
@@ -43,6 +44,9 @@ struct _MonoClass {
         * Field information: Type and location from object base
         */
        MonoClassField *fields;
+       
+       struct MonoMethod **methods;
+
        /*
         * After the fields, there is room for the static fields...
         */
index 15979aa2ae1869595cbd14732b4c9a76d3e6520b..ca0612f6010b4578272290d98d84152aa9ce0220 100644 (file)
@@ -1,3 +1,17 @@
+
+Sat Aug 18 12:43:38 CEST 2001 Paolo Molaro <lupus@ximian.com>
+
+       * interp.c, interp.h: added support code to create exceptions.
+       Changed interncal calling convnetion over to MonoInvocation, to support
+       exceptions, walking the stack back and forward and passing the 'this'
+       pointer separately (remove the cludges required before to pass this on the
+       stack). Use alloca heavily for both local vars and a copy of the incoming 
+       arguments. Init local vars to zero.
+       Simplify stackval_from_data() and stackval_to_data() to only take a pointer
+       instead of pointer + offset.
+       Implement a few exceptions-related opcodes and the code to run finally, fault and
+       catch blocks as well as a stack trace if no handler is found.
+       
 2001-08-16  Alex Graveley  <alex@ximian.com>
 
        * Makefile.am (mono_int_LDADD): Link with ../../libffi/libffi.a
index de4663b256ce4e0ae78fd9287f8edd95bdcd8b53..dafae4ea6373faed499da0e95e289dbaa6828db0 100644 (file)
@@ -67,7 +67,7 @@
 #define CASE(l)        case l:
 #define DEFAULT        \
                default:        \
-                       g_error ("Unimplemented opcode: %x at 0x%x\n", *ip, ip-(unsigned char*)mm->header->code);
+                       g_error ("Unimplemented opcode: %x at 0x%x\n", *ip, ip-header->code);
 #define SUB_SWITCH case 0xFE:
 #define GOTO_LABEL_VARS
 
index 91028942fa96cb3c5f448ace187cf7b27fa32a1e..70298c78e03ea12d1110d776447d5f3543d8f56c 100644 (file)
@@ -283,7 +283,7 @@ mono_lookup_internal_call (const char *name)
 
                icall_hash = g_hash_table_new (g_str_hash , g_str_equal);
                
-               while (n = icall_map [i]) {
+               while ((n = icall_map [i])) {
                        g_hash_table_insert (icall_hash, n, icall_map [i+1]);
                        i += 2;
                }
index 6568d3e8ee03896c409eff11815c05f85c46bbef..3ecaaccbc87ba232cb9c0c3c0017bb583acae9b1 100644 (file)
@@ -29,7 +29,6 @@
 #   endif
 #endif
 
-#include "interp.h"
 /* trim excessive headers */
 #include <mono/metadata/image.h>
 #include <mono/metadata/assembly.h>
@@ -40,6 +39,7 @@
 #include <mono/metadata/tokentype.h>
 #include <mono/cli/cli.h>
 #include <mono/cli/types.h>
+#include "interp.h"
 #include "hacks.h"
 
 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
@@ -52,11 +52,12 @@ enum {
 #undef OPDEF
 
 static int debug_indent_level = 0;
+static MonoImage *corlib = NULL;
 
 #define GET_NATI(sp) ((guint32)(sp).data.i)
 #define CSIZE(x) (sizeof (x) / 4)
 
-static void ves_exec_method (MonoMethod *mh, stackval *args);
+static void ves_exec_method (MonoInvocation *frame);
 
 typedef void (*ICallMethod) (MonoMethod *mh, stackval *args);
 
@@ -68,14 +69,14 @@ ves_real_abort (int line, MonoMethod *mh,
        MonoMethodNormal *mm = (MonoMethodNormal *)mh;
        fprintf (stderr, "Execution aborted in method: %s\n", mh->name);
        fprintf (stderr, "Line=%d IP=0x%04x, Aborted execution\n", line,
-                ip-(unsigned char *)mm->header->code);
+                ip-mm->header->code);
        g_print ("0x%04x %02x\n",
-                ip-(unsigned char*)mm->header->code, *ip);
+                ip-mm->header->code, *ip);
        if (sp > stack)
                printf ("\t[%d] %d 0x%08x %0.5f\n", sp-stack, sp[-1].type, sp[-1].data.i, sp[-1].data.f);
        exit (1);
 }
-#define ves_abort() ves_real_abort(__LINE__, mh, ip, stack, sp)
+#define ves_abort() ves_real_abort(__LINE__, frame->method, ip, frame->stack, sp)
 
 /*
  * init_class:
@@ -90,6 +91,12 @@ init_class (MonoClass *klass)
        MonoMetadata *m;
        MonoTableInfo *t;
        int i;
+       MonoInvocation call;
+
+       call.parent = NULL;
+       call.retval = NULL;
+       call.obj = NULL;
+       call.stack_args = NULL;
        
        if (klass->inited)
                return;
@@ -103,9 +110,9 @@ init_class (MonoClass *klass)
                mono_metadata_decode_row (t, i, cols, MONO_METHOD_SIZE);
                
                if (strcmp (".cctor", mono_metadata_string_heap (m, cols [MONO_METHOD_NAME])) == 0) {
-                       MonoMethod *cctor = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (i + 1));
-                       ves_exec_method (cctor, NULL);
-                       mono_free_method (cctor);
+                       call.method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (i + 1));
+                       ves_exec_method (&call);
+                       mono_free_method (call.method);
                        klass->inited = 1;
                        return;
                }
@@ -186,53 +193,145 @@ get_virtual_method (MonoImage *image, guint32 token, stackval *args)
        return NULL;
 }
 
+/*
+ * When this is tested, export it from cli/.
+ */
+static int
+match_signature (const char *name, MonoMethodSignature *sig, MonoMethod *method)
+{
+       int i;
+       MonoMethodSignature *sig2 = method->signature;
+       /* 
+        * compare the signatures.
+        * First the cheaper comparisons.
+        */
+       if (sig->param_count != sig2->param_count)
+               return 0;
+       if (sig->hasthis != sig2->hasthis)
+               return 0;
+       /*if (!sig->ret) {
+               if (sig2->ret) return 0;
+       } else {
+               if (!sig2->ret) return 0;
+               if (sig->ret->type->type != sig2->ret->type->type)
+                       return 0;
+       }*/
+       for (i = sig->param_count - 1; i >= 0; ++i) {
+               if (sig->params [i]->type->type != sig2->params [i]->type->type)
+                       return 0;
+       }
+       /* compare the function name */
+       return strcmp (name, method->name) == 0;
+}
+
+static MonoObject*
+get_named_exception (const char *name)
+{
+       MonoClass *klass;
+       MonoInvocation call;
+       MonoObject *o;
+       MonoMethodSignature sig = {
+               1, /* hasthis */
+               0,
+               MONO_CALL_DEFAULT,
+               0, /* param count */
+               0, /* sentinel pos */
+               NULL, /* retval -> void */
+               NULL, /* params */
+               0
+       };
+       int i;
+       guint32 tdef = mono_typedef_from_name (corlib, name, "System", NULL);
+       o = newobj (corlib, tdef);
+       klass = mono_class_get (corlib, tdef);
+       call.method = NULL;
+       for (i = 0; i < klass->method.count; ++i) {
+               if (match_signature (".ctor", &sig, klass->methods [i])) {
+                       call.method = klass->methods [i];
+                       break;
+               }
+       }
+       g_assert (call.method);
+       call.obj = o;
+       ves_exec_method (&call);
+       return o;
+}
+
+static MonoObject*
+get_exception_divide_by_zero ()
+{
+       static MonoObject *ex = NULL;
+       if (ex)
+               return ex;
+       ex = get_named_exception ("DivideByZeroException");
+       return ex;
+}
+
+static int
+mono_isinst (MonoObject *obj, MonoClass *klass)
+{
+       MonoClass *oklass = obj->klass;
+       while (oklass) {
+               if (oklass == klass)
+                       return 1;
+               oklass = oklass->parent;
+       }
+       return 0;
+}
+
 static stackval
-stackval_from_data (MonoType *type, const char *data, guint offset)
+stackval_from_data (MonoType *type, const char *data)
 {
        stackval result;
+       if (type->byref) {
+               result.type = VAL_OBJ;
+               result.data.p = *(gpointer*)data;
+               return result;
+       }
        switch (type->type) {
        case MONO_TYPE_I1:
                result.type = VAL_I32;
-               result.data.i = *(gint8*)(data + offset);
+               result.data.i = *(gint8*)data;
                break;
        case MONO_TYPE_U1:
        case MONO_TYPE_BOOLEAN:
                result.type = VAL_I32;
-               result.data.i = *(guint8*)(data + offset);
+               result.data.i = *(guint8*)data;
                break;
        case MONO_TYPE_I2:
                result.type = VAL_I32;
-               result.data.i = *(gint16*)(data + offset);
+               result.data.i = *(gint16*)data;
                break;
        case MONO_TYPE_U2:
        case MONO_TYPE_CHAR:
                result.type = VAL_I32;
-               result.data.i = *(guint16*)(data + offset);
+               result.data.i = *(guint16*)data;
                break;
        case MONO_TYPE_I4:
                result.type = VAL_I32;
-               result.data.i = *(gint32*)(data + offset);
+               result.data.i = *(gint32*)data;
                break;
        case MONO_TYPE_U4:
                result.type = VAL_I32;
-               result.data.i = *(guint32*)(data + offset);
+               result.data.i = *(guint32*)data;
                break;
        case MONO_TYPE_R4:
                result.type = VAL_DOUBLE;
-               result.data.f = *(float*)(data + offset);
+               result.data.f = *(float*)data;
                break;
        case MONO_TYPE_R8:
                result.type = VAL_DOUBLE;
-               result.data.f = *(double*)(data + offset);
+               result.data.f = *(double*)data;
                break;
        case MONO_TYPE_STRING:
        case MONO_TYPE_SZARRAY:
        case MONO_TYPE_CLASS:
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_ARRAY:
+       case MONO_TYPE_PTR:
                result.type = VAL_OBJ;
-               result.data.p = *(gpointer*)(data + offset);
-               break; 
+               result.data.p = *(gpointer*)data;
+               break;
        default:
                g_warning ("got type %x", type->type);
                g_assert_not_reached ();
@@ -241,36 +340,41 @@ stackval_from_data (MonoType *type, const char *data, guint offset)
 }
 
 static void
-stackval_to_data (MonoType *type, stackval *val, char *data, guint offset)
+stackval_to_data (MonoType *type, stackval *val, char *data)
 {
+       if (type->byref) {
+               *(gpointer*)data = val->data.p;
+               return;
+       }
        switch (type->type) {
        case MONO_TYPE_I1:
        case MONO_TYPE_U1:
-               *(guint8*)(data + offset) = val->data.i;
+               *(guint8*)data = val->data.i;
                break;
        case MONO_TYPE_BOOLEAN:
-               *(guint8*)(data + offset) = (val->data.i != 0);
+               *(guint8*)data = (val->data.i != 0);
                break;
        case MONO_TYPE_I2:
        case MONO_TYPE_U2:
-               *(guint16*)(data + offset) = val->data.i;
+               *(guint16*)data = val->data.i;
                break;
        case MONO_TYPE_I4:
        case MONO_TYPE_U4:
-               *(gint32*)(data + offset) = val->data.i;
+               *(gint32*)data = val->data.i;
                break;
        case MONO_TYPE_R4:
-               *(float*)(data + offset) = val->data.f;
+               *(float*)data = val->data.f;
                break;
        case MONO_TYPE_R8:
-               *(double*)(data + offset) = val->data.f;
+               *(double*)data = val->data.f;
                break;
        case MONO_TYPE_STRING:
        case MONO_TYPE_SZARRAY:
        case MONO_TYPE_CLASS:
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_ARRAY:
-               *(gpointer*)(data + offset) = val->data.p;
+       case MONO_TYPE_PTR:
+               *(gpointer*)data = val->data.p;
                break;
        default:
                g_warning ("got type %x", type->type);
@@ -384,7 +488,8 @@ ves_pinvoke_method (MonoMethod *mh, stackval *sp)
        g_slist_free (l);
 
        if (mh->signature->ret->type)
-               *sp = stackval_from_data (mh->signature->ret->type, res, 0);
+               *sp = stackval_from_data (mh->signature->ret->type, res);
+                       
 }
 
 #define DEBUG_INTERP 0
@@ -394,6 +499,7 @@ static char *opcode_names[] = {
 #include "mono/cil/opcode.def"
        NULL
 };
+#undef OPDEF
 
 static void
 output_indent (void)
@@ -428,13 +534,32 @@ dump_stack (stackval *stack, stackval *sp)
 
 #endif
 
-#define DEFAULT_LOCALS_SIZE    64
+static MonoType 
+method_this = {
+       MONO_TYPE_CLASS, 
+       0, 
+       1, /* byref */
+       0,
+       {0}
+};
+
+#define LOCAL_POS(n)            (locals_pointers [(n)])
+#define LOCAL_TYPE(header, n)   ((header)->locals [(n)])
+
+#define ARG_POS(n)              (args_pointers [(n)])
+#define ARG_TYPE(sig, n)        ((n) ? (sig)->params [(n) - (sig)->hasthis]->type : \
+                               (sig)->hasthis ? &method_this: (sig)->params [(0)]->type)
+
+#define THROW_EX(exception,ex_ip)      \
+               do {\
+                       frame->ip = (ex_ip);            \
+                       frame->ex = (exception);        \
+                       goto handle_exception;  \
+               } while (0)
 
 /*
  * Need to optimize ALU ops when natural int == int32 
  *
- * Need to design how exceptions are supposed to work...
- *
  * IDEA: if we maintain a stack of ip, sp to be checked
  * in the return opcode, we could inline simple methods that don't
  * use the stack or local variables....
@@ -442,68 +567,109 @@ dump_stack (stackval *stack, stackval *sp)
  * The {,.S} versions of many opcodes can/should be merged to reduce code
  * duplication.
  * 
- * -fomit-frame-pointer gives about 2% speedup. 
  */
 static void 
-ves_exec_method (MonoMethod *mh, stackval *args)
+ves_exec_method (MonoInvocation *frame)
 {
-       MonoMethodNormal *mm = (MonoMethodNormal *)mh;
-       stackval *stack;
+       MonoInvocation child_frame;
+       MonoMethodHeader *header;
+       MonoMethodSignature *signature;
+       MonoImage *image;
+       const unsigned char *endfinally_ip;
        register const unsigned char *ip;
        register stackval *sp;
-       char locals_store [DEFAULT_LOCALS_SIZE];
-       char *locals = locals_store;
+       void **locals_pointers;
+       void **args_pointers;
        GOTO_LABEL_VARS;
 
-       if (mh->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
-               ICallMethod icall = mh->addr;
+       if (frame->method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
+               ICallMethod icall = frame->method->addr;
 
-               icall (mh, args);
+               icall (frame->method, frame->stack_args);
                return;
        }
 
-       if (mh->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
-               ves_pinvoke_method (mh, args);
+       if (frame->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+               ves_pinvoke_method (frame->method, frame->stack_args);
                return;
        } 
 
-       ip = mm->header->code;
+       header = ((MonoMethodNormal *)frame->method)->header;
+       signature = frame->method->signature;
+       image = frame->method->image;
 
 #if DEBUG_INTERP
        debug_indent_level++;
        output_indent ();
-       g_print ("Entering %s\n", mh->name);
+       g_print ("Entering %s\n", frame->method->name);
 #endif
 
        /*
         * with alloca we get the expected huge performance gain
-        * stackval *stack = g_new0(stackval, mh->max_stack);
+        * stackval *stack = g_new0(stackval, header->max_stack);
         */
-       /* We allocate one more stack val and increase stack temporarily to handle
-        * passing this to instance methods: this needs to be removed when we'll
-        * use a different argument passing mechanism.
-        */
 
-       stack = alloca (sizeof (stackval) * (mm->header->max_stack + 1));
-       sp = stack + 1;
-       ++stack;
-
-       if (mm->header->num_locals && mm->header->locals_offsets [0] > DEFAULT_LOCALS_SIZE) {
-               locals = alloca (mm->header->locals_offsets [0]);
+       sp = frame->stack = alloca (sizeof (stackval) * header->max_stack);
+
+       if (header->num_locals) {
+               int i, align, size, offset = 0;
+
+               frame->locals = alloca (header->locals_size);
+               locals_pointers = alloca (sizeof(void*) * header->num_locals);
+               /* 
+                * yes, we do it unconditionally, because it needs to be done for
+                * some cases anyway and checking for that would be even slower.
+                */
+               memset (frame->locals, 0, header->locals_size);
+               for (i = 0; i < header->num_locals; ++i) {
+                       locals_pointers [i] = frame->locals + offset;
+                       size = mono_type_size (header->locals [i], &align);
+                       offset += offset % align;
+                       offset += size;
+               }
+       }
+       /*
+        * Copy args from stack_args to args.
+        */
+       if (signature->params_size) {
+               int i, align, size, offset = 0;
+               int has_this = signature->hasthis;
+
+               frame->args = alloca (signature->params_size);
+               args_pointers = alloca (sizeof(void*) * (signature->param_count + has_this));
+               if (has_this) {
+                       args_pointers [0] = frame->args;
+                       *(gpointer*) frame->args = frame->obj;
+                       offset += sizeof (gpointer);
+               }
+               for (i = 0; i < signature->param_count; ++i) {
+                       args_pointers [i + has_this] = frame->args + offset;
+                       stackval_to_data (signature->params [i]->type, frame->stack_args + i, frame->args + offset);
+                       size = mono_type_size (signature->params [i]->type, &align);
+                       offset += offset % align;
+                       offset += size;
+               }
        }
 
+       child_frame.parent = frame;
+       frame->child = &child_frame;
+       frame->ex = NULL;
+
+       /* ready to go */
+       ip = header->code;
+
        /*
         * using while (ip < end) may result in a 15% performance drop, 
         * but it may be useful for debug
         */
        while (1) {
+       main_loop:
                /*g_assert (sp >= stack);*/
 #if DEBUG_INTERP
-               dump_stack (stack, sp);
+               dump_stack (frame->stack, sp);
                g_print ("\n");
                output_indent ();
-               g_print ("0x%04x: %s\n",
-                        ip-(unsigned char*)mm->header->code,
+               g_print ("0x%04x: %s\n", ip-header->code,
                         *ip == 0xfe ? opcode_names [256 + ip [1]] : opcode_names [*ip]);
 #endif
                
@@ -518,19 +684,20 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                CASE (CEE_LDARG_0)
                CASE (CEE_LDARG_1)
                CASE (CEE_LDARG_2)
-               CASE (CEE_LDARG_3)
-                       *sp = args [(*ip)-CEE_LDARG_0];
-                       ++sp;
+               CASE (CEE_LDARG_3) {
+                       int n = (*ip)-CEE_LDARG_0;
                        ++ip;
+                       *sp = stackval_from_data (ARG_TYPE (signature, n), ARG_POS (n));
+                       ++sp;
                        BREAK;
+               }
                CASE (CEE_LDLOC_0)
                CASE (CEE_LDLOC_1)
                CASE (CEE_LDLOC_2)
                CASE (CEE_LDLOC_3) {
                        int n = (*ip)-CEE_LDLOC_0;
                        ++ip;
-                       *sp = stackval_from_data (mm->header->locals [n], locals,
-                               n ? mm->header->locals_offsets [n]: 0);
+                       *sp = stackval_from_data (LOCAL_TYPE (header, n), LOCAL_POS (n));
                        ++sp;
                        BREAK;
                }
@@ -541,43 +708,40 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                        int n = (*ip)-CEE_STLOC_0;
                        ++ip;
                        --sp;
-                       stackval_to_data (mm->header->locals [n], sp, locals,
-                               n ? mm->header->locals_offsets [n]: 0);
+                       stackval_to_data (LOCAL_TYPE (header, n), sp, LOCAL_POS (n));
                        BREAK;
                }
                CASE (CEE_LDARG_S)
                        ++ip;
-                       *sp = args [*ip];
+                       *sp = stackval_from_data (ARG_TYPE (signature, *ip), ARG_POS (*ip));
                        ++sp;
                        ++ip;
                        BREAK;
                CASE (CEE_LDARGA_S)
                        ++ip;
                        sp->type = VAL_TP;
-                       sp->data.p = &(args [*ip]);
+                       sp->data.p = ARG_POS (*ip);
                        ++sp;
                        ++ip;
                        BREAK;
                CASE (CEE_STARG_S) ves_abort(); BREAK;
                CASE (CEE_LDLOC_S)
                        ++ip;
-                       *sp = stackval_from_data (mm->header->locals [*ip], locals,
-                               *ip ? mm->header->locals_offsets [*ip]: 0);
+                       *sp = stackval_from_data (LOCAL_TYPE (header, *ip), LOCAL_POS (*ip));
                        ++ip;
                        ++sp;
                        BREAK;
                CASE (CEE_LDLOCA_S)
                        ++ip;
                        sp->type = VAL_TP;
-                       sp->data.p = locals + (*ip ? mm->header->locals_offsets [*ip]: 0);
+                       sp->data.p = LOCAL_POS (*ip);
                        ++sp;
                        ++ip;
                        BREAK;
                CASE (CEE_STLOC_S)
                        ++ip;
                        --sp;
-                       stackval_to_data (mm->header->locals [*ip], sp, locals,
-                               *ip ? mm->header->locals_offsets [*ip]: 0);
+                       stackval_to_data (LOCAL_TYPE (header, *ip), sp, LOCAL_POS (*ip));
                        ++ip;
                        BREAK;
                CASE (CEE_LDNULL) 
@@ -656,45 +820,69 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                CASE (CEE_JMP) ves_abort(); BREAK;
                CASE (CEE_CALLVIRT) /* Fall through */
                CASE (CEE_CALL) {
-                       MonoMethod *cmh;
+                       MonoMethodSignature *csignature;
+                       stackval retval;
                        guint32 token;
                        int virtual = *ip == CEE_CALLVIRT;
 
+                       frame->ip = ip;
+                       
                        ++ip;
                        token = read32 (ip);
                        ip += 4;
                        if (virtual)
-                               cmh = get_virtual_method (mh->image, token, sp);
+                               child_frame.method = get_virtual_method (image, token, sp);
                        else
-                               cmh = mono_get_method (mh->image, token);
-                       g_assert (cmh->signature->call_convention == MONO_CALL_DEFAULT);
+                               child_frame.method = mono_get_method (image, token);
+                       csignature = child_frame.method->signature;
+                       g_assert (csignature->call_convention == MONO_CALL_DEFAULT);
 
                        /* decrement by the actual number of args */
-                       sp -= cmh->signature->param_count;
-                       if (cmh->signature->hasthis) {
-                               g_assert (sp >= stack);
+                       if (csignature->param_count) {
+                               sp -= csignature->param_count;
+                               child_frame.stack_args = sp;
+                       } else {
+                               child_frame.stack_args = NULL;
+                       }
+                       if (csignature->hasthis) {
+                               g_assert (sp >= frame->stack);
                                --sp;
                                g_assert (sp->type == VAL_OBJ);
+                               child_frame.obj = sp->data.p;
+                       } else {
+                               child_frame.obj = NULL;
+                       }
+                       if (csignature->ret->type) {
+                               /* FIXME: handle valuetype */
+                               child_frame.retval = &retval;
+                       } else {
+                               child_frame.retval = NULL;
+                       }
+                       ves_exec_method (&child_frame);
+                       if (child_frame.ex) {
+                               /*
+                                * An exception occurred, need to run finally, fault and catch handlers..
+                                */
+                               frame->ex = child_frame.ex;
+                               goto handle_finally;
                        }
-
-                       /* we need to truncate according to the type of args ... */
-                       ves_exec_method (cmh, sp);
 
                        /* need to handle typedbyref ... */
-                       if (cmh->signature->ret->type)
+                       if (csignature->ret->type) {
+                               *sp = retval;
                                sp++;
+                       }
                        BREAK;
                }
                CASE (CEE_CALLI) ves_abort(); BREAK;
                CASE (CEE_RET)
-                       if (mh->signature->ret->type) {
+                       if (signature->ret->type) {
                                --sp;
-                               *args = *sp;
+                               *frame->retval = *sp;
                        }
-                       if (sp > stack)
-                               g_warning ("more values on stack: %d", sp-stack);
+                       if (sp > frame->stack)
+                               g_warning ("more values on stack: %d", sp-frame->stack);
 
-                       /* g_free (stack); */
 #if DEBUG_INTERP
                        debug_indent_level--;
 #endif
@@ -1069,9 +1257,14 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                CASE (CEE_DIV)
                        ++ip;
                        --sp;
-                       if (sp->type == VAL_I32)
+                       if (sp->type == VAL_I32) {
+                               /* 
+                                * FIXME: move to handle also the other types
+                                */
+                               if (GET_NATI (sp [0]) == 0)
+                                       THROW_EX (get_exception_divide_by_zero (), ip - 1);
                                sp [-1].data.i /= GET_NATI (sp [0]);
-                       else if (sp->type == VAL_I64)
+                       else if (sp->type == VAL_I64)
                                sp [-1].data.l /= sp [0].data.l;
                        else if (sp->type == VAL_DOUBLE)
                                sp [-1].data.f /= sp [0].data.f;
@@ -1225,11 +1418,10 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                CASE (CEE_LDOBJ) ves_abort(); BREAK;
                CASE (CEE_LDSTR) {
                        guint32 ctor, ttoken;
-                       MonoMetadata *m = &mh->image->metadata;
-                       MonoMethod *cmh;
+                       MonoMetadata *m = &image->metadata;
                        MonoObject *o;
                        MonoImage *cl;
-                       const char *name;
+                       const char *name;
                        int len;
                        guint32 index;
                        guint16 *data;
@@ -1253,16 +1445,17 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                        
                        g_assert (o != NULL);
 
-                       cmh = mono_get_method (cl, ctor);
+                       child_frame.method = mono_get_method (cl, ctor);
 
-                       sp->type = VAL_OBJ;
-                       sp->data.p = o;
+                       child_frame.obj = o;
+                       
+                       sp->type = VAL_TP;
+                       sp->data.p = data;
                        
-                       sp[1].type = VAL_TP;
-                       sp[1].data.p = data;
+                       child_frame.stack_args = sp;
 
-                       g_assert (cmh->signature->call_convention == MONO_CALL_DEFAULT);
-                       ves_exec_method (cmh, sp);
+                       g_assert (child_frame.method->signature->call_convention == MONO_CALL_DEFAULT);
+                       ves_exec_method (&child_frame);
 
                        g_free (data);
 
@@ -1273,36 +1466,36 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                }
                CASE (CEE_NEWOBJ) {
                        MonoObject *o;
-                       MonoMethod *cmh;
+                       MonoMethodSignature *csig;
                        guint32 token;
-                       int pc;
 
                        ip++;
                        token = read32 (ip);
-                       o = newobj (mh->image, token);
+                       o = newobj (image, token);
                        ip += 4;
                        
                        /* call the contructor */
-                       cmh = mono_get_method (mh->image, token);
+                       child_frame.method = mono_get_method (image, token);
+                       csig = child_frame.method->signature;
 
                        /*
-                        * decrement by the actual number of args 
-                        * need to pass object as first arg: we may overflow the stack here
-                        * until we use a different argument passing mechanism. 
-                        * we shift the args to make room for the object reference
+                        * First arg is the object.
                         */
-                       for (pc = 0; pc < cmh->signature->param_count; ++pc)
-                               sp [-pc] = sp [-pc-1];
-                       sp -= cmh->signature->param_count + 1;
-                       sp->type = VAL_OBJ;
-                       sp->data.p = o;
+                       child_frame.obj = o;
 
-                       g_assert (cmh->signature->call_convention == MONO_CALL_DEFAULT);
+                       if (csig->param_count) {
+                               sp -= csig->param_count;
+                               child_frame.stack_args = sp;
+                       } else {
+                               child_frame.stack_args = NULL;
+                       }
+
+                       g_assert (csig->call_convention == MONO_CALL_DEFAULT);
 
+                       ves_exec_method (&child_frame);
                        /*
-                        * we need to truncate according to the type of args ...
+                        * FIXME: check for exceptions
                         */
-                       ves_exec_method (cmh, sp);
                        /*
                         * a constructor returns void, but we need to return the object we created
                         */
@@ -1311,7 +1504,6 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                        ++sp;
                        BREAK;
                }
-               
                CASE (CEE_CASTCLASS) {
                        MonoObject *o;
                        MonoClass *c;
@@ -1357,7 +1549,7 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                        ++ip;
                        token = read32 (ip);
                        
-                       c = mono_class_get (mh->image, token);
+                       c = mono_class_get (image, token);
                        
                        o = sp [-1].data.p;
 
@@ -1369,7 +1561,10 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                        ip += 4;
                        BREAK;
                }
-               CASE (CEE_THROW) ves_abort(); BREAK;
+               CASE (CEE_THROW)
+                       --sp;
+                       THROW_EX (sp->data.p, ip);
+                       BREAK;
                CASE (CEE_LDFLD) {
                        MonoObject *obj;
                        MonoClassField *field;
@@ -1383,7 +1578,7 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                        obj = sp [-1].data.p;
                        field = mono_class_get_field (obj->klass, token);
                        g_assert (field);
-                       sp [-1] = stackval_from_data (field->type->type, (char*)obj, field->offset);
+                       sp [-1] = stackval_from_data (field->type->type, (char*)obj + field->offset);
                        BREAK;
                }
                CASE (CEE_LDFLDA) ves_abort(); BREAK;
@@ -1402,7 +1597,7 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                        obj = sp [0].data.p;
                        field = mono_class_get_field (obj->klass, token);
                        g_assert (field);
-                       stackval_to_data (field->type->type, &sp [1], (char*)obj, field->offset);
+                       stackval_to_data (field->type->type, &sp [1], (char*)obj + field->offset);
                        BREAK;
                }
                CASE (CEE_LDSFLD) {
@@ -1415,11 +1610,11 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                        ip += 4;
                        
                        /* need to handle fieldrefs */
-                       klass = mono_class_get (mh->image, 
-                               MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (&mh->image->metadata, token & 0xffffff));
+                       klass = mono_class_get (image, 
+                               MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (&image->metadata, token & 0xffffff));
                        field = mono_class_get_field (klass, token);
                        g_assert (field);
-                       *sp = stackval_from_data (field->type->type, (char*)klass, field->offset);
+                       *sp = stackval_from_data (field->type->type, (char*)klass + field->offset);
                        ++sp;
                        BREAK;
                }
@@ -1435,11 +1630,11 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                        --sp;
 
                        /* need to handle fieldrefs */
-                       klass = mono_class_get (mh->image, 
-                               MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (&mh->image->metadata, token & 0xffffff));
+                       klass = mono_class_get (image, 
+                               MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (&image->metadata, token & 0xffffff));
                        field = mono_class_get_field (klass, token);
                        g_assert (field);
-                       stackval_to_data (field->type->type, sp, (char*)klass, field->offset);
+                       stackval_to_data (field->type->type, sp, (char*)klass + field->offset);
                        BREAK;
                }
                CASE (CEE_STOBJ) ves_abort(); BREAK;
@@ -1460,7 +1655,7 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                        token = read32 (ip);
 
                        sp [-1].type = VAL_OBJ;
-                       sp [-1].data.p = mono_value_box (mh->image, token, 
+                       sp [-1].data.p = mono_value_box (image, token, 
                                                         &sp [-1]);
 
                        ip += 4;
@@ -1473,7 +1668,7 @@ ves_exec_method (MonoMethod *mh, stackval *args)
 
                        ip++;
                        token = read32 (ip);
-                       o = mono_new_szarray (mh->image, token, sp [-1].data.i);
+                       o = mono_new_szarray (image, token, sp [-1].data.i);
                        ip += 4;
 
                        sp [-1].type = VAL_OBJ;
@@ -1704,9 +1899,34 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                CASE (CEE_MUL_OVF_UN) ves_abort(); BREAK;
                CASE (CEE_SUB_OVF) ves_abort(); BREAK;
                CASE (CEE_SUB_OVF_UN) ves_abort(); BREAK;
-               CASE (CEE_ENDFINALLY) ves_abort(); BREAK;
+               CASE (CEE_ENDFINALLY)
+                       if (frame->ex)
+                               goto handle_fault;
+                       /*
+                        * There was no exception, we continue normally at the target address.
+                        */
+                       ip = endfinally_ip;
+                       BREAK;
                CASE (CEE_LEAVE) ves_abort(); BREAK;
-               CASE (CEE_LEAVE_S) ves_abort(); BREAK;
+               CASE (CEE_LEAVE_S)
+                       ++ip;
+                       ip += (signed char) *ip;
+                       /*
+                        * We may be either inside a try block or inside an handler.
+                        * In the first case there was no exception and we go on
+                        * executing the finally handlers and after that resume control
+                        * at endfinally_ip.
+                        * In the second case we need to clear the exception and
+                        * continue directly at the target ip.
+                        */
+                       if (frame->ex) {
+                               frame->ex = NULL;
+                               frame->ex_handler = NULL;
+                       } else {
+                               endfinally_ip = ip;
+                               goto handle_finally;
+                       }
+                       BREAK;
                CASE (CEE_STIND_I) ves_abort(); BREAK;
                CASE (CEE_UNUSED26) 
                CASE (CEE_UNUSED27) 
@@ -1777,7 +1997,7 @@ ves_exec_method (MonoMethod *mh, stackval *args)
                        case CEE_UNUSED55: 
                        case CEE_UNUSED70: 
                        default:
-                               g_error ("Unimplemented opcode: 0xFE %02x at 0x%x\n", *ip, ip-(unsigned char*)mm->header->code);
+                               g_error ("Unimplemented opcode: 0xFE %02x at 0x%x\n", *ip, ip-header->code);
                        }
                        continue;
                DEFAULT;
@@ -1785,6 +2005,110 @@ ves_exec_method (MonoMethod *mh, stackval *args)
        }
 
        g_assert_not_reached ();
+       /*
+        * Exception handling code.
+        * The exception object is stored in frame->ex.
+        */
+#define OFFSET_IN_CLAUSE(clause,offset) \
+       ((clause)->try_offset <= (offset) && (offset) < ((clause)->try_offset + (clause)->try_len))
+
+       handle_exception:
+       {
+               int i;
+               guint32 ip_offset;
+               MonoInvocation *inv;
+               MonoMethodHeader *hd;
+               MonoExceptionClause *clause;
+               
+               for (inv = frame; inv; inv = inv->parent) {
+                       hd = ((MonoMethodNormal*)inv->method)->header;
+                       ip_offset = inv->ip - hd->code;
+                       for (i = 0; i < hd->num_clauses; ++i) {
+                               clause = &hd->clauses [i];
+                               if (clause->flags <= 1 && OFFSET_IN_CLAUSE (clause, ip_offset)) {
+                                       if (!clause->flags && mono_isinst (frame->ex, mono_class_get (inv->method->image, clause->token_or_filter))) {
+                                                       /* 
+                                                        * OK, we found an handler, now we need to execute the finally
+                                                        * and fault blocks before branching to the handler code.
+                                                        */
+                                                       inv->ex_handler = clause;
+                                                       goto handle_finally;
+                                       } else {
+                                               /* FIXME: handle filter clauses */
+                                               g_assert (0);
+                                       }
+                               }
+                       }
+               }
+               /*
+                * If we get here, no handler was found: print a stack trace.
+                */
+               for (inv = frame, i = 0; inv; inv = inv->parent, ++i) {
+                       /*
+                        * FIXME: print out also the arguments passed to the func.
+                        */
+                       g_print ("Unhandled exception.\n");
+                       g_print ("$%d: %s ()\n", i, inv->method->name);
+               }
+               exit (1);
+       }
+       handle_finally:
+       {
+               int i;
+               guint32 ip_offset;
+               MonoExceptionClause *clause;
+               
+               ip_offset = frame->ip - header->code;
+               for (i = 0; i < header->num_clauses; ++i) {
+                       clause = &header->clauses [i];
+                       if (clause->flags == 2 && OFFSET_IN_CLAUSE (clause, ip_offset)) {
+                               ip = header->code + clause->handler_offset;
+                               goto main_loop;
+                       }
+               }
+               /*
+                * If an exception is set, we need to execute the fault handler, too,
+                * otherwise, we continue normally.
+                */
+               if (frame->ex)
+                       goto handle_fault;
+               ip = endfinally_ip;
+               goto main_loop;
+       }
+       handle_fault:
+       {
+               int i;
+               guint32 ip_offset;
+               MonoExceptionClause *clause;
+               
+               ip_offset = frame->ip - header->code;
+               for (i = 0; i < header->num_clauses; ++i) {
+                       clause = &header->clauses [i];
+                       if (clause->flags == 3 && OFFSET_IN_CLAUSE (clause, ip_offset)) {
+                               ip = header->code + clause->handler_offset;
+                               goto main_loop;
+                       }
+               }
+               /*
+                * If the handler for the exception was found in this method, we jump
+                * to it right away, otherwise we return and let the caller run
+                * the finally, fault and catch blocks.
+                * This same code should be present in the endfault opcode, but it
+                * is corrently not assigned in the ECMA specs: LAMESPEC.
+                */
+               if (frame->ex_handler) {
+                       ip = header->code + frame->ex_handler->handler_offset;
+                       sp = frame->stack;
+                       sp->type = VAL_OBJ;
+                       sp->data.p = frame->ex;
+                       goto main_loop;
+               }
+#if DEBUG_INTERP
+               debug_indent_level--;
+#endif
+               return;
+       }
+       
 }
 
 static int 
@@ -1793,15 +2117,17 @@ ves_exec (MonoAssembly *assembly)
        MonoImage *image = assembly->image;
        MonoCLIImageInfo *iinfo;
        stackval result;
-       MonoMethod *mh;
+       MonoInvocation call;
 
        iinfo = image->image_info;
        
-       /* we need to exec the class and object constructors... */
-       mh = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point);
-       ves_exec_method (mh, &result);
-       fprintf (stderr, "result: %d\n", result.data.i);
-       mono_free_method (mh);
+       call.parent = NULL;
+       call.obj = NULL;
+       call.stack_args = NULL;
+       call.method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point);
+       call.retval = &result;
+       ves_exec_method (&call);
+       mono_free_method (call.method);
 
        return result.data.i;
 }
@@ -1825,6 +2151,8 @@ main (int argc, char *argv [])
 
        file = argv [1];
 
+       corlib = mono_get_corlib ();
+
        assembly = mono_assembly_open (file, NULL, NULL);
        if (!assembly){
                fprintf (stderr, "Can not open image %s\n", file);
index 584e058ba51d22da0daac575929e7b7d0661dd0e..7faa223f76eaa516130cdc3768301e9d1623b842 100644 (file)
@@ -2,15 +2,22 @@
 #include <glib.h>
 
 enum {
-       VAL_I32,
-       VAL_I64,
-       VAL_DOUBLE,
-       VAL_NATI,
-       VAL_MP,
-       VAL_TP,
-       VAL_OBJ
+       VAL_I32     = 0,
+       VAL_DOUBLE  = 1,
+       VAL_I64     = 2,
+       VAL_VALUET  = 3,
+       VAL_POINTER = 4,
+       VAL_NATI    = 0 + VAL_POINTER,
+       VAL_MP      = 1 + VAL_POINTER,
+       VAL_TP      = 2 + VAL_POINTER,
+       VAL_OBJ     = 3 + VAL_POINTER
 };
 
+/*
+ * Value types are represented on the eval stack as pointers to the
+ * actual storage. The size field tells how much storage is allocated.
+ * A value type can't be larger than 16 MB.
+ */
 typedef struct {
        union {
                gint32 i;
@@ -19,6 +26,25 @@ typedef struct {
                /* native size integer and pointer types */
                gpointer p;
        } data;
-       int type;
+       unsigned int type : 8;
+       unsigned int size : 24; /* used for value types */
 } stackval;
 
+typedef struct _MonoInvocation MonoInvocation;
+
+struct _MonoInvocation {
+       MonoInvocation *parent; /* parent */
+       MonoInvocation *child;
+       MonoMethod     *method; /* parent */
+       stackval       *retval; /* parent */
+       void           *obj;    /* this - parent */
+       char           *locals;
+       char           *args;
+       stackval       *stack_args; /* parent */
+       stackval       *stack;
+       /* exception info */
+       const unsigned char  *ip;
+       MonoObject     *ex;
+       MonoExceptionClause *ex_handler;
+};
+
index 67b2c4f85532631617bade732fd5fdbdb898b7ee..7bfb724831e3fb16044ee985aa544d914535234b 100644 (file)
@@ -1,3 +1,8 @@
+Sat Aug 18 12:51:28 CEST 2001 Paolo Molaro <lupus@ximian.com>
+
+       * metadata.c, metadata.h: in the signature and method header store
+       only the space required for holding the loca vars and incoming arguments.
+
 2001-08-09  Dietmar Maurer  <dietmar@ximian.com>
 
        * image.c (do_mono_image_open): added a cache for arrays.
index 300975441e5e426932fdca3f8b2967d5e9e4530d..fbafd5f54f9c550bf83b2508e4025249aee53ac6 100644 (file)
@@ -234,6 +234,14 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
                g_assert (class->instance_size == sizeof (MonoArrayObject));
        }
 
+       if (class->method.count > 0) {
+               int i;
+               class->methods = g_new (MonoMethod*, class->method.count);
+               for (i = class->method.first; i < class->method.last; ++i)
+                       class->methods [i - class->method.first] = mono_get_method (image,
+                                                       MONO_TOKEN_METHOD_DEF | (i + 1));
+       }
+       
        class = g_malloc0 (class->class_size);
        *class = stack_class;
        return class;
index 501f2db876fdd6cce6308a40a889a70c8ab84d27..8928f7e3c196565620bb1aa7fb38111f21d5fee0 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <mono/metadata/metadata.h>
 #include <mono/metadata/image.h>
+#include <mono/cli/cli.h>
 
 #define MONO_CLASS_IS_ARRAY(c) (c->type_token == 0)
 
@@ -43,6 +44,9 @@ struct _MonoClass {
         * Field information: Type and location from object base
         */
        MonoClassField *fields;
+       
+       struct MonoMethod **methods;
+
        /*
         * After the fields, there is room for the static fields...
         */
index 91028942fa96cb3c5f448ace187cf7b27fa32a1e..70298c78e03ea12d1110d776447d5f3543d8f56c 100644 (file)
@@ -283,7 +283,7 @@ mono_lookup_internal_call (const char *name)
 
                icall_hash = g_hash_table_new (g_str_hash , g_str_equal);
                
-               while (n = icall_map [i]) {
+               while ((n = icall_map [i])) {
                        g_hash_table_insert (icall_hash, n, icall_map [i+1]);
                        i += 2;
                }
index cdebca3f46449e7876aea9749dab273aa1f2f2e5..c61b3880a1fc9ce646745124640c2b9a57f75140 100644 (file)
@@ -184,7 +184,7 @@ load_cli_header (MonoImage *image, MonoCLIImageInfo *iinfo)
            (iinfo->cli_cli_header.ch_ridmap.rva != 0) ||
            (iinfo->cli_cli_header.ch_debug_map.rva != 0) ||
            (iinfo->cli_cli_header.ch_ip_map.rva != 0)){
-               g_message ("Some fields in the CLI header which should have been zero are not zero");
+               g_warning ("Some fields in the CLI header which should have been zero are not zero");
        }
            
        return TRUE;
index c984351f81c261d54e543bae7040caeb8262487c..930eff1587f0a67c8253bb193464b58bad433fb2 100644 (file)
@@ -1021,7 +1021,7 @@ MonoMethodSignature *
 mono_metadata_parse_method_signature (MonoMetadata *m, int def, const char *ptr, const char **rptr)
 {
        MonoMethodSignature *method = g_new0(MonoMethodSignature, 1);
-       int i, align;
+       int i, align, offset = 0;
 
        if (*ptr & 0x20)
                method->hasthis = 1;
@@ -1032,16 +1032,14 @@ mono_metadata_parse_method_signature (MonoMetadata *m, int def, const char *ptr,
        method->param_count = mono_metadata_decode_value (ptr, &ptr);
        method->ret = mono_metadata_parse_param (m, 1, ptr, &ptr);
 
+       if (method->hasthis)
+               offset += sizeof(gpointer);
        if (method->param_count) {
-               int size, offset = 0;
+               int size;
                
                method->params = g_new0(MonoParam*, method->param_count);
-               method->param_offsets = g_new0(guint, method->param_count);
                method->sentinelpos = -1;
                
-               if (method->hasthis)
-                       offset += sizeof(gpointer);
-               
                for (i = 0; i < method->param_count; ++i) {
                        if (*ptr == MONO_TYPE_SENTINEL) {
                                if (method->call_convention != MONO_CALL_VARARG || def)
@@ -1050,23 +1048,12 @@ mono_metadata_parse_method_signature (MonoMetadata *m, int def, const char *ptr,
                                ptr++;
                        }
                        method->params [i] = mono_metadata_parse_param (m, 0, ptr, &ptr);
-                       method->param_offsets [i] = offset;
                        size = mono_type_size (method->params [i]->type, &align);
                        offset += (offset % align);
                        offset += size;
                }
-               /*
-                * The offset of the first item is always 0, so we use the slot
-                * to store how much data we need in total.
-                */
-                method->param_offsets [0] = MAX (offset, mono_type_size (method->ret->type, &align));
-       } else {
-               /* FIXME: hasthis */
-               if (method->hasthis)
-                       method->param_offsets = GUINT_TO_POINTER (MAX (sizeof (gpointer), mono_type_size (method->ret->type, &align)));
-               else
-                       method->param_offsets = GUINT_TO_POINTER (mono_type_size (method->ret->type, &align));
        }
+       method->params_size = offset;
 
        if (rptr)
                *rptr = ptr;
@@ -1081,8 +1068,6 @@ mono_metadata_free_method_signature (MonoMethodSignature *method)
        for (i = 0; i < method->param_count; ++i)
                mono_metadata_free_param (method->params[i]);
 
-       if (method->param_count)
-               g_free (method->param_offsets);
        g_free (method->params);
        g_free (method);
 }
@@ -1410,7 +1395,6 @@ mono_metadata_parse_mh (MonoMetadata *m, const char *ptr)
                if (!mh->num_locals)
                        return mh;
                mh->locals = g_new (MonoType*, len);
-               mh->locals_offsets = g_new0 (guint32, len);
                for (i = 0; i < len; ++i) {
                        int val;
                        int align;
@@ -1425,16 +1409,11 @@ mono_metadata_parse_mh (MonoMetadata *m, const char *ptr)
                                p = ptr;
                        }
                        mh->locals [i] = mono_metadata_parse_type (m, p, &ptr);
-                       mh->locals_offsets [i] = offset;
                        val = mono_type_size (mh->locals [i], &align);
                        offset += (offset % align);
                        offset += val;
                }
-               /*
-                * The offset of the first item is always 0, so we use the slot
-                * to store how much data we need in total.
-                */
-               mh->locals_offsets [0] = offset;
+               mh->locals_size = offset;
        }
        return mh;
 }
@@ -1446,7 +1425,6 @@ mono_metadata_free_mh (MonoMethodHeader *mh)
        for (i = 0; i < mh->num_locals; ++i)
                mono_metadata_free_type (mh->locals[i]);
        g_free (mh->locals);
-       g_free (mh->locals_offsets);
        g_free (mh->clauses);
        g_free (mh);
 }
index 29a3edcdb1fc72928a77d1315f1700c203716cf9..98b9ced0a5485c26b540842effe605f0deb006b3 100644 (file)
@@ -219,19 +219,19 @@ struct _MonoMethodSignature {
        guint16       sentinelpos;
        MonoRetType  *ret;
        MonoParam   **params;
-       guint32      *param_offsets;
+       guint32       params_size;
 };
 
 typedef struct {
        guint32      code_size;
-       const char  *code;
+       const unsigned char  *code;
        guint16      max_stack;
        unsigned int num_clauses : 15;
        /* if num_locals != 0, then the following apply: */
        unsigned int init_locals : 1;
        guint16      num_locals;
        MonoType   **locals;
-       guint32     *locals_offsets;
+       guint32      locals_size;
        MonoExceptionClause *clauses;
 } MonoMethodHeader;