+ /* Initialize vtable */
+ if (callbacks.get_vtable_trampoline) {
+ // This also covers the AOT case
+ for (i = 0; i < class->vtable_size; ++i) {
+ vt->vtable [i] = callbacks.get_vtable_trampoline (i);
+ }
+ } else {
+ mono_class_setup_vtable (class);
+
+ for (i = 0; i < class->vtable_size; ++i) {
+ MonoMethod *cm;
+
+ if ((cm = class->vtable [i]))
+ vt->vtable [i] = arch_create_jit_trampoline (cm);
+ }
+ }
+
+ if (ARCH_USE_IMT && imt_table_bytes) {
+ /* Now that the vtable is full, we can actually fill up the IMT */
+ if (callbacks.get_imt_trampoline) {
+ /* lazy construction of the IMT entries enabled */
+ for (i = 0; i < MONO_IMT_SIZE; ++i)
+ interface_offsets [i] = callbacks.get_imt_trampoline (i);
+ } else {
+ build_imt (class, vt, domain, interface_offsets, NULL);
+ }
+ }
+
+ /*
+ * FIXME: Is it ok to allocate while holding the domain/loader locks ? If not, we can release them, allocate, then
+ * re-acquire them and check if another thread has created the vtable in the meantime.
+ */
+ /* Special case System.MonoType to avoid infinite recursion */
+ if (class != mono_defaults.monotype_class) {
+ /*FIXME check for OOM*/
+ vt->type = mono_type_get_object (domain, &class->byval_arg);
+ if (mono_object_get_class (vt->type) != mono_defaults.monotype_class)
+ /* This is unregistered in
+ unregister_vtable_reflection_type() in
+ domain.c. */
+ MONO_GC_REGISTER_ROOT_IF_MOVING(vt->type);
+ }
+
+ if (class->contextbound)
+ vt->remote = 1;
+ else
+ vt->remote = 0;
+