Author: mprobst
Date: 2007-12-07 09:00:30 -0500 (Fri, 07 Dec 2007)
New Revision: 90930
Modified:
trunk/mono/mono/mini/ChangeLog
trunk/mono/mono/mini/aliasing.c
trunk/mono/mono/mini/graph.c
trunk/mono/mono/mini/inssel.brg
trunk/mono/mono/mini/local-propagation.c
trunk/mono/mono/mini/mini-amd64.c
trunk/mono/mono/mini/mini-amd64.h
trunk/mono/mono/mini/mini-ops.h
trunk/mono/mono/mini/mini-trampolines.c
trunk/mono/mono/mini/mini-x86.c
trunk/mono/mono/mini/mini-x86.h
trunk/mono/mono/mini/mini.c
trunk/mono/mono/mini/mini.h
trunk/mono/mono/mini/tramp-amd64.c
trunk/mono/mono/mini/tramp-x86.c
Log:
2007-12-07 Mark Probst <[EMAIL PROTECTED]>
* inssel.brg: Added a pattern for the OP_TRAMPCALL_VTABLE
trampoline call, which takes a vtable argument.
* graph.c, mini-ops.h, local-propagation.c, aliasing.c: Treat
OP_TRAMPCALL_VTABLEs like other calls.
* mini-amd64.c, mini-amd64.h, mini-x86.c, mini-x86.h: Designated a
register to hold the vtable argument to the OP_TRAMPCALL_VTABLE
call. Implemented a support function which fetches the vtable
from a register set.
* mini.c, mini.h, tramp-amd64.c, tramp-x86.c, mini-trampolines.c:
Implemented a generic class init trampoline, using the
OP_TRAMPCALL_VTABLE opcode.
* mini.c: Implemented static field access when sharing generic
code. This implies initing the class using the new
OP_TRAMPCALL_VTABLE call.
Modified: trunk/mono/mono/mini/ChangeLog
===================================================================
--- trunk/mono/mono/mini/ChangeLog 2007-12-07 13:39:31 UTC (rev 90929)
+++ trunk/mono/mono/mini/ChangeLog 2007-12-07 14:00:30 UTC (rev 90930)
@@ -1,5 +1,26 @@
2007-12-07 Mark Probst <[EMAIL PROTECTED]>
+ * inssel.brg: Added a pattern for the OP_TRAMPCALL_VTABLE
+ trampoline call, which takes a vtable argument.
+
+ * graph.c, mini-ops.h, local-propagation.c, aliasing.c: Treat
+ OP_TRAMPCALL_VTABLEs like other calls.
+
+ * mini-amd64.c, mini-amd64.h, mini-x86.c, mini-x86.h: Designated a
+ register to hold the vtable argument to the OP_TRAMPCALL_VTABLE
+ call. Implemented a support function which fetches the vtable
+ from a register set.
+
+ * mini.c, mini.h, tramp-amd64.c, tramp-x86.c, mini-trampolines.c:
+ Implemented a generic class init trampoline, using the
+ OP_TRAMPCALL_VTABLE opcode.
+
+ * mini.c: Implemented static field access when sharing generic
+ code. This implies initing the class using the new
+ OP_TRAMPCALL_VTABLE call.
+
+2007-12-07 Mark Probst <[EMAIL PROTECTED]>
+
* mini.c: Don't compile methods with sharing enabled if their
classes are disabled for sharing.
Modified: trunk/mono/mono/mini/aliasing.c
===================================================================
--- trunk/mono/mono/mini/aliasing.c 2007-12-07 13:39:31 UTC (rev 90929)
+++ trunk/mono/mono/mini/aliasing.c 2007-12-07 14:00:30 UTC (rev 90930)
@@ -167,7 +167,8 @@
case OP_VCALL:
case OP_VCALLVIRT:
case OP_VOIDCALL:
- case OP_VOIDCALLVIRT: {
+ case OP_VOIDCALLVIRT:
+ case OP_TRAMPCALL_VTABLE: {
MonoCallInst *call = (MonoCallInst*)tree;
if (call->method)
printf ("[%s]", call->method->name);
Modified: trunk/mono/mono/mini/graph.c
===================================================================
--- trunk/mono/mono/mini/graph.c 2007-12-07 13:39:31 UTC (rev 90929)
+++ trunk/mono/mono/mini/graph.c 2007-12-07 14:00:30 UTC (rev 90930)
@@ -235,6 +235,7 @@
case OP_LCALL_REG:
case OP_VCALL_REG:
case OP_VOIDCALL_REG:
+ case OP_TRAMPCALL_VTABLE:
mono_print_label (fp, tree->inst_left);
break;
case CEE_BNE_UN:
Modified: trunk/mono/mono/mini/inssel.brg
===================================================================
--- trunk/mono/mono/mini/inssel.brg 2007-12-07 13:39:31 UTC (rev 90929)
+++ trunk/mono/mono/mini/inssel.brg 2007-12-07 14:00:30 UTC (rev 90930)
@@ -921,6 +921,23 @@
mono_bblock_add_inst (s->cbb, tree);
}
+stmt: OP_TRAMPCALL_VTABLE (reg) {
+ #ifdef MONO_ARCH_VTABLE_REG
+ MonoCallInst *call = (MonoCallInst*)tree;
+ int vtable_reg = mono_regstate_next_int (s->rs);
+
+ MONO_EMIT_NEW_UNALU (s, OP_MOVE, vtable_reg, state->left->reg1);
+
+ call->inst.opcode = OP_VOIDCALL;
+
+ mono_call_inst_add_outarg_reg (s, call, vtable_reg,
MONO_ARCH_VTABLE_REG, FALSE);
+
+ mono_bblock_add_inst (s->cbb, &call->inst);
+ #else
+ g_assert_not_reached ();
+ #endif
+}
+
stmt: OP_SAVE_LMF,
stmt: OP_RESTORE_LMF {
mono_bblock_add_inst (s->cbb, tree);
Modified: trunk/mono/mono/mini/local-propagation.c
===================================================================
--- trunk/mono/mono/mini/local-propagation.c 2007-12-07 13:39:31 UTC (rev
90929)
+++ trunk/mono/mono/mini/local-propagation.c 2007-12-07 14:00:30 UTC (rev
90930)
@@ -716,7 +716,8 @@
case OP_VCALL:
case OP_VOIDCALL_REG:
case OP_VOIDCALLVIRT:
- case OP_VOIDCALL: {
+ case OP_VOIDCALL:
+ case OP_TRAMPCALL_VTABLE: {
MonoCallInst *call = (MonoCallInst *)tree;
MonoMethodSignature *sig = call->signature;
int i, byref = FALSE;
Modified: trunk/mono/mono/mini/mini-amd64.c
===================================================================
--- trunk/mono/mono/mini/mini-amd64.c 2007-12-07 13:39:31 UTC (rev 90929)
+++ trunk/mono/mono/mini/mini-amd64.c 2007-12-07 14:00:30 UTC (rev 90930)
@@ -5772,6 +5772,12 @@
}
#endif
+MonoVTable*
+mono_arch_find_vtable (gpointer *regs, guint8 *code)
+{
+ return (MonoVTable*) regs [MONO_ARCH_VTABLE_REG];
+}
+
MonoInst*
mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod,
MonoMethodSignature *fsig, MonoInst **args)
{
Modified: trunk/mono/mono/mini/mini-amd64.h
===================================================================
--- trunk/mono/mono/mini/mini-amd64.h 2007-12-07 13:39:31 UTC (rev 90929)
+++ trunk/mono/mono/mini/mini-amd64.h 2007-12-07 14:00:30 UTC (rev 90930)
@@ -269,6 +269,7 @@
#define MONO_ARCH_HAVE_ATOMIC_EXCHANGE 1
#define MONO_ARCH_HAVE_IMT 1
#define MONO_ARCH_IMT_REG AMD64_R11
+#define MONO_ARCH_VTABLE_REG AMD64_R11
#define MONO_ARCH_COMMON_VTABLE_TRAMPOLINE 1
#define MONO_ARCH_AOT_SUPPORTED 1
Modified: trunk/mono/mono/mini/mini-ops.h
===================================================================
--- trunk/mono/mono/mini/mini-ops.h 2007-12-07 13:39:31 UTC (rev 90929)
+++ trunk/mono/mono/mini/mini-ops.h 2007-12-07 14:00:30 UTC (rev 90930)
@@ -36,6 +36,7 @@
MINI_OP(OP_VOIDCALLVIRT, "voidcallvirt")
MINI_OP(OP_VOIDCALL_REG, "voidcall_reg")
MINI_OP(OP_VOIDCALL_MEMBASE, "voidcall_membase")
+MINI_OP(OP_TRAMPCALL_VTABLE, "trampcall_vtable")
MINI_OP(OP_FCALL, "fcall")
MINI_OP(OP_FCALLVIRT, "fcallvirt")
MINI_OP(OP_FCALL_REG, "fcall_reg")
Modified: trunk/mono/mono/mini/mini-trampolines.c
===================================================================
--- trunk/mono/mono/mini/mini-trampolines.c 2007-12-07 13:39:31 UTC (rev
90929)
+++ trunk/mono/mono/mini/mini-trampolines.c 2007-12-07 14:00:30 UTC (rev
90930)
@@ -292,6 +292,24 @@
}
}
+/**
+ * mono_generic_class_init_trampoline:
+ *
+ * This method calls mono_runtime_class_init () to run the static constructor
+ * for the type, then patches the caller code so it is not called again.
+ */
+void
+mono_generic_class_init_trampoline (gssize *regs, guint8 *code, gpointer
dummy, guint8 *tramp)
+{
+ MonoVTable *vtable = mono_arch_find_vtable ((gpointer*)regs, code);
+
+ //g_print ("generic class init for class %s.%s\n",
vtable->klass->name_space, vtable->klass->name);
+
+ mono_runtime_class_init (vtable);
+
+ //g_print ("done initing generic\n");
+}
+
#ifdef MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE
/**
Modified: trunk/mono/mono/mini/mini-x86.c
===================================================================
--- trunk/mono/mono/mini/mini-x86.c 2007-12-07 13:39:31 UTC (rev 90929)
+++ trunk/mono/mono/mini/mini-x86.c 2007-12-07 14:00:30 UTC (rev 90930)
@@ -4371,6 +4371,12 @@
}
#endif
+MonoVTable*
+mono_arch_find_vtable (gpointer *regs, guint8 *code)
+{
+ return (MonoVTable*) regs [MONO_ARCH_VTABLE_REG];
+}
+
MonoInst*
mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod,
MonoMethodSignature *fsig, MonoInst **args)
{
Modified: trunk/mono/mono/mini/mini-x86.h
===================================================================
--- trunk/mono/mono/mini/mini-x86.h 2007-12-07 13:39:31 UTC (rev 90929)
+++ trunk/mono/mono/mini/mini-x86.h 2007-12-07 14:00:30 UTC (rev 90930)
@@ -276,6 +276,7 @@
#define MONO_ARCH_HAVE_ATOMIC_EXCHANGE 1
#define MONO_ARCH_HAVE_IMT 1
#define MONO_ARCH_IMT_REG X86_EDX
+#define MONO_ARCH_VTABLE_REG X86_EDX
#define MONO_ARCH_COMMON_VTABLE_TRAMPOLINE 1
#define MONO_ARCH_AOT_SUPPORTED 1
Modified: trunk/mono/mono/mini/mini.c
===================================================================
--- trunk/mono/mono/mini/mini.c 2007-12-07 13:39:31 UTC (rev 90929)
+++ trunk/mono/mono/mini/mini.c 2007-12-07 14:00:30 UTC (rev 90930)
@@ -152,6 +152,7 @@
/* helper methods signature */
static MonoMethodSignature *helper_sig_class_init_trampoline = NULL;
+static MonoMethodSignature *helper_sig_generic_class_init_trampoline = NULL;
static MonoMethodSignature *helper_sig_domain_get = NULL;
static guint32 default_opt = 0;
@@ -6744,6 +6745,8 @@
case CEE_STSFLD: {
MonoClassField *field;
gpointer addr = NULL;
+ gboolean shared_access = FALSE;
+ int relation;
CHECK_OPSIZE (5);
token = read32 (ip + 1);
@@ -6759,9 +6762,33 @@
if (!dont_verify && !cfg->skip_visibility &&
!mono_method_can_access_field (method, field))
FIELD_ACCESS_FAILURE;
- if (cfg->generic_sharing_context &&
mono_class_check_context_used (klass))
- GENERIC_SHARING_FAILURE (*ip);
+ /*
+ * We can only support shared generic static
+ * field access on architectures where the
+ * trampoline code has been extended to handle
+ * the generic class init.
+ */
+#ifndef MONO_ARCH_VTABLE_REG
+ GENERIC_SHARING_FAILURE (*ip);
+#endif
+ if (cfg->generic_sharing_context) {
+ int context_used =
mono_class_check_context_used (klass);
+
+ if (context_used &
MONO_GENERIC_CONTEXT_USED_METHOD ||
+ klass->valuetype)
+ GENERIC_SHARING_FAILURE (*ip);
+
+ if (context_used) {
+ relation =
mono_class_generic_class_relation (klass, method->klass, generic_context, NULL);
+
+ if (!(method->flags &
METHOD_ATTRIBUTE_STATIC) /*&& relation != MINI_GENERIC_CLASS_RELATION_OTHER*/)
+ shared_access = TRUE;
+ else
+ GENERIC_SHARING_FAILURE (*ip);
+ }
+ }
+
g_assert (!(field->type->attrs &
FIELD_ATTRIBUTE_LITERAL));
if ((*ip) == CEE_STSFLD)
@@ -6777,7 +6804,70 @@
addr = g_hash_table_lookup
(cfg->domain->special_static_fields, field);
mono_domain_unlock (cfg->domain);
- if ((cfg->opt & MONO_OPT_SHARED) || (cfg->compile_aot
&& addr)) {
+ if (shared_access) {
+ MonoInst *this, *rgctx, *static_data;
+
+ /*
+ g_print ("sharing static field access in
%s.%s.%s - depth %d offset %d\n",
+ method->klass->name_space,
method->klass->name, method->name,
+ depth, field->offset);
+ */
+
+ if (mono_class_needs_cctor_run (klass, method))
{
+ MonoMethodSignature *sig =
helper_sig_generic_class_init_trampoline;
+ MonoCallInst *call;
+ MonoInst *this, *vtable;
+
+ NEW_ARGLOAD (cfg, this, 0);
+
+ if (relation ==
MINI_GENERIC_CLASS_RELATION_SELF) {
+ MONO_INST_NEW (cfg, vtable,
CEE_LDIND_I);
+ vtable->cil_code = ip;
+ vtable->inst_left = this;
+ vtable->type = STACK_PTR;
+ vtable->klass = klass;
+ } else {
+ MonoInst *rgctx =
get_runtime_generic_context_from_this (cfg, this, ip);
+
+ vtable =
get_runtime_generic_context_ptr (cfg, method, bblock, klass,
+ token, generic_context,
rgctx, MINI_RGCTX_VTABLE, ip);
+ }
+
+ call = mono_emit_call_args (cfg,
bblock, sig, NULL, FALSE, FALSE, ip, FALSE);
+ call->inst.opcode = OP_TRAMPCALL_VTABLE;
+ call->fptr = mono_get_trampoline_code
(MONO_TRAMPOLINE_GENERIC_CLASS_INIT);
+
+ call->inst.inst_left = vtable;
+
+ mono_spill_call (cfg, bblock, call,
sig, FALSE, ip, FALSE);
+ }
+
+ /*
+ * The pointer we're computing here is
+ *
+ * super_info.static_data + field->offset
+ */
+
+ NEW_ARGLOAD (cfg, this, 0);
+ rgctx = get_runtime_generic_context_from_this
(cfg, this, ip);
+ static_data = get_runtime_generic_context_ptr
(cfg, method, bblock, klass,
+ token, generic_context, rgctx,
MINI_RGCTX_STATIC_DATA, ip);
+
+ if (field->offset == 0) {
+ ins = static_data;
+ } else {
+ MonoInst *field_offset;
+
+ NEW_ICONST (cfg, field_offset,
field->offset);
+
+ MONO_INST_NEW (cfg, ins, OP_PADD);
+ ins->cil_code = ip;
+ ins->inst_left = static_data;
+ ins->inst_right = field_offset;
+ ins->type = STACK_PTR;
+ ins->klass = klass;
+ }
+ } else if ((cfg->opt & MONO_OPT_SHARED) ||
(cfg->compile_aot && addr)) {
int temp;
MonoInst *iargs [2];
MonoInst *domain_var;
@@ -6859,7 +6949,7 @@
} else {
gboolean is_const = FALSE;
MonoVTable *vtable = mono_class_vtable
(cfg->domain, klass);
- if (!((cfg->opt & MONO_OPT_SHARED) ||
cfg->compile_aot) &&
+ if (!shared_access && !((cfg->opt &
MONO_OPT_SHARED) || cfg->compile_aot) &&
vtable->initialized && (field->type->attrs
& FIELD_ATTRIBUTE_INIT_ONLY)) {
gpointer addr = (char*)vtable->data +
field->offset;
int ro_type = field->type->type;
@@ -8497,7 +8587,8 @@
case OP_VCALL:
case OP_VCALLVIRT:
case OP_VOIDCALL:
- case OP_VOIDCALLVIRT: {
+ case OP_VOIDCALLVIRT:
+ case OP_TRAMPCALL_VTABLE: {
MonoCallInst *call = (MonoCallInst*)tree;
if (call->method)
printf ("[%s]", call->method->name);
@@ -8589,6 +8680,7 @@
{
helper_sig_domain_get = mono_create_icall_signature ("ptr");
helper_sig_class_init_trampoline = mono_create_icall_signature ("void");
+ helper_sig_generic_class_init_trampoline = mono_create_icall_signature
("void");
}
gconstpointer
@@ -8637,6 +8729,7 @@
mono_trampoline_code [MONO_TRAMPOLINE_GENERIC] =
mono_arch_create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
mono_trampoline_code [MONO_TRAMPOLINE_JUMP] =
mono_arch_create_trampoline_code (MONO_TRAMPOLINE_JUMP);
mono_trampoline_code [MONO_TRAMPOLINE_CLASS_INIT] =
mono_arch_create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
+ mono_trampoline_code [MONO_TRAMPOLINE_GENERIC_CLASS_INIT] =
mono_arch_create_trampoline_code (MONO_TRAMPOLINE_GENERIC_CLASS_INIT);
#ifdef MONO_ARCH_AOT_SUPPORTED
mono_trampoline_code [MONO_TRAMPOLINE_AOT] =
mono_arch_create_trampoline_code (MONO_TRAMPOLINE_AOT);
mono_trampoline_code [MONO_TRAMPOLINE_AOT_PLT] =
mono_arch_create_trampoline_code (MONO_TRAMPOLINE_AOT_PLT);
@@ -8668,6 +8761,8 @@
{
gpointer code, ptr;
+ g_assert (!vtable->klass->generic_container);
+
/* previously created trampoline code */
mono_domain_lock (vtable->domain);
ptr =
Modified: trunk/mono/mono/mini/mini.h
===================================================================
--- trunk/mono/mono/mini/mini.h 2007-12-07 13:39:31 UTC (rev 90929)
+++ trunk/mono/mono/mini/mini.h 2007-12-07 14:00:30 UTC (rev 90930)
@@ -513,6 +513,7 @@
MONO_TRAMPOLINE_GENERIC,
MONO_TRAMPOLINE_JUMP,
MONO_TRAMPOLINE_CLASS_INIT,
+ MONO_TRAMPOLINE_GENERIC_CLASS_INIT,
MONO_TRAMPOLINE_AOT,
MONO_TRAMPOLINE_AOT_PLT,
MONO_TRAMPOLINE_DELEGATE,
@@ -963,6 +964,7 @@
gpointer mono_aot_plt_trampoline (gssize *regs, guint8 *code, guint8
*token_info,
guint8* tramp) MONO_INTERNAL;
void mono_class_init_trampoline (gssize *regs, guint8 *code,
MonoVTable *vtable, guint8 *tramp) MONO_INTERNAL;
+void mono_generic_class_init_trampoline (gssize *regs, guint8
*code, gpointer dummy, guint8 *tramp) MONO_INTERNAL;
gpointer mini_get_vtable_trampoline (void) MONO_INTERNAL;
gpointer mono_debugger_create_notification_function (void)
MONO_INTERNAL;
@@ -1060,6 +1062,7 @@
void mono_arch_emit_imt_argument (MonoCompile *cfg,
MonoCallInst *call) MONO_INTERNAL;
MonoMethod* mono_arch_find_imt_method (gpointer *regs, guint8 *code)
MONO_INTERNAL;
MonoObject* mono_arch_find_this_argument (gpointer *regs, MonoMethod
*method) MONO_INTERNAL;
+MonoVTable* mono_arch_find_vtable (gpointer *regs, guint8 *code)
MONO_INTERNAL;
gpointer mono_arch_build_imt_thunk (MonoVTable *vtable,
MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count) MONO_INTERNAL;
/* Exception handling */
Modified: trunk/mono/mono/mini/tramp-amd64.c
===================================================================
--- trunk/mono/mono/mini/tramp-amd64.c 2007-12-07 13:39:31 UTC (rev 90929)
+++ trunk/mono/mono/mini/tramp-amd64.c 2007-12-07 14:00:30 UTC (rev 90930)
@@ -190,8 +190,10 @@
offset = 0;
- /* Pop the return address off the stack */
- amd64_pop_reg (code, AMD64_R11);
+ if (tramp_type != MONO_TRAMPOLINE_GENERIC_CLASS_INIT) {
+ /* Pop the return address off the stack */
+ amd64_pop_reg (code, AMD64_R11);
+ }
/*
* Allocate a new stack frame
@@ -200,16 +202,18 @@
amd64_mov_reg_reg (code, AMD64_RBP, AMD64_RSP, 8);
amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, framesize);
- offset += 8;
- tramp_offset = - offset;
+ if (tramp_type != MONO_TRAMPOLINE_GENERIC_CLASS_INIT) {
+ offset += 8;
+ tramp_offset = - offset;
- offset += 8;
- method_offset = - offset;
+ offset += 8;
+ method_offset = - offset;
- /* Compute the trampoline address from the return address */
- /* 5 = length of amd64_call_membase () */
- amd64_alu_reg_imm (code, X86_SUB, AMD64_R11, 5);
- amd64_mov_membase_reg (code, AMD64_RBP, tramp_offset, AMD64_R11, 8);
+ /* Compute the trampoline address from the return address */
+ /* 5 = length of amd64_call_membase () */
+ amd64_alu_reg_imm (code, X86_SUB, AMD64_R11, 5);
+ amd64_mov_membase_reg (code, AMD64_RBP, tramp_offset,
AMD64_R11, 8);
+ }
/* Save all registers */
@@ -222,22 +226,24 @@
for (i = 0; i < 8; ++i)
amd64_movsd_membase_reg (code, AMD64_RBP, saved_fpregs_offset +
(i * 8), i);
- /* Obtain the trampoline argument which is encoded in the instruction
stream */
- amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, tramp_offset, 8);
- amd64_mov_reg_membase (code, AMD64_RAX, AMD64_R11, 5, 1);
- amd64_widen_reg (code, AMD64_RAX, AMD64_RAX, TRUE, FALSE);
- amd64_alu_reg_imm_size (code, X86_CMP, AMD64_RAX, 4, 1);
- br [0] = code;
- x86_branch8 (code, X86_CC_NE, 6, FALSE);
- /* 32 bit immediate */
- amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 6, 4);
- br [1] = code;
- x86_jump8 (code, 10);
- /* 64 bit immediate */
- mono_amd64_patch (br [0], code);
- amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 6, 8);
- mono_amd64_patch (br [1], code);
- amd64_mov_membase_reg (code, AMD64_RBP, method_offset, AMD64_R11, 8);
+ if (tramp_type != MONO_TRAMPOLINE_GENERIC_CLASS_INIT) {
+ /* Obtain the trampoline argument which is encoded in the
instruction stream */
+ amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP,
tramp_offset, 8);
+ amd64_mov_reg_membase (code, AMD64_RAX, AMD64_R11, 5, 1);
+ amd64_widen_reg (code, AMD64_RAX, AMD64_RAX, TRUE, FALSE);
+ amd64_alu_reg_imm_size (code, X86_CMP, AMD64_RAX, 4, 1);
+ br [0] = code;
+ x86_branch8 (code, X86_CC_NE, 6, FALSE);
+ /* 32 bit immediate */
+ amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 6, 4);
+ br [1] = code;
+ x86_jump8 (code, 10);
+ /* 64 bit immediate */
+ mono_amd64_patch (br [0], code);
+ amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 6, 8);
+ mono_amd64_patch (br [1], code);
+ amd64_mov_membase_reg (code, AMD64_RBP, method_offset,
AMD64_R11, 8);
+ }
/* Save LMF begin */
@@ -257,9 +263,11 @@
amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, 8);
amd64_alu_reg_imm (code, X86_ADD, AMD64_R11, framesize + 16);
amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET
(MonoLMF, rsp), AMD64_R11, 8);
- /* Save method */
- amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, method_offset, 8);
- amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET
(MonoLMF, method), AMD64_R11, 8);
+ if (tramp_type != MONO_TRAMPOLINE_GENERIC_CLASS_INIT) {
+ /* Save method */
+ amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP,
method_offset, 8);
+ amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset +
G_STRUCT_OFFSET (MonoLMF, method), AMD64_R11, 8);
+ }
/* Save callee saved regs */
#ifdef PLATFORM_WIN32
amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET
(MonoLMF, rdi), AMD64_RDI, 8);
@@ -294,14 +302,22 @@
else
amd64_mov_reg_imm (code, AMD64_ARG_REG2, 0);
- /* Arg3 is the method/vtable ptr */
- amd64_mov_reg_membase (code, AMD64_ARG_REG3, AMD64_RBP, method_offset,
8);
+ /* Arg3 is the method ptr / dummy */
+ if (tramp_type == MONO_TRAMPOLINE_GENERIC_CLASS_INIT)
+ amd64_mov_reg_imm (code, AMD64_ARG_REG3, 0);
+ else
+ amd64_mov_reg_membase (code, AMD64_ARG_REG3, AMD64_RBP,
method_offset, 8);
/* Arg4 is the trampoline address */
- amd64_mov_reg_membase (code, AMD64_ARG_REG4, AMD64_RBP, tramp_offset,
8);
+ if (tramp_type == MONO_TRAMPOLINE_GENERIC_CLASS_INIT)
+ amd64_mov_reg_imm (code, AMD64_ARG_REG4, 0);
+ else
+ amd64_mov_reg_membase (code, AMD64_ARG_REG4, AMD64_RBP,
tramp_offset, 8);
if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT)
tramp = (guint8*)mono_class_init_trampoline;
+ else if (tramp_type == MONO_TRAMPOLINE_GENERIC_CLASS_INIT)
+ tramp = (guint8*)mono_generic_class_init_trampoline;
else if (tramp_type == MONO_TRAMPOLINE_AOT)
tramp = (guint8*)mono_aot_trampoline;
else if (tramp_type == MONO_TRAMPOLINE_AOT_PLT)
@@ -331,7 +347,7 @@
/* Restore stack */
amd64_leave (code);
- if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT)
+ if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT || tramp_type ==
MONO_TRAMPOLINE_GENERIC_CLASS_INIT)
amd64_ret (code);
else
/* call the compiled method */
Modified: trunk/mono/mono/mini/tramp-x86.c
===================================================================
--- trunk/mono/mono/mini/tramp-x86.c 2007-12-07 13:39:31 UTC (rev 90929)
+++ trunk/mono/mono/mini/tramp-x86.c 2007-12-07 14:00:30 UTC (rev 90930)
@@ -190,6 +190,16 @@
* and it is stored at: esp + pushed_args * sizeof (gpointer)
* the ret address is at: esp + (pushed_args + 1) * sizeof (gpointer)
*/
+
+ /* If this is a generic class init the argument is not on the
+ * stack yet but in MONO_ARCH_VTABLE_REG and is accessed by
+ * the callee via the register array. As a dummy argument we
+ * pass it NULL, which we push here, and then everything that
+ * follows works the same way.
+ */
+ if (tramp_type == MONO_TRAMPOLINE_GENERIC_CLASS_INIT)
+ x86_push_imm (buf, 0);
+
/* Put all registers into an array on the stack
* If this code is changed, make sure to update the offset value in
* mono_arch_find_this_argument () in mini-x86.c.
@@ -298,6 +308,8 @@
if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT)
x86_call_code (buf, mono_class_init_trampoline);
+ else if (tramp_type == MONO_TRAMPOLINE_GENERIC_CLASS_INIT)
+ x86_call_code (buf, mono_generic_class_init_trampoline);
else if (tramp_type == MONO_TRAMPOLINE_AOT)
x86_call_code (buf, mono_aot_trampoline);
else if (tramp_type == MONO_TRAMPOLINE_AOT_PLT)
@@ -338,7 +350,7 @@
/* Pop saved reg array + stack align + method ptr */
x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 10 * 4);
- if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT)
+ if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT || tramp_type ==
MONO_TRAMPOLINE_GENERIC_CLASS_INIT)
x86_ret (buf);
else
/* call the compiled method */
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches