ip += 3;
MINT_IN_BREAK;
}
- MINT_IN_CASE(MINT_NEWOBJ_FAST)
+ MINT_IN_CASE(MINT_NEWOBJ_FAST) {
+ guint16 param_count;
+ guint16 imethod_index = *(guint16*) (ip + 1);
+
+ const gboolean is_inlined = imethod_index == 0xffff;
+
+ param_count = *(guint16*)(ip + 2);
+
+ if (param_count) {
+ sp -= param_count;
+ memmove (sp + 1 + is_inlined, sp, param_count * sizeof (stackval));
+ }
+
+ MonoVTable *vtable = (MonoVTable*) imethod->data_items [*(guint16*)(ip + 3)];
+ INIT_VTABLE (vtable);
+
+ frame_objref (frame) = mono_gc_alloc_obj (vtable, m_class_get_instance_size (vtable->klass));
+ if (G_UNLIKELY (!frame_objref (frame))) {
+ mono_error_set_out_of_memory (error, "Could not allocate %i bytes", m_class_get_instance_size (vtable->klass));
+ THROW_EX (mono_error_convert_to_exception (error), ip);
+ }
+
+ sp [0].data.o = frame_objref (frame);
+ if (is_inlined) {
+ sp [1].data.o = frame_objref (frame);
+ sp += param_count + 2;
+ } else {
+ InterpMethod *ctor_method = (InterpMethod*) imethod->data_items [imethod_index];
+ frame->ip = ip;
+
+ child_frame.imethod = ctor_method;
+ child_frame.stack_args = sp;
+
+ interp_exec_method (&child_frame, context, error);
+ CHECK_RESUME_STATE (context);
+ sp [0].data.o = frame_objref (frame);
+ sp++;
+ }
+ ip += 4;
+
+ MINT_IN_BREAK;
+ }
MINT_IN_CASE(MINT_NEWOBJ_VT_FAST)
MINT_IN_CASE(MINT_NEWOBJ_VTST_FAST) {
guint16 param_count;
- gboolean vt = *ip != MINT_NEWOBJ_FAST;
stackval valuetype_this;
frame->ip = ip;
}
child_frame.stack_args = sp;
- if (vt) {
- gboolean vtst = *ip == MINT_NEWOBJ_VTST_FAST;
- if (vtst) {
- memset (vt_sp, 0, *(guint16*)(ip + 3));
- sp->data.p = vt_sp;
- valuetype_this.data.p = vt_sp;
- ip += 4;
- } else {
- memset (&valuetype_this, 0, sizeof (stackval));
- sp->data.p = &valuetype_this;
- ip += 3;
- }
- } else {
- MonoVTable *vtable = (MonoVTable*) imethod->data_items [*(guint16*)(ip + 3)];
- if (G_UNLIKELY (!vtable->initialized)) {
- mono_runtime_class_init_full (vtable, error);
- if (!mono_error_ok (error))
- THROW_EX (mono_error_convert_to_exception (error), ip);
- }
- frame_objref (frame) = mono_gc_alloc_obj (vtable, m_class_get_instance_size (vtable->klass));
- if (G_UNLIKELY (!frame_objref (frame))) {
- mono_error_set_out_of_memory (error, "Could not allocate %i bytes", m_class_get_instance_size (vtable->klass));
- THROW_EX (mono_error_convert_to_exception (error), ip);
- }
- sp->data.o = frame_objref (frame);
+ gboolean vtst = *ip == MINT_NEWOBJ_VTST_FAST;
+ if (vtst) {
+ memset (vt_sp, 0, *(guint16*)(ip + 3));
+ sp->data.p = vt_sp;
+ valuetype_this.data.p = vt_sp;
ip += 4;
+ } else {
+ memset (&valuetype_this, 0, sizeof (stackval));
+ sp->data.p = &valuetype_this;
+ ip += 3;
}
interp_exec_method (&child_frame, context, error);
CHECK_RESUME_STATE (context);
- if (vt)
- *sp = valuetype_this;
- else
- sp->data.p = frame_objref (frame);
+ *sp = valuetype_this;
++sp;
MINT_IN_BREAK;
}
do { \
(td)->stack_capacity *= 2; \
(td)->stack = (StackInfo*)realloc ((td)->stack, (td)->stack_capacity * sizeof (td->stack [0])); \
- (td)->sp = (td)->stack + sppos; \
+ (td)->sp = (td)->stack + (sppos); \
} while (0);
#define PUSH_SIMPLE_TYPE(td, ty) \
SET_TYPE((td)->sp - 1, ty, k); \
} while (0)
+static void
+move_stack (TransformData *td, int start, int amount)
+{
+ int sp_height = td->sp - td->stack;
+ int to_move = sp_height - start;
+
+ td->sp += amount;
+ sp_height += amount;
+ if (amount > 0) {
+ if (sp_height > td->max_stack_height)
+ td->max_stack_height = sp_height;
+ if (sp_height > td->stack_capacity)
+ REALLOC_STACK (td, sp_height);
+ } else {
+ g_assert (td->sp >= td->stack);
+ }
+
+ if (to_move > 0)
+ memmove (td->stack + start + amount, td->stack + start, to_move * sizeof (StackInfo));
+}
+
#define PUSH_VT(td, size) \
do { \
(td)->vt_sp += ALIGN_TO ((size), MINT_VT_ALIGNMENT); \
goto_if_nok (error, exit);
}
- td->sp -= csignature->param_count;
if (mono_class_is_magic_int (klass) || mono_class_is_magic_float (klass)) {
+ td->sp -= csignature->param_count;
#if SIZEOF_VOID_P == 8
if (mono_class_is_magic_int (klass) && td->sp [0].type == STACK_TYPE_I4)
interp_add_ins (td, MINT_CONV_I8_I4);
!mono_class_is_marshalbyref (klass) &&
!mono_class_has_finalizer (klass) &&
!m_class_has_weak_fields (klass)) {
- if (!m_class_is_valuetype (klass))
- interp_add_ins (td, MINT_NEWOBJ_FAST);
- else if (mint_type (m_class_get_byval_arg (klass)) == MINT_TYPE_VT)
- interp_add_ins (td, MINT_NEWOBJ_VTST_FAST);
- else
- interp_add_ins (td, MINT_NEWOBJ_VT_FAST);
+ if (!m_class_is_valuetype (klass)) {
+ InterpInst *newobj_fast = interp_add_ins (td, MINT_NEWOBJ_FAST);
- td->last_ins->data [0] = get_data_item_index (td, mono_interp_get_imethod (domain, m, error));
- td->last_ins->data [1] = csignature->param_count;
+ newobj_fast->data [1] = csignature->param_count;
- if (!m_class_is_valuetype (klass)) {
MonoVTable *vtable = mono_class_vtable_checked (domain, klass, error);
goto_if_nok (error, exit);
- td->last_ins->data [2] = get_data_item_index (td, vtable);
- } else if (mint_type (m_class_get_byval_arg (klass)) == MINT_TYPE_VT) {
- td->last_ins->data [2] = mono_class_value_size (klass, NULL);
+ newobj_fast->data [2] = get_data_item_index (td, vtable);
+
+ move_stack (td, (td->sp - td->stack) - csignature->param_count, 2);
+
+ StackInfo *tmp_sp = td->sp - csignature->param_count - 2;
+ SET_TYPE (tmp_sp, STACK_TYPE_O, klass);
+ SET_TYPE (tmp_sp + 1, STACK_TYPE_O, klass);
+
+ if ((mono_interp_opt & INTERP_OPT_INLINE) && interp_method_check_inlining (td, m)) {
+ MonoMethodHeader *mheader = interp_method_get_header (m, error);
+ goto_if_nok (error, exit);
+
+ if (interp_inline_method (td, m, mheader, error)) {
+ newobj_fast->data [0] = 0xffff;
+ break;
+ }
+ }
+ // If inlining failed we need to restore the stack
+ move_stack (td, (td->sp - td->stack) - csignature->param_count, -2);
+ // Set the method to be executed as part of newobj instruction
+ newobj_fast->data [0] = get_data_item_index (td, mono_interp_get_imethod (domain, m, error));
+ } else {
+ if (mint_type (m_class_get_byval_arg (klass)) == MINT_TYPE_VT)
+ interp_add_ins (td, MINT_NEWOBJ_VTST_FAST);
+ else
+ interp_add_ins (td, MINT_NEWOBJ_VT_FAST);
+
+ td->last_ins->data [0] = get_data_item_index (td, mono_interp_get_imethod (domain, m, error));
+ td->last_ins->data [1] = csignature->param_count;
+
+ if (mint_type (m_class_get_byval_arg (klass)) == MINT_TYPE_VT) {
+ td->last_ins->data [2] = mono_class_value_size (klass, NULL);
+ }
}
} else {
interp_add_ins (td, MINT_NEWOBJ);
}
goto_if_nok (error, exit);
+ td->sp -= csignature->param_count;
if (mint_type (m_class_get_byval_arg (klass)) == MINT_TYPE_VT) {
vt_res_size = mono_class_value_size (klass, NULL);
PUSH_VT (td, vt_res_size);