+2001-09-23 Dietmar Maurer <dietmar@ximian.com>
+
+ * testjit.c: use the memory pool to avoid memory leaks
+
+2001-09-22 Dietmar Maurer <dietmar@ximian.com>
+
+ * x86.brg: increment the stack pointer after function calls
+
2001-09-21 Dick Porter <dick@ximian.com>
* Makefile.am (testjit_LDADD): Added PTHREAD_LIBS to the link line
jit.h \
regset.h \
regset.c \
+ mempool.c \
testjit.h \
testjit.c
#include "jit.h"
#include "testjit.h"
#include "regset.h"
+
/*
* Pull the list of opcodes
*/
#define MAKE_CJUMP(name) \
case CEE_##name: \
-case CEE_##name##_S: \
-{ \
+case CEE_##name##_S: { \
int near_jump = *ip == CEE_##name##_S; \
++ip; \
sp -= 2; \
- t1 = ctree_new (MB_TERM_##name, 0, sp [0], sp [1]); \
+ t1 = ctree_new (mp, MB_TERM_##name, 0, sp [0], sp [1]); \
if (near_jump) \
t1->data.i = cli_addr + 2 + (signed char) *ip; \
else \
break; \
}
-
+#define MAKE_BI_ALU(name) \
+case CEE_##name: { \
+ ++ip; \
+ sp -= 2; \
+ t1 = ctree_new (mp, MB_TERM_##name, 0, sp [0], sp [1]); \
+ t1->cli_addr = sp [0]->cli_addr; \
+ PUSH_TREE (t1); \
+ break; \
+}
+
/* Whether to dump the assembly code after genreating it */
gboolean dump_asm = FALSE;
static gpointer mono_compile_method (MonoMethod *method);
+/*
+ * allocates static data (we never free it). Such data is
+ * needed by the code generation to store constants. We should
+ * use something faster than g_malloc()
+ */
+inline static gpointer
+alloc_static (int size)
+{
+ return g_malloc (size);
+}
+
static MonoRegSet *
get_x86_regset ()
{
}
static MBTree *
-ctree_new (int op, MonoTypeEnum type, MBTree *left, MBTree *right)
+ctree_new (MonoMemPool *mp, int op, MonoTypeEnum type,
+ MBTree *left, MBTree *right)
{
- MBTree *t = g_malloc (sizeof (MBTree));
+ MBTree *t = mono_mempool_alloc0 (mp, sizeof (MBTree));
t->op = op;
t->left = left;
t->type = type;
t->reg1 = -1;
t->reg2 = -1;
- t->is_jump = 0;
- t->jump_target = 0;
- t->last_instr = 0;
- t->exclude_edx = 0;
t->cli_addr = -1;
- t->addr = 0;
- t->first_addr = 0;
- t->emit = NULL;
return t;
}
static MBTree *
-ctree_new_leaf (int op, MonoTypeEnum type)
+ctree_new_leaf (MonoMemPool *mp, int op, MonoTypeEnum type)
{
- return ctree_new (op, type, NULL, NULL);
+ return ctree_new (mp, op, type, NULL, NULL);
}
static void
}
static void
-forest_label (GPtrArray *forest)
+forest_label (MBCodeGenStatus *s)
{
+ GPtrArray *forest = s->forest;
const int top = forest->len;
int i;
for (i = 0; i < top; i++) {
MBTree *t1 = (MBTree *) g_ptr_array_index (forest, i);
- MBState *s;
+ MBState *mbstate;
- s = mono_burg_label (t1);
- if (!s) {
+ mbstate = mono_burg_label (t1, s);
+ if (!mbstate) {
g_warning ("tree does not match");
print_tree (t1); printf ("\n");
g_assert_not_reached ();
{
method->addr = s->start = s->code = g_malloc (1024);
- forest_label (s->forest);
+ forest_label (s);
forest_allocate_regs (s);
arch_emit_prologue (s);
MonoMethodHeader *header;
MonoMethodSignature *signature;
MonoImage *image;
+ MonoMemPool *mp;
MBTree **sp, **stack, *t1, *t2;
register const unsigned char *ip, *end;
guint *locals_offsets;
ip = header->code;
end = ip + header->code_size;
+ cgstat.mp = mp = mono_mempool_new ();
+
sp = stack = alloca (sizeof (MBTree *) * header->max_stack);
if (header->num_locals) {
guint32 cli_addr = ip - header->code;
switch (*ip) {
- case CEE_NOP:
+ case CEE_NOP: {
++ip;
break;
-
- case CEE_BREAK:
+ }
+ case CEE_BREAK: {
++ip;
- t1 = ctree_new_leaf (MB_TERM_BREAK, 0);
+ t1 = ctree_new_leaf (mp, MB_TERM_BREAK, 0);
t1->cli_addr = cli_addr;
ADD_TREE (t1);
break;
-
+ }
+/*
+ case CEE_SWITCH:
+ guint32 n;
+ const unsigned char *st;
+ ++ip;
+ n = read32 (ip);
+ ip += 4;
+ st = ip + 4 * n;
+ --sp;
+ if ((guint32)sp->data.i < n) {
+ gint offset;
+ ip += 4 * (guint32)sp->data.i;
+ offset = read32 (ip);
+ ip = st + offset;
+ } else {
+ ip = st;
+ }
+ break;
+ }
+*/
case CEE_CALL: {
MonoMethodSignature *csig;
MonoMethod *cm;
guint32 token, nargs;
- int i;
+ int i, align, size, offset = 0;
gint32 fa;
++ip;
fa = sp [-nargs]->cli_addr;
- for (i = 0; i < nargs; i++) {
+ for (i = nargs - 1; i >= 0; i--) {
sp--;
- t1 = ctree_new (MB_TERM_ARG, 0, *sp, NULL);
-
- if (i)
- t1->cli_addr = -1;
- else
- t1->cli_addr = fa;
-
+ t1 = ctree_new (mp, MB_TERM_ARG, 0, *sp, NULL);
ADD_TREE (t1);
+ if (!i && csig->hasthis)
+ size = mono_type_size (&cm->klass->this_arg, &align);
+ else
+ size = mono_type_size (cm->signature->params [i], &align);
+
+ // fixme: does this really work ?
+ offset += (size + 3) & ~3;
}
+ t1->cli_addr = fa;
fa = -1;
} else
fa = cli_addr;
-
+
cm->addr = create_jit_trampoline (cm);
if (csig->ret->type != MONO_TYPE_VOID) {
- int size, align;
- t1 = ctree_new_leaf (MB_TERM_CALL, csig->ret->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_CALL, csig->ret->type);
t1->data.p = cm;
- t2 = ctree_new (MB_TERM_STLOC, csig->ret->type, t1, NULL);
+ t1->size = offset;
+ t2 = ctree_new (mp, MB_TERM_STLOC, csig->ret->type, t1, NULL);
size = mono_type_size (csig->ret, &align);
local_offset += align - 1;
local_offset &= ~(align - 1);
t2->data.i = - local_offset;
t2->cli_addr = fa;
ADD_TREE (t2);
- t1 = ctree_new_leaf (MB_TERM_LDLOC, t2->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_LDLOC, t2->type);
t1->data.i = t2->data.i;
PUSH_TREE (t1);
} else {
- t1 = ctree_new_leaf (MB_TERM_CALL, MONO_TYPE_VOID);
+ t1 = ctree_new_leaf (mp, MB_TERM_CALL, MONO_TYPE_VOID);
t1->data.p = cm;
+ t1->size = offset;
t1->cli_addr = fa;
ADD_TREE (t1);
}
break;
}
- case CEE_LDC_I4_S:
+ case CEE_LDC_I4_S: {
++ip;
- t1 = ctree_new_leaf (MB_TERM_CONST_I4, MONO_TYPE_I4);
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_I4, MONO_TYPE_I4);
t1->data.i = *ip;
++ip;
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
break;
-
- case CEE_LDC_I4:
+ }
+ case CEE_LDC_I4: {
++ip;
- t1 = ctree_new_leaf (MB_TERM_CONST_I4, MONO_TYPE_I4);
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_I4, MONO_TYPE_I4);
t1->data.i = read32 (ip);
ip += 4;
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
break;
-
+ }
case CEE_LDC_I4_M1:
case CEE_LDC_I4_0:
case CEE_LDC_I4_1:
case CEE_LDC_I4_5:
case CEE_LDC_I4_6:
case CEE_LDC_I4_7:
- case CEE_LDC_I4_8:
- t1 = ctree_new_leaf (MB_TERM_CONST_I4, MONO_TYPE_I4);
+ case CEE_LDC_I4_8: {
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_I4, MONO_TYPE_I4);
t1->data.i = (*ip) - CEE_LDC_I4_0;
++ip;
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
break;
-
- case CEE_LDC_R8:
+ }
+ case CEE_LDNULL: {
+ //fixme: don't know if this is portable ?
++ip;
- t1 = ctree_new_leaf (MB_TERM_CONST_R8, MONO_TYPE_R8);
- (const void *) t1->data.p = ip;
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_I4, MONO_TYPE_I4);
+ t1->data.i = 0;
t1->cli_addr = cli_addr;
+ PUSH_TREE (t1);
+ break;
+ }
+ case CEE_LDC_I8: {
+ ++ip;
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_I8, MONO_TYPE_I8);
+ t1->data.l = read64 (ip);
ip += 8;
+ t1->cli_addr = cli_addr;
PUSH_TREE (t1);
break;
-
+ }
+ case CEE_LDC_R4: {
+ float *f = alloc_static (sizeof (float));
+ ++ip;
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_R4, MONO_TYPE_R4);
+ readr4 (ip, f);
+ t1->data.p = f;
+ t1->cli_addr = cli_addr;
+ ip += 4;
+ PUSH_TREE (t1);
+ break;
+ }
+ case CEE_LDC_R8: {
+ double *d = alloc_static (sizeof (double));
+ ++ip;
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_R8, MONO_TYPE_R8);
+ readr8 (ip, d);
+ t1->data.p = d;
+ t1->cli_addr = cli_addr;
+ ip += 8;
+ PUSH_TREE (t1);
+ break;
+ }
case CEE_LDLOC_0:
case CEE_LDLOC_1:
case CEE_LDLOC_2:
int n = (*ip) - CEE_LDLOC_0;
++ip;
- t1 = ctree_new_leaf (MB_TERM_LDLOC, LOCAL_TYPE (n)->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_LDLOC, LOCAL_TYPE (n)->type);
t1->data.i = LOCAL_POS (n);
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
case CEE_LDLOC_S: {
++ip;
- t1 = ctree_new_leaf (MB_TERM_LDLOC, LOCAL_TYPE (*ip)->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_LDLOC, LOCAL_TYPE (*ip)->type);
t1->data.i = LOCAL_POS (*ip);
t1->cli_addr = cli_addr;
++ip;
PUSH_TREE (t1);
break;
}
-
case CEE_STLOC_0:
case CEE_STLOC_1:
case CEE_STLOC_2:
++ip;
--sp;
- t1 = ctree_new (MB_TERM_STLOC, LOCAL_TYPE (n)->type, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_STLOC, LOCAL_TYPE (n)->type, *sp, NULL);
t1->data.i = LOCAL_POS (n);
t1->cli_addr = sp [0]->cli_addr;
ADD_TREE (t1);
++ip;
--sp;
- t1 = ctree_new (MB_TERM_STLOC, LOCAL_TYPE (*ip)->type, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_STLOC, LOCAL_TYPE (*ip)->type, *sp, NULL);
t1->data.i = LOCAL_POS (*ip);
t1->cli_addr = sp [0]->cli_addr;
++ip;
ADD_TREE (t1);
break;
}
- case CEE_ADD:
- ++ip;
- sp -= 2;
- t1 = ctree_new (MB_TERM_ADD, 0, sp [0], sp [1]);
- t1->cli_addr = sp [0]->cli_addr;
- PUSH_TREE (t1);
- break;
-
- case CEE_SUB:
- ++ip;
- sp -= 2;
- t1 = ctree_new (MB_TERM_SUB, 0, sp [0], sp [1]);
- t1->cli_addr = sp [0]->cli_addr;
- PUSH_TREE (t1);
- break;
- case CEE_MUL:
+ MAKE_BI_ALU (ADD)
+ MAKE_BI_ALU (SUB)
+ MAKE_BI_ALU (AND)
+ MAKE_BI_ALU (OR)
+ MAKE_BI_ALU (XOR)
+ //MAKE_BI_ALU (SHL)
+ //MAKE_BI_ALU (SHR)
+ //MAKE_BI_ALU (SHR_UN)
+ MAKE_BI_ALU (MUL)
+ MAKE_BI_ALU (DIV)
+ //MAKE_BI_ALU (DIV_UN)
+ //MAKE_BI_ALU (REM)
+ //MAKE_BI_ALU (REM_UN)
+
+ case CEE_BR_S: {
++ip;
- sp -= 2;
- t1 = ctree_new (MB_TERM_MUL, 0, sp [0], sp [1]);
- t1->cli_addr = sp [0]->cli_addr;
- PUSH_TREE (t1);
- break;
-
- case CEE_DIV:
- ++ip;
- sp -= 2;
- t1 = ctree_new (MB_TERM_DIV, 0, sp [0], sp [1]);
- t1->cli_addr = sp [0]->cli_addr;
- PUSH_TREE (t1);
- break;
-
- case CEE_BR_S:
- ++ip;
- t1 = ctree_new_leaf (MB_TERM_BR, 0);
+ t1 = ctree_new_leaf (mp, MB_TERM_BR, 0);
t1->data.i = cli_addr + 2 + (signed char) *ip;
t1->cli_addr = cli_addr;
ADD_TREE (t1);
++ip;
break;
-
- case CEE_BR:
+ }
+ case CEE_BR: {
++ip;
- t1 = ctree_new_leaf (MB_TERM_BR, 0);
+ t1 = ctree_new_leaf (mp, MB_TERM_BR, 0);
t1->data.i = cli_addr + 5 + (gint32) read32(ip);
t1->cli_addr = cli_addr;
ADD_TREE (t1);
ip += 4;
break;
+ }
MAKE_CJUMP(BGT)
MAKE_CJUMP(BGT_UN)
++ip;
--sp;
- t1 = ctree_new (MB_TERM_BRTRUE, 0, sp [0], NULL);
+ t1 = ctree_new (mp, MB_TERM_BRTRUE, 0, sp [0], NULL);
if (near_jump)
t1->data.i = cli_addr + 2 + (signed char) *ip;
ADD_TREE (t1);
break;
}
-
case CEE_BRFALSE:
case CEE_BRFALSE_S: {
int near_jump = *ip == CEE_BRFALSE_S;
++ip;
--sp;
- t1 = ctree_new (MB_TERM_BRFALSE, 0, sp [0], NULL);
+ t1 = ctree_new (mp, MB_TERM_BRFALSE, 0, sp [0], NULL);
if (near_jump)
t1->data.i = cli_addr + 2 + (signed char) *ip;
ADD_TREE (t1);
break;
}
- case CEE_RET:
+ case CEE_RET: {
ip++;
if (signature->ret->type != MONO_TYPE_VOID) {
--sp;
- t1 = ctree_new (MB_TERM_RETV, 0, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_RETV, 0, *sp, NULL);
t1->cli_addr = sp [0]->cli_addr;
} else {
- t1 = ctree_new (MB_TERM_RET, 0, NULL, NULL);
+ t1 = ctree_new (mp, MB_TERM_RET, 0, NULL, NULL);
t1->cli_addr = cli_addr;
}
g_warning ("more values on stack: %d", sp - stack);
break;
-
+ }
case CEE_LDARG_0:
case CEE_LDARG_1:
case CEE_LDARG_2:
case CEE_LDARG_3: {
int n = (*ip) - CEE_LDARG_0;
++ip;
- t1 = ctree_new_leaf (MB_TERM_LDARG, ARG_TYPE (n)->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_LDARG, ARG_TYPE (n)->type);
t1->data.i = ARG_POS (n);
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
break;
}
-
- case CEE_LDARG_S:
+ case CEE_LDARG_S: {
++ip;
- t1 = ctree_new_leaf (MB_TERM_LDARG, ARG_TYPE (*ip)->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_LDARG, ARG_TYPE (*ip)->type);
t1->data.i = ARG_POS (*ip);
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
++ip;
break;
-
- case CEE_DUP:
+ }
+ case CEE_DUP: {
++ip;
if (sp [-1]->op == MB_TERM_LDLOC) {
- t1 = ctree_new (0, 0, NULL, NULL);
+ t1 = ctree_new (mp, 0, 0, NULL, NULL);
*t1 = *sp [-1];
PUSH_TREE (t1);
} else
g_assert_not_reached ();
break;
-
- case CEE_POP:
+ }
+ case CEE_POP: {
++ip;
--sp;
/*
* all side effects are already on the forest,
* so we can simply ignore this tree
*/
- g_free (*sp);
+ // we use the mompool g_free (*sp);
break;
-
+ }
case CEE_CONV_U1:
- case CEE_CONV_I1:
+ case CEE_CONV_I1: {
++ip;
sp--;
- t1 = ctree_new (MB_TERM_CONV_I1, MONO_TYPE_I4, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_CONV_I1, MONO_TYPE_I4, *sp, NULL);
t1->cli_addr = sp [0]->cli_addr;
PUSH_TREE (t1);
break;
-
+ }
case CEE_CONV_U2:
- case CEE_CONV_I2:
+ case CEE_CONV_I2: {
++ip;
sp--;
- t1 = ctree_new (MB_TERM_CONV_I2, MONO_TYPE_I4, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_CONV_I2, MONO_TYPE_I4, *sp, NULL);
t1->cli_addr = sp [0]->cli_addr;
PUSH_TREE (t1);
break;
-
+ }
case CEE_CONV_I:
- case CEE_CONV_I4:
+ case CEE_CONV_I4: {
++ip;
sp--;
- t1 = ctree_new (MB_TERM_CONV_I4, MONO_TYPE_I4, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_CONV_I4, MONO_TYPE_I4, *sp, NULL);
t1->cli_addr = sp [0]->cli_addr;
PUSH_TREE (t1);
break;
-
- case CEE_CONV_I8:
+ }
+ case CEE_CONV_I8: {
++ip;
sp--;
- t1 = ctree_new (MB_TERM_CONV_I8, MONO_TYPE_I8, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_CONV_I8, MONO_TYPE_I8, *sp, NULL);
t1->cli_addr = sp [0]->cli_addr;
PUSH_TREE (t1);
break;
-
+ }
case 0xFE:
++ip;
switch (*ip) {
++ip;
n = read32 (ip);
ip += 4;
- t1 = ctree_new_leaf (MB_TERM_LDARG, ARG_TYPE (n)->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_LDARG, ARG_TYPE (n)->type);
t1->data.i = ARG_POS (n);
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
emit_method (method, &cgstat);
mono_regset_free (cgstat.rs);
+ g_ptr_array_free (forest, TRUE);
+ mono_mempool_destroy (cgstat.mp);
return method->addr;
}
#ifndef _MONO_JIT_JIT_H_
#define _MONO_JIT_JIT_H_
-#include "codegen.h"
+#include "regset.h"
-void arch_emit_prologue (MBCodeGenStatus *s);
-void arch_emit_epilogue (MBCodeGenStatus *s);
+typedef struct _MonoMemPool MonoMemPool;
+
+typedef struct {
+ MonoMemPool *mp;
+ guint8 *start;
+ guint8 *code;
+ gint32 locals_size;
+ GPtrArray *forest;
+ MonoRegSet *rs;
+ guint32 epilog;
+} MBCodeGenStatus;
+
+MonoMemPool *
+mono_mempool_new (void);
+
+void
+mono_mempool_destroy (MonoMemPool *pool);
+
+gpointer
+mono_mempool_alloc (MonoMemPool *pool, guint size);
+
+gpointer
+mono_mempool_alloc0 (MonoMemPool *pool, guint size);
+
+void
+arch_emit_prologue (MBCodeGenStatus *s);
+
+void
+arch_emit_epilogue (MBCodeGenStatus *s);
#endif
--- /dev/null
+#include <config.h>
+#include <glib.h>
+
+#include "jit.h"
+
+/*
+ * MonoMemPool is for fast allocation of memory. We free
+ * all memory when the pool is destroyed.
+ */
+
+#if SIZEOF_VOID_P > SIZEOF_LONG
+#define MEM_ALIGN SIZEOF_VOID_P
+#else
+#define MEM_ALIGN SIZEOF_LONG
+#endif
+
+#define MONO_MEMPOOL_PAGESIZE 8192
+
+struct _MonoMemPool {
+ MonoMemPool *next;
+ gint rest;
+ gpointer pos;
+};
+
+/**
+ * mono_mempool_new:
+ *
+ * Returns: a new memory pool.
+ */
+MonoMemPool *
+mono_mempool_new ()
+{
+
+ MonoMemPool *pool = g_malloc (MONO_MEMPOOL_PAGESIZE);
+ pool->next = NULL;
+ pool->pos = (gpointer)pool + sizeof (MonoMemPool);
+ pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool);
+ return pool;
+}
+
+/**
+ * mono_mempool_destroy:
+ * @pool: the momory pool to destroy
+ *
+ * Free all memory associated with this pool.
+ */
+void
+mono_mempool_destroy (MonoMemPool *pool)
+{
+ MonoMemPool *p, *n;
+
+ p = pool;
+ while (p) {
+ n = p->next;
+ g_free (p);
+ p = n;
+ }
+}
+
+/**
+ * mono_mempool_alloc:
+ * @pool: the momory pool to destroy
+ * @size: size of the momory block
+ *
+ * Allocates a new block of memory in @pool. @size must
+ * be smaller than 256.
+ *
+ * Returns: the address of a newly allocated memory block.
+ */
+gpointer
+mono_mempool_alloc (MonoMemPool *pool, guint size)
+{
+ gpointer rval;
+
+ g_assert (pool != NULL);
+ g_assert (size < 256);
+
+ size = (size + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1);
+
+ if (pool->rest < size) {
+ MonoMemPool *np = g_malloc (MONO_MEMPOOL_PAGESIZE);
+ np->next = pool->next;
+ pool->next = np;
+ pool->pos = (gpointer)np + sizeof (MonoMemPool);
+ pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool);
+ }
+
+ rval = pool->pos;
+ pool->rest -= size;
+ pool->pos += size;
+
+ return rval;
+}
+
+/**
+ * mono_mempool_alloc0:
+ *
+ * same as mono_mempool_alloc, but fills memory with zero.
+ */
+gpointer
+mono_mempool_alloc0 (MonoMemPool *pool, guint size)
+{
+ gpointer rval = mono_mempool_alloc (pool, size);
+ memset (rval, 0, size);
+ return rval;
+}
+
#include "jit.h"
#include "testjit.h"
#include "regset.h"
+
/*
* Pull the list of opcodes
*/
#define MAKE_CJUMP(name) \
case CEE_##name: \
-case CEE_##name##_S: \
-{ \
+case CEE_##name##_S: { \
int near_jump = *ip == CEE_##name##_S; \
++ip; \
sp -= 2; \
- t1 = ctree_new (MB_TERM_##name, 0, sp [0], sp [1]); \
+ t1 = ctree_new (mp, MB_TERM_##name, 0, sp [0], sp [1]); \
if (near_jump) \
t1->data.i = cli_addr + 2 + (signed char) *ip; \
else \
break; \
}
-
+#define MAKE_BI_ALU(name) \
+case CEE_##name: { \
+ ++ip; \
+ sp -= 2; \
+ t1 = ctree_new (mp, MB_TERM_##name, 0, sp [0], sp [1]); \
+ t1->cli_addr = sp [0]->cli_addr; \
+ PUSH_TREE (t1); \
+ break; \
+}
+
/* Whether to dump the assembly code after genreating it */
gboolean dump_asm = FALSE;
static gpointer mono_compile_method (MonoMethod *method);
+/*
+ * allocates static data (we never free it). Such data is
+ * needed by the code generation to store constants. We should
+ * use something faster than g_malloc()
+ */
+inline static gpointer
+alloc_static (int size)
+{
+ return g_malloc (size);
+}
+
static MonoRegSet *
get_x86_regset ()
{
}
static MBTree *
-ctree_new (int op, MonoTypeEnum type, MBTree *left, MBTree *right)
+ctree_new (MonoMemPool *mp, int op, MonoTypeEnum type,
+ MBTree *left, MBTree *right)
{
- MBTree *t = g_malloc (sizeof (MBTree));
+ MBTree *t = mono_mempool_alloc0 (mp, sizeof (MBTree));
t->op = op;
t->left = left;
t->type = type;
t->reg1 = -1;
t->reg2 = -1;
- t->is_jump = 0;
- t->jump_target = 0;
- t->last_instr = 0;
- t->exclude_edx = 0;
t->cli_addr = -1;
- t->addr = 0;
- t->first_addr = 0;
- t->emit = NULL;
return t;
}
static MBTree *
-ctree_new_leaf (int op, MonoTypeEnum type)
+ctree_new_leaf (MonoMemPool *mp, int op, MonoTypeEnum type)
{
- return ctree_new (op, type, NULL, NULL);
+ return ctree_new (mp, op, type, NULL, NULL);
}
static void
}
static void
-forest_label (GPtrArray *forest)
+forest_label (MBCodeGenStatus *s)
{
+ GPtrArray *forest = s->forest;
const int top = forest->len;
int i;
for (i = 0; i < top; i++) {
MBTree *t1 = (MBTree *) g_ptr_array_index (forest, i);
- MBState *s;
+ MBState *mbstate;
- s = mono_burg_label (t1);
- if (!s) {
+ mbstate = mono_burg_label (t1, s);
+ if (!mbstate) {
g_warning ("tree does not match");
print_tree (t1); printf ("\n");
g_assert_not_reached ();
{
method->addr = s->start = s->code = g_malloc (1024);
- forest_label (s->forest);
+ forest_label (s);
forest_allocate_regs (s);
arch_emit_prologue (s);
MonoMethodHeader *header;
MonoMethodSignature *signature;
MonoImage *image;
+ MonoMemPool *mp;
MBTree **sp, **stack, *t1, *t2;
register const unsigned char *ip, *end;
guint *locals_offsets;
ip = header->code;
end = ip + header->code_size;
+ cgstat.mp = mp = mono_mempool_new ();
+
sp = stack = alloca (sizeof (MBTree *) * header->max_stack);
if (header->num_locals) {
guint32 cli_addr = ip - header->code;
switch (*ip) {
- case CEE_NOP:
+ case CEE_NOP: {
++ip;
break;
-
- case CEE_BREAK:
+ }
+ case CEE_BREAK: {
++ip;
- t1 = ctree_new_leaf (MB_TERM_BREAK, 0);
+ t1 = ctree_new_leaf (mp, MB_TERM_BREAK, 0);
t1->cli_addr = cli_addr;
ADD_TREE (t1);
break;
-
+ }
+/*
+ case CEE_SWITCH:
+ guint32 n;
+ const unsigned char *st;
+ ++ip;
+ n = read32 (ip);
+ ip += 4;
+ st = ip + 4 * n;
+ --sp;
+ if ((guint32)sp->data.i < n) {
+ gint offset;
+ ip += 4 * (guint32)sp->data.i;
+ offset = read32 (ip);
+ ip = st + offset;
+ } else {
+ ip = st;
+ }
+ break;
+ }
+*/
case CEE_CALL: {
MonoMethodSignature *csig;
MonoMethod *cm;
guint32 token, nargs;
- int i;
+ int i, align, size, offset = 0;
gint32 fa;
++ip;
fa = sp [-nargs]->cli_addr;
- for (i = 0; i < nargs; i++) {
+ for (i = nargs - 1; i >= 0; i--) {
sp--;
- t1 = ctree_new (MB_TERM_ARG, 0, *sp, NULL);
-
- if (i)
- t1->cli_addr = -1;
- else
- t1->cli_addr = fa;
-
+ t1 = ctree_new (mp, MB_TERM_ARG, 0, *sp, NULL);
ADD_TREE (t1);
+ if (!i && csig->hasthis)
+ size = mono_type_size (&cm->klass->this_arg, &align);
+ else
+ size = mono_type_size (cm->signature->params [i], &align);
+
+ // fixme: does this really work ?
+ offset += (size + 3) & ~3;
}
+ t1->cli_addr = fa;
fa = -1;
} else
fa = cli_addr;
-
+
cm->addr = create_jit_trampoline (cm);
if (csig->ret->type != MONO_TYPE_VOID) {
- int size, align;
- t1 = ctree_new_leaf (MB_TERM_CALL, csig->ret->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_CALL, csig->ret->type);
t1->data.p = cm;
- t2 = ctree_new (MB_TERM_STLOC, csig->ret->type, t1, NULL);
+ t1->size = offset;
+ t2 = ctree_new (mp, MB_TERM_STLOC, csig->ret->type, t1, NULL);
size = mono_type_size (csig->ret, &align);
local_offset += align - 1;
local_offset &= ~(align - 1);
t2->data.i = - local_offset;
t2->cli_addr = fa;
ADD_TREE (t2);
- t1 = ctree_new_leaf (MB_TERM_LDLOC, t2->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_LDLOC, t2->type);
t1->data.i = t2->data.i;
PUSH_TREE (t1);
} else {
- t1 = ctree_new_leaf (MB_TERM_CALL, MONO_TYPE_VOID);
+ t1 = ctree_new_leaf (mp, MB_TERM_CALL, MONO_TYPE_VOID);
t1->data.p = cm;
+ t1->size = offset;
t1->cli_addr = fa;
ADD_TREE (t1);
}
break;
}
- case CEE_LDC_I4_S:
+ case CEE_LDC_I4_S: {
++ip;
- t1 = ctree_new_leaf (MB_TERM_CONST_I4, MONO_TYPE_I4);
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_I4, MONO_TYPE_I4);
t1->data.i = *ip;
++ip;
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
break;
-
- case CEE_LDC_I4:
+ }
+ case CEE_LDC_I4: {
++ip;
- t1 = ctree_new_leaf (MB_TERM_CONST_I4, MONO_TYPE_I4);
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_I4, MONO_TYPE_I4);
t1->data.i = read32 (ip);
ip += 4;
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
break;
-
+ }
case CEE_LDC_I4_M1:
case CEE_LDC_I4_0:
case CEE_LDC_I4_1:
case CEE_LDC_I4_5:
case CEE_LDC_I4_6:
case CEE_LDC_I4_7:
- case CEE_LDC_I4_8:
- t1 = ctree_new_leaf (MB_TERM_CONST_I4, MONO_TYPE_I4);
+ case CEE_LDC_I4_8: {
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_I4, MONO_TYPE_I4);
t1->data.i = (*ip) - CEE_LDC_I4_0;
++ip;
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
break;
-
- case CEE_LDC_R8:
+ }
+ case CEE_LDNULL: {
+ //fixme: don't know if this is portable ?
++ip;
- t1 = ctree_new_leaf (MB_TERM_CONST_R8, MONO_TYPE_R8);
- (const void *) t1->data.p = ip;
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_I4, MONO_TYPE_I4);
+ t1->data.i = 0;
t1->cli_addr = cli_addr;
+ PUSH_TREE (t1);
+ break;
+ }
+ case CEE_LDC_I8: {
+ ++ip;
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_I8, MONO_TYPE_I8);
+ t1->data.l = read64 (ip);
ip += 8;
+ t1->cli_addr = cli_addr;
PUSH_TREE (t1);
break;
-
+ }
+ case CEE_LDC_R4: {
+ float *f = alloc_static (sizeof (float));
+ ++ip;
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_R4, MONO_TYPE_R4);
+ readr4 (ip, f);
+ t1->data.p = f;
+ t1->cli_addr = cli_addr;
+ ip += 4;
+ PUSH_TREE (t1);
+ break;
+ }
+ case CEE_LDC_R8: {
+ double *d = alloc_static (sizeof (double));
+ ++ip;
+ t1 = ctree_new_leaf (mp, MB_TERM_CONST_R8, MONO_TYPE_R8);
+ readr8 (ip, d);
+ t1->data.p = d;
+ t1->cli_addr = cli_addr;
+ ip += 8;
+ PUSH_TREE (t1);
+ break;
+ }
case CEE_LDLOC_0:
case CEE_LDLOC_1:
case CEE_LDLOC_2:
int n = (*ip) - CEE_LDLOC_0;
++ip;
- t1 = ctree_new_leaf (MB_TERM_LDLOC, LOCAL_TYPE (n)->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_LDLOC, LOCAL_TYPE (n)->type);
t1->data.i = LOCAL_POS (n);
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
case CEE_LDLOC_S: {
++ip;
- t1 = ctree_new_leaf (MB_TERM_LDLOC, LOCAL_TYPE (*ip)->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_LDLOC, LOCAL_TYPE (*ip)->type);
t1->data.i = LOCAL_POS (*ip);
t1->cli_addr = cli_addr;
++ip;
PUSH_TREE (t1);
break;
}
-
case CEE_STLOC_0:
case CEE_STLOC_1:
case CEE_STLOC_2:
++ip;
--sp;
- t1 = ctree_new (MB_TERM_STLOC, LOCAL_TYPE (n)->type, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_STLOC, LOCAL_TYPE (n)->type, *sp, NULL);
t1->data.i = LOCAL_POS (n);
t1->cli_addr = sp [0]->cli_addr;
ADD_TREE (t1);
++ip;
--sp;
- t1 = ctree_new (MB_TERM_STLOC, LOCAL_TYPE (*ip)->type, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_STLOC, LOCAL_TYPE (*ip)->type, *sp, NULL);
t1->data.i = LOCAL_POS (*ip);
t1->cli_addr = sp [0]->cli_addr;
++ip;
ADD_TREE (t1);
break;
}
- case CEE_ADD:
- ++ip;
- sp -= 2;
- t1 = ctree_new (MB_TERM_ADD, 0, sp [0], sp [1]);
- t1->cli_addr = sp [0]->cli_addr;
- PUSH_TREE (t1);
- break;
-
- case CEE_SUB:
- ++ip;
- sp -= 2;
- t1 = ctree_new (MB_TERM_SUB, 0, sp [0], sp [1]);
- t1->cli_addr = sp [0]->cli_addr;
- PUSH_TREE (t1);
- break;
- case CEE_MUL:
+ MAKE_BI_ALU (ADD)
+ MAKE_BI_ALU (SUB)
+ MAKE_BI_ALU (AND)
+ MAKE_BI_ALU (OR)
+ MAKE_BI_ALU (XOR)
+ //MAKE_BI_ALU (SHL)
+ //MAKE_BI_ALU (SHR)
+ //MAKE_BI_ALU (SHR_UN)
+ MAKE_BI_ALU (MUL)
+ MAKE_BI_ALU (DIV)
+ //MAKE_BI_ALU (DIV_UN)
+ //MAKE_BI_ALU (REM)
+ //MAKE_BI_ALU (REM_UN)
+
+ case CEE_BR_S: {
++ip;
- sp -= 2;
- t1 = ctree_new (MB_TERM_MUL, 0, sp [0], sp [1]);
- t1->cli_addr = sp [0]->cli_addr;
- PUSH_TREE (t1);
- break;
-
- case CEE_DIV:
- ++ip;
- sp -= 2;
- t1 = ctree_new (MB_TERM_DIV, 0, sp [0], sp [1]);
- t1->cli_addr = sp [0]->cli_addr;
- PUSH_TREE (t1);
- break;
-
- case CEE_BR_S:
- ++ip;
- t1 = ctree_new_leaf (MB_TERM_BR, 0);
+ t1 = ctree_new_leaf (mp, MB_TERM_BR, 0);
t1->data.i = cli_addr + 2 + (signed char) *ip;
t1->cli_addr = cli_addr;
ADD_TREE (t1);
++ip;
break;
-
- case CEE_BR:
+ }
+ case CEE_BR: {
++ip;
- t1 = ctree_new_leaf (MB_TERM_BR, 0);
+ t1 = ctree_new_leaf (mp, MB_TERM_BR, 0);
t1->data.i = cli_addr + 5 + (gint32) read32(ip);
t1->cli_addr = cli_addr;
ADD_TREE (t1);
ip += 4;
break;
+ }
MAKE_CJUMP(BGT)
MAKE_CJUMP(BGT_UN)
++ip;
--sp;
- t1 = ctree_new (MB_TERM_BRTRUE, 0, sp [0], NULL);
+ t1 = ctree_new (mp, MB_TERM_BRTRUE, 0, sp [0], NULL);
if (near_jump)
t1->data.i = cli_addr + 2 + (signed char) *ip;
ADD_TREE (t1);
break;
}
-
case CEE_BRFALSE:
case CEE_BRFALSE_S: {
int near_jump = *ip == CEE_BRFALSE_S;
++ip;
--sp;
- t1 = ctree_new (MB_TERM_BRFALSE, 0, sp [0], NULL);
+ t1 = ctree_new (mp, MB_TERM_BRFALSE, 0, sp [0], NULL);
if (near_jump)
t1->data.i = cli_addr + 2 + (signed char) *ip;
ADD_TREE (t1);
break;
}
- case CEE_RET:
+ case CEE_RET: {
ip++;
if (signature->ret->type != MONO_TYPE_VOID) {
--sp;
- t1 = ctree_new (MB_TERM_RETV, 0, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_RETV, 0, *sp, NULL);
t1->cli_addr = sp [0]->cli_addr;
} else {
- t1 = ctree_new (MB_TERM_RET, 0, NULL, NULL);
+ t1 = ctree_new (mp, MB_TERM_RET, 0, NULL, NULL);
t1->cli_addr = cli_addr;
}
g_warning ("more values on stack: %d", sp - stack);
break;
-
+ }
case CEE_LDARG_0:
case CEE_LDARG_1:
case CEE_LDARG_2:
case CEE_LDARG_3: {
int n = (*ip) - CEE_LDARG_0;
++ip;
- t1 = ctree_new_leaf (MB_TERM_LDARG, ARG_TYPE (n)->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_LDARG, ARG_TYPE (n)->type);
t1->data.i = ARG_POS (n);
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
break;
}
-
- case CEE_LDARG_S:
+ case CEE_LDARG_S: {
++ip;
- t1 = ctree_new_leaf (MB_TERM_LDARG, ARG_TYPE (*ip)->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_LDARG, ARG_TYPE (*ip)->type);
t1->data.i = ARG_POS (*ip);
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
++ip;
break;
-
- case CEE_DUP:
+ }
+ case CEE_DUP: {
++ip;
if (sp [-1]->op == MB_TERM_LDLOC) {
- t1 = ctree_new (0, 0, NULL, NULL);
+ t1 = ctree_new (mp, 0, 0, NULL, NULL);
*t1 = *sp [-1];
PUSH_TREE (t1);
} else
g_assert_not_reached ();
break;
-
- case CEE_POP:
+ }
+ case CEE_POP: {
++ip;
--sp;
/*
* all side effects are already on the forest,
* so we can simply ignore this tree
*/
- g_free (*sp);
+ // we use the mompool g_free (*sp);
break;
-
+ }
case CEE_CONV_U1:
- case CEE_CONV_I1:
+ case CEE_CONV_I1: {
++ip;
sp--;
- t1 = ctree_new (MB_TERM_CONV_I1, MONO_TYPE_I4, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_CONV_I1, MONO_TYPE_I4, *sp, NULL);
t1->cli_addr = sp [0]->cli_addr;
PUSH_TREE (t1);
break;
-
+ }
case CEE_CONV_U2:
- case CEE_CONV_I2:
+ case CEE_CONV_I2: {
++ip;
sp--;
- t1 = ctree_new (MB_TERM_CONV_I2, MONO_TYPE_I4, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_CONV_I2, MONO_TYPE_I4, *sp, NULL);
t1->cli_addr = sp [0]->cli_addr;
PUSH_TREE (t1);
break;
-
+ }
case CEE_CONV_I:
- case CEE_CONV_I4:
+ case CEE_CONV_I4: {
++ip;
sp--;
- t1 = ctree_new (MB_TERM_CONV_I4, MONO_TYPE_I4, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_CONV_I4, MONO_TYPE_I4, *sp, NULL);
t1->cli_addr = sp [0]->cli_addr;
PUSH_TREE (t1);
break;
-
- case CEE_CONV_I8:
+ }
+ case CEE_CONV_I8: {
++ip;
sp--;
- t1 = ctree_new (MB_TERM_CONV_I8, MONO_TYPE_I8, *sp, NULL);
+ t1 = ctree_new (mp, MB_TERM_CONV_I8, MONO_TYPE_I8, *sp, NULL);
t1->cli_addr = sp [0]->cli_addr;
PUSH_TREE (t1);
break;
-
+ }
case 0xFE:
++ip;
switch (*ip) {
++ip;
n = read32 (ip);
ip += 4;
- t1 = ctree_new_leaf (MB_TERM_LDARG, ARG_TYPE (n)->type);
+ t1 = ctree_new_leaf (mp, MB_TERM_LDARG, ARG_TYPE (n)->type);
t1->data.i = ARG_POS (n);
t1->cli_addr = cli_addr;
PUSH_TREE (t1);
emit_method (method, &cgstat);
mono_regset_free (cgstat.rs);
+ g_ptr_array_free (forest, TRUE);
+ mono_mempool_destroy (cgstat.mp);
return method->addr;
}
#include <mono/arch/x86/x86-codegen.h>
#include "regset.h"
+#include "jit.h"
#define MBTREE_TYPE MBTree
#define MBCGEN_TYPE MBCodeGenStatus
-
-typedef struct {
- guint8 *start;
- guint8 *code;
- gint32 locals_size;
- GPtrArray *forest;
- MonoRegSet *rs;
- guint32 epilog;
-} MBCodeGenStatus;
+#define MBCOST_DATA MBCodeGenStatus
+#define MBALLOC_STATE mono_mempool_alloc (data->mp, sizeof (MBState))
typedef struct _MBTree MBTree;
struct _MBTree {
gint8 reg1;
gint8 reg2;
MonoTypeEnum type;
+ gint32 size;
union {
- int i;
+ gint32 i;
+ gint64 l;
gpointer p;
} data;
};
#
# constatnts
-%term CONST_I4 CONST_R8
+%term CONST_I4 CONST_I8 CONST_R4 CONST_R8
%term LDLOC LDARG STLOC BR RET RETV ARG CALL BREAK
-%term ADD SUB MUL DIV
-%term BLT BLT_UN BEQ BNE_UN BRTRUE BRFALSE BGE BGE_UN BLE BLE_UN BGT BGT_UN
+%term ADD SUB MUL DIV AND OR XOR
+%term BLT BLT_UN BEQ BNE_UN BRTRUE BRFALSE BGE BGE_UN BLE BLE_UN BGT BGT_UN
%term CONV_I4 CONV_I1 CONV_I2 CONV_I8
+
#
# we start at stmt
#
x86_alu_reg_reg (s->code, X86_SUB, tree->reg1, tree->right->reg1);
}
+reg: AND (reg, reg) {
+ if (tree->reg1 != tree->left->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+ x86_alu_reg_reg (s->code, X86_AND, tree->reg1, tree->right->reg1);
+}
+
+reg: OR (reg, reg) {
+ if (tree->reg1 != tree->left->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+ x86_alu_reg_reg (s->code, X86_OR, tree->reg1, tree->right->reg1);
+}
+
+reg: XOR (reg, reg) {
+ if (tree->reg1 != tree->left->reg1)
+ x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+ x86_alu_reg_reg (s->code, X86_XOR, tree->reg1, tree->right->reg1);
+}
+
stmt: STLOC (CONST_I4) "MB_USE_OPT1(0)" {
x86_mov_membase_imm (s->code, X86_EBP, tree->data.i,
tree->left->data.i, 4);
x86_branch32 (s->code, X86_CC_GT, tree->data.i - offset, TRUE);
}
+stmt: BGT_UN (reg, reg) 1 {
+ guint8 *start = s->code;
+ gint32 offset;
+
+ tree->is_jump = 1;
+ x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
+ offset = 6 + s->code - start;
+ x86_branch32 (s->code, X86_CC_GT, tree->data.i - offset, FALSE);
+}
+
+stmt: BGT_UN (reg, CONST_I4) "MB_USE_OPT1(0)" {
+ guint8 *start = s->code;
+ gint32 offset;
+
+ tree->is_jump = 1;
+ x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, tree->right->data.i);
+ offset = 6 + s->code - start;
+ x86_branch32 (s->code, X86_CC_GT, tree->data.i - offset, FALSE);
+}
+
stmt: BEQ (reg, CONST_I4) "MB_USE_OPT1(0)" {
guint8 *start = s->code;
gint32 offset;
x86_mov_reg_imm (s->code, X86_EAX, tree->data.p);
x86_call_membase (s->code, X86_EAX,
G_STRUCT_OFFSET (MonoMethod, addr));
+ if (tree->size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->size);
+
g_assert (tree->reg1 == X86_EAX);
break;
default:
stmt: CALL {
x86_mov_reg_imm (s->code, X86_EAX, tree->data.p);
x86_call_membase (s->code, X86_EAX, G_STRUCT_OFFSET (MonoMethod, addr));
+ if (tree->size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->size);
}
#
# 64 bit integers
#
+lreg: CONST_I8 1 {
+ x86_mov_reg_imm (s->code, tree->reg1, tree->data.i);
+ x86_mov_reg_imm (s->code, tree->reg2, *(gint32 *)(&tree->data.p + 4));
+}
+
lreg: CONV_I8 (CONST_I4) 1 {
x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
x86_mov_reg_imm (s->code, X86_EAX, tree->data.p);
x86_call_membase (s->code, X86_EAX,
G_STRUCT_OFFSET (MonoMethod, addr));
+ if (tree->size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->size);
} cost {
MBCOND (tree->type == MONO_TYPE_I8 ||
tree->type == MONO_TYPE_U8);
#
# floating point
-# fixme: dont know how to assign registers?
+
+freg: CONST_R4 {
+ x86_fld (s->code, tree->data.p, FALSE);
+}
freg: CONST_R8 {
x86_fld (s->code, tree->data.p, TRUE);
x86_mov_reg_imm (s->code, X86_EAX, tree->data.p);
x86_call_membase (s->code, X86_EAX,
G_STRUCT_OFFSET (MonoMethod, addr));
+ if (tree->size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->size);
} cost {
MBCOND (tree->type == MONO_TYPE_R4 ||
tree->type == MONO_TYPE_R8);
--- /dev/null
+#include <config.h>
+#include <glib.h>
+
+#include "jit.h"
+
+/*
+ * MonoMemPool is for fast allocation of memory. We free
+ * all memory when the pool is destroyed.
+ */
+
+#if SIZEOF_VOID_P > SIZEOF_LONG
+#define MEM_ALIGN SIZEOF_VOID_P
+#else
+#define MEM_ALIGN SIZEOF_LONG
+#endif
+
+#define MONO_MEMPOOL_PAGESIZE 8192
+
+struct _MonoMemPool {
+ MonoMemPool *next;
+ gint rest;
+ gpointer pos;
+};
+
+/**
+ * mono_mempool_new:
+ *
+ * Returns: a new memory pool.
+ */
+MonoMemPool *
+mono_mempool_new ()
+{
+
+ MonoMemPool *pool = g_malloc (MONO_MEMPOOL_PAGESIZE);
+ pool->next = NULL;
+ pool->pos = (gpointer)pool + sizeof (MonoMemPool);
+ pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool);
+ return pool;
+}
+
+/**
+ * mono_mempool_destroy:
+ * @pool: the momory pool to destroy
+ *
+ * Free all memory associated with this pool.
+ */
+void
+mono_mempool_destroy (MonoMemPool *pool)
+{
+ MonoMemPool *p, *n;
+
+ p = pool;
+ while (p) {
+ n = p->next;
+ g_free (p);
+ p = n;
+ }
+}
+
+/**
+ * mono_mempool_alloc:
+ * @pool: the momory pool to destroy
+ * @size: size of the momory block
+ *
+ * Allocates a new block of memory in @pool. @size must
+ * be smaller than 256.
+ *
+ * Returns: the address of a newly allocated memory block.
+ */
+gpointer
+mono_mempool_alloc (MonoMemPool *pool, guint size)
+{
+ gpointer rval;
+
+ g_assert (pool != NULL);
+ g_assert (size < 256);
+
+ size = (size + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1);
+
+ if (pool->rest < size) {
+ MonoMemPool *np = g_malloc (MONO_MEMPOOL_PAGESIZE);
+ np->next = pool->next;
+ pool->next = np;
+ pool->pos = (gpointer)np + sizeof (MonoMemPool);
+ pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool);
+ }
+
+ rval = pool->pos;
+ pool->rest -= size;
+ pool->pos += size;
+
+ return rval;
+}
+
+/**
+ * mono_mempool_alloc0:
+ *
+ * same as mono_mempool_alloc, but fills memory with zero.
+ */
+gpointer
+mono_mempool_alloc0 (MonoMemPool *pool, guint size)
+{
+ gpointer rval = mono_mempool_alloc (pool, size);
+ memset (rval, 0, size);
+ return rval;
+}
+
+2001-09-23 Dietmar Maurer <dietmar@ximian.com>
+
+ * monoburg.c: add a macro MBALLOC_STATE to define the allocation
+ function for MBState. Added an additional user data argument to
+ mono_burg_label - the data can be used in the cost functions. The
+ type can be defined with MBCOST_DATA macro.
+ (emit_cost_func): inline cost functions
+
2001-09-22 Dietmar Maurer <dietmar@ximian.com>
* monoburg.y (strndup): removed, use g_strndup instead
if (cost)
yyerror ("duplicated costs (constant costs and cost function)");
else
- rule->cost = g_strdup_printf ("mono_burg_cost_%d (tree)",
+ rule->cost = g_strdup_printf ("mono_burg_cost_%d (tree, data)",
g_list_length (rule_list));
}
output ("#ifndef MBTREE_RIGHT\n#define MBTREE_RIGHT(t) ((t)->right)\n#endif\n");
output ("#ifndef MBTREE_STATE\n#define MBTREE_STATE(t) ((t)->state)\n#endif\n");
output ("#ifndef MBCGEN_TYPE\n#define MBCGEN_TYPE int\n#endif\n");
-
+ output ("#ifndef MBALLOC_STATE\n#define MBALLOC_STATE g_new (MBState, 1)\n#endif\n");
+ output ("#ifndef MBCOST_DATA\n#define MBCOST_DATA gpointer\n#endif\n");
output ("\n");
output ("#define MBMAXCOST 32768\n");
int i;
output ("static MBState *\n");
- output ("mono_burg_label_priv (MBTREE_TYPE *tree) {\n");
+ output ("mono_burg_label_priv (MBTREE_TYPE *tree, MBCOST_DATA *data) {\n");
output ("\tint arity;\n");
output ("\tint c;\n");
output ("\t\tright = NULL;\n");
output ("\t\tbreak;\n");
output ("\tcase 1:\n");
- output ("\t\tleft = mono_burg_label_priv (MBTREE_LEFT(tree));\n");
+ output ("\t\tleft = mono_burg_label_priv (MBTREE_LEFT(tree), data);\n");
output ("\t\tright = NULL;\n");
output ("\t\tbreak;\n");
output ("\tcase 2:\n");
- output ("\t\tleft = mono_burg_label_priv (MBTREE_LEFT(tree));\n");
- output ("\t\tright = mono_burg_label_priv (MBTREE_RIGHT(tree));\n");
+ output ("\t\tleft = mono_burg_label_priv (MBTREE_LEFT(tree), data);\n");
+ output ("\t\tright = mono_burg_label_priv (MBTREE_RIGHT(tree), data);\n");
output ("\t}\n\n");
output ("\tarity = (left != NULL) + (right != NULL);\n");
output ("\tg_assert (arity == mono_burg_arity [MBTREE_OP(tree)]);\n\n");
- output ("\tp = g_new0 (MBState, 1);\n");
+ output ("\tp = MBALLOC_STATE;\n");
+ output ("\tmemset (p, 0, sizeof (MBState));\n");
output ("\tp->op = MBTREE_OP(tree);\n");
output ("\tp->left = left;\n");
output ("\tp->right = right;\n");
output ("}\n\n");
output ("MBState *\n");
- output ("mono_burg_label (MBTREE_TYPE *tree)\n{\n");
- output ("\tMBState *p = mono_burg_label_priv (tree);\n");
+ output ("mono_burg_label (MBTREE_TYPE *tree, MBCOST_DATA *data)\n{\n");
+ output ("\tMBState *p = mono_burg_label_priv (tree, data);\n");
output ("\treturn p->rule_%s ? p : NULL;\n", ((NonTerm *)nonterm_list->data)->name);
output ("}\n\n");
}
Rule *rule = (Rule *)l->data;
if (rule->cfunc) {
- output ("static guint16\n");
+ output ("inline static guint16\n");
emit_rule_string (rule, "");
- output ("mono_burg_cost_%d (MBTREE_TYPE *tree)\n", i + 1);
+ output ("mono_burg_cost_%d (MBTREE_TYPE *tree, MBCOST_DATA *data)\n", i + 1);
output ("{\n");
output ("%s\n", rule->cfunc);
output ("}\n\n");
output ("extern guint16 *mono_burg_nts [];\n");
output ("extern MBEmitFunc mono_burg_func [];\n");
- output ("MBState *mono_burg_label (MBTREE_TYPE *tree);\n");
+ output ("MBState *mono_burg_label (MBTREE_TYPE *tree, MBCOST_DATA *data);\n");
output ("int mono_burg_rule (MBState *state, int goal);\n");
output ("MBTREE_TYPE **mono_burg_kids (MBTREE_TYPE *tree, int rulenr, MBTREE_TYPE *kids []);\n");
t = create_tree (MB_TERM_Fetch, l, NULL);
- s = mono_burg_label (t);
+ s = mono_burg_label (t, NULL);
g_assert (s);