void
mono_mb_emit_cominterop_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethod* method)
{
+#ifndef DISABLE_JIT
// get function pointer from 1st arg, the COM interface pointer
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_icon (mb, cominterop_get_com_slot_for_method (method));
mono_mb_emit_calli (mb, sig);
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_byte (mb, CEE_MONO_RESTORE_LMF);
+#endif /* DISABLE_JIT */
}
void
mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec)
{
+#ifndef DISABLE_JIT
switch (conv) {
case MONO_MARSHAL_CONV_OBJECT_INTERFACE:
case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN:
default:
g_assert_not_reached ();
}
+#endif /* DISABLE_JIT */
}
void
mono_cominterop_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec)
{
+#ifndef DISABLE_JIT
switch (conv) {
case MONO_MARSHAL_CONV_OBJECT_INTERFACE:
case MONO_MARSHAL_CONV_OBJECT_IDISPATCH:
default:
g_assert_not_reached ();
}
+#endif /* DISABLE_JIT */
}
/**
sig = mono_method_signature (method);
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_COMINTEROP);
+#ifndef DISABLE_JIT
/* if method klass is import, that means method
* is really a com call. let interop system emit it.
*/
imported classes is not yet implemented.");
mono_mb_emit_exception (mb, "NotSupportedException", msg);
}
+#endif /* DISABLE_JIT */
+
csig = mono_metadata_signature_dup_full (method->klass->image, sig);
csig->pinvoke = 0;
res = mono_mb_create_and_cache (cache, method,
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_COMINTEROP_INVOKE);
+#ifndef DISABLE_JIT
/* get real proxy object, which is a ComInteropProxy in this case*/
mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
mono_mb_emit_ldarg (mb, 0);
mono_marshal_emit_thread_interrupt_checkpoint (mb);
mono_mb_emit_byte (mb, CEE_RET);
+#endif /* DISABLE_JIT */
res = mono_mb_create_and_cache (cache, method, mb, sig, sig->param_count + 16);
mono_mb_free (mb);
if (!marshal_release)
marshal_release = mono_class_get_method_from_name (mono_defaults.marshal_class, "Release", 1);
+#ifdef DISABLE_JIT
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN:
+ *conv_arg_type = &mono_defaults.int_class->byval_arg;
+ break;
+ case MARSHAL_ACTION_MANAGED_CONV_IN:
+ *conv_arg_type = &mono_defaults.int_class->byval_arg;
+ break;
+ default:
+ break;
+ }
+#else
switch (action) {
case MARSHAL_ACTION_CONV_IN: {
guint32 pos_null = 0;
default:
g_assert_not_reached ();
}
+#endif /* DISABLE_JIT */
return conv_arg;
}
mspecs [0] = NULL;
}
+#ifndef DISABLE_JIT
/* skip visiblity since we call internal methods */
mb->skip_visibility = TRUE;
+#endif
cominterop_setup_marshal_context (&m, adjust_method);
m.mb = mb;
vtable [vtable_index--] = mono_compile_method (wrapper_method);
-
for (param_index = sig_adjusted->param_count; param_index >= 0; param_index--)
if (mspecs [param_index])
mono_metadata_free_marshal_spec (mspecs [param_index]);
mspecs [0] = NULL;
- if (!preserve_sig) {
+#ifndef DISABLE_JIT
+ if (!preserve_sig)
hr = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg);
- }
else if (!MONO_TYPE_IS_VOID (sig->ret))
hr = mono_mb_add_local (mb, sig->ret);
mono_mb_emit_ldloc (mb, hr);
mono_mb_emit_byte (mb, CEE_RET);
+#endif /* DISABLE_JIT */
mono_cominterop_lock ();
res = mono_mb_create_method (mb, sig_native, sig_native->param_count + 16);
{
MonoMethodBuilder *mb = m->mb;
+#ifndef DISABLE_JIT
switch (action) {
-
case MARSHAL_ACTION_CONV_IN: {
-
if (t->attrs & PARAM_ATTRIBUTE_IN) {
/* Generates IL code for the following algorithm:
break;
case MARSHAL_ACTION_CONV_OUT: {
-
if (t->attrs & PARAM_ATTRIBUTE_OUT) {
/* Generates IL code for the following algorithm:
default:
g_assert_not_reached ();
}
+#endif /* DISABLE_JIT */
return conv_arg;
}
return emit_marshal_string (m, argnum, t, spec, conv_arg, conv_arg_type, action);
case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
-#ifndef DISABLE_COM
+#if !defined(DISABLE_COM) && !defined(DISABLE_JIT)
if (spec && spec->native == MONO_NATIVE_STRUCT)
return emit_marshal_variant (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+#endif
+#if !defined(DISABLE_COM)
if (spec && (spec->native == MONO_NATIVE_IUNKNOWN ||
spec->native == MONO_NATIVE_IDISPATCH ||
spec->native == MONO_NATIVE_INTERFACE))
gc_descr = mono_gc_get_description ();
g_print ("\tGC: %s\n", gc_descr);
g_free (gc_descr);
- if (mini_verbose) {
- const char *cerror;
- const char *clibpath;
- mono_init ("mono");
- cerror = mono_check_corlib_version ();
- clibpath = mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown";
- if (cerror) {
- g_print ("The currently installed mscorlib doesn't match this runtime version.\n");
- g_print ("The error is: %s\n", cerror);
- g_print ("mscorlib.dll loaded at: %s\n", clibpath);
- return 1;
- }
- }
return 0;
} else if (strcmp (argv [i], "--help") == 0 || strcmp (argv [i], "-h") == 0) {
mini_usage ();
guint16 obj_size_index;
/* FIXME: Reduce this - it only needs a byte. */
volatile gint32 state;
+ gint16 nused;
unsigned int pinned : 1;
unsigned int has_references : 1;
unsigned int has_pinned : 1; /* means cannot evacuate */
for (i = 0; i < MS_NUM_MARK_WORDS; ++i)
nused += bitcount (block->mark_words [i]);
+ block->nused = nused;
if (nused)
have_live = TRUE;
if (nused < count)
#endif
}
+static int
+block_usage_comparer (const void *bl1, const void *bl2)
+{
+ const gint16 nused1 = (*(MSBlockInfo**)bl1)->nused;
+ const gint16 nused2 = (*(MSBlockInfo**)bl2)->nused;
+
+ return nused2 - nused1;
+}
+
+static void
+sgen_evacuation_freelist_blocks (MSBlockInfo * volatile *block_list, int size_index)
+{
+ MSBlockInfo **evacuated_blocks;
+ size_t index = 0, count, num_blocks = 0, num_used = 0;
+ MSBlockInfo *info;
+ MSBlockInfo * volatile *prev;
+
+ for (info = *block_list; info != NULL; info = info->next_free) {
+ num_blocks++;
+ num_used += info->nused;
+ }
+
+ /*
+ * We have a set of blocks in the freelist which will be evacuated. Instead
+ * of evacuating all of the blocks into new ones, we traverse the freelist
+ * sorting it by the number of occupied slots, evacuating the objects from
+ * blocks with fewer used slots into fuller blocks.
+ *
+ * The number of used slots is set at the end of the previous sweep. Since
+ * we sequentially unlink slots from blocks, except for the head of the
+ * freelist, for blocks on the freelist, the number of used slots is the same
+ * as at the end of the previous sweep.
+ */
+ evacuated_blocks = (MSBlockInfo**)sgen_alloc_internal_dynamic (sizeof (MSBlockInfo*) * num_blocks, INTERNAL_MEM_TEMPORARY, TRUE);
+
+ for (info = *block_list; info != NULL; info = info->next_free) {
+ evacuated_blocks [index++] = info;
+ }
+
+ SGEN_ASSERT (0, num_blocks == index, "Why did the freelist change ?");
+
+ qsort (evacuated_blocks, num_blocks, sizeof (gpointer), block_usage_comparer);
+
+ /*
+ * Form a new freelist with the fullest blocks. These blocks will also be
+ * marked as to_space so we don't evacuate from them.
+ */
+ count = MS_BLOCK_FREE / block_obj_sizes [size_index];
+ prev = block_list;
+ for (index = 0; index < (num_used + count - 1) / count; index++) {
+ SGEN_ASSERT (0, index < num_blocks, "Why do we need more blocks for compaction than we already had ?");
+ info = evacuated_blocks [index];
+ info->is_to_space = TRUE;
+ *prev = info;
+ prev = &info->next_free;
+ }
+ *prev = NULL;
+
+ sgen_free_internal_dynamic (evacuated_blocks, sizeof (MSBlockInfo*) * num_blocks, INTERNAL_MEM_TEMPORARY);
+}
+
static void
major_start_major_collection (void)
{
binary_protocol_evacuating_blocks (block_obj_sizes [i]);
- free_block_lists [0][i] = NULL;
- free_block_lists [MS_BLOCK_FLAG_REFS][i] = NULL;
+ sgen_evacuation_freelist_blocks (&free_block_lists [0][i], i);
+ sgen_evacuation_freelist_blocks (&free_block_lists [MS_BLOCK_FLAG_REFS][i], i);
}
if (lazy_sweep)
sweep_block (block);
SGEN_ASSERT (0, block->state == BLOCK_STATE_SWEPT, "All blocks must be swept when we're pinning.");
set_block_state (block, BLOCK_STATE_MARKING, BLOCK_STATE_SWEPT);
+ /*
+ * Swept blocks that have a null free_list are full. Evacuation is not
+ * effective on these blocks since we expect them to have high usage anyway,
+ * given that the survival rate for majors is relatively high.
+ */
+ if (evacuate_block_obj_sizes [block->obj_size_index] && !block->free_list)
+ block->is_to_space = TRUE;
} END_FOREACH_BLOCK_NO_LOCK;
if (lazy_sweep)