summaryrefslogtreecommitdiff
path: root/doc/mono-gc.txt
diff options
context:
space:
mode:
Diffstat (limited to 'doc/mono-gc.txt')
-rw-r--r--doc/mono-gc.txt445
1 files changed, 0 insertions, 445 deletions
diff --git a/doc/mono-gc.txt b/doc/mono-gc.txt
deleted file mode 100644
index bc30334c5..000000000
--- a/doc/mono-gc.txt
+++ /dev/null
@@ -1,445 +0,0 @@
-The problem:
- + mono is mind mangled & doesn't expose a sane GC API
- + ie. it wants to know about your entire C stack & wander over it
- + it should push/pop start/stop tags as we invoke in/out
- + it should manage C handles with a controlled lifecycle
- mechanism: ref/unref layered on top of the GC
- => no need to worry about walking the C stack.
- + however - this is horribly broken somehow.
-
-We really need something like GC_start_routine()
- the start_info would be used to invoke our fn. and cleanup would
- be automatic.
-
-* RedHerring 1: what is:
- GC_push_all_stack(self, <base ptr>)
- called from GCThreadFunctions mono_gc_thread_vtable
- -> mono_gc_push_all_stacks
- + for the debugger [ libgc/include/libgc-mono-debugger.h ]
-
-
-* The pthread_support.c code seems to be not much called:
- GC_segment_is_thread_stack - only from some dlopen code
- GC_register_map_entries() [ filtering out code regions ? ]
-
- * seems to call GC_add_roots *
-
- /* Add a root segment. Wizards only. */
- GC_API void GC_add_roots GC_PROTO((char * low_address,
- char * high_address_plus_1));
- /* Remove a root segment. Wizards only. */
- GC_API void GC_remove_roots GC_PROTO((char * low_address,
- char * high_address_plus_1));
-
-
-* Adding a thread has to set the GC_suspend_handler / GC_restart_handler
- + cf. pthread_stop_world, pthread_stop_init (?)
-
- + GC_stop_world uses the stop_world method from the vtable ...
- GCThreadFunctions *gc_thread_vtable = &pthread_thread_vtable;
-
- => We need thread data to ensure we have stopped all the threads properly.
- => we need to setup / install our signal handler properly in
- each thread.
-
- + The high stack pointer is grokked from the
- GC_approx_sp function - from the signal handler - just
- returns cur ptr. - signal handler executing on stack of
- signal recieving thread. [ fun ]
-
-* GC_push_all_stacks [ pthread_stop_world.c ]
- + calls 'push_all_stack' for each thread.
- + called from os_dep.c (GC_default_push_other_roots)
- [ GC_push_other_roots ]
-
-* Hacking libgc:
-
-<lupus> yes, I suggest just duplicating the needed code for now
-<michael_> lupus: is this a minimal-changes regimen ? or a wild-crazy-re-factoring-festival ?
-<lupus> michael_: no crazy refactoring:-)
-<michael_> lupus: and what does one do about a non-internal libgcj ? - or is that not a case worth worrying about ?
-<lupus> michael_: we'll use the proper ifdef in the mono runtime
-<michael_> sure - but it's ok to break horribly if we're not using an internal libgcj ? ;-)
-<lupus> but a not internal gc is just for our testing, it's not a supported feature for people to use
-<michael_> ie. no foreign-thread / OO.o impl. ?
-<michael_> oh - great :-)
-
-** How does Mono get a callback from the pthread foo ?
- +
-
-We need to add the functionality we need to mono_thread_attach
-
-
-2005-04-12 log:
-
-<michael_> lupus: so - are you utterly opposed to adding this to mono_runtime_invoke ?
-<lupus> michael_: why should I be opposed?
-<michael_> lupus: there is a small cost, particularly if you don't have a thread-variable,
-<michael_> lupus: of course - then we could bin the mono_thread_attach or whatever;
-<lupus> michael_: unmanaged->managed is not an important transition and a simple check is cheap
-<lupus> of course there is no need to drop mono_thread_attach
-<michael_> lupus: ok'y dokey,
-<michael_> lupus: so - I'll re-work the patch to move this code into mono_runtime_invoke ?
-<lupus> michael_: if your current patch works for you, I can write the equivalent code for the next mono release
-<lupus> we're not going to remove the thread info at the end of _invoke
-<lupus> something like the setspecific hack you had may be enough
-<michael_> lupus: the problem is - we could get invoked again from lower down the stack in the same thread trivially.
-<michael_> lupus: so - it's really no safer;
-<michael_> lupus: and removing the thread information from the gc post invoke - [ if we added it ourself ] is cheap anyhow.
-<lupus> that is not cheap, it requires locking both in the runtime and the GC
-<lupus> I don't see what removing the info each time buys us
-<michael_> lupus: consider A() -> B() -> C() -> runtime_invoke -> adds stack base --><--
---> eno (~atsushi@east94-p4.eaccess.hi-ho.ne.jp) has joined #mono
-<lupus> the code I have in mind will check the stack start registered: if it doesn't contain the current stack address, we change it
-<michael_> lupus: subsequently A() -> runtime_invoke -> stack base is now --><--
-<michael_> lupus: sounds fine,
-<lupus> it will also register an aligned address
-<michael_> lupus: sounds fine,
-<lupus> at a page size so hopefully we get a good enough approximation of the thread start
-<michael_> lupus: sounds like you've got it under control anyhow
-<michael_> clearly manipulating the local thread stack/state should require precisely no locking in an ideal world ;-)
-<michael_> but ...
-<michael_> [ when we write a better GC - we'll make it perfectly precise - right ? ;-]
-<lupus> michael_: since you need to register the thread with the GC it's not possible to avoid a lock, since it's global state
-<lupus> and we won't have a perfectly precise GC
-<michael_> lupus: AFAICS the GC only asks for that when a signal is fired,
-<lupus> the unamanged stack will still be conservatively scanned for a while
-<lupus> michael_: the GC needs the stack boundaries when doing collection
-<michael_> lupus: I appreciate that ;-)
-<michael_> lupus: anyhow - thanks for taking that on.
-<michael_> lupus: when is the next release ? :-)
-<lupus> michael_: likely in a month or so
-
-
-
-
---------------------- Debugging my bogus (non)-GC related bug ---------------------
-
-0x8240e70
-
- + Threads created outside Mono's control ...
- + GC crash - under gdb:
- + greatest_ha -
-(gdb) p limit
-$1 = (word *) 0x83c2104
-(gdb) p *limit
-Cannot access memory at address 0x83c2104
-(gdb) p *(limit - 4096)
-$2 = 0
-(gdb) p *(limit + 4096)
-Cannot access memory at address 0x83c6104
-
- GC_mark_from mis-calculates limit, clearly it's scanning a
-broken / non-object; missing the length [ with 0 bottom 2 bits] tag /
-marker. Who sets that up ?
-
- The mark stack is a simple array, and looks fine ( in places ):
-
-$42 = {mse_start = 0x81fd800, mse_descr = 1024}
-(gdb) p mark_stack[14]
-$43 = {mse_start = 0x81eff00, mse_descr = 32}
-(gdb) p mark_stack[15]
-$44 = {mse_start = 0x81eef00, mse_descr = 160}
-(gdb) p mark_stack[16]
-$45 = {mse_start = 0x81fae00, mse_descr = 4294967279}
-... <identical > ...
-(gdb) p mark_stack[20]
-$52 = {mse_start = 0x8355000, mse_descr = 4294967279}
-(gdb) p mark_stack[21]
-$53 = {mse_start = 0x83c2108, mse_descr = 136027216}
-(gdb) p mark_stack[22]
-$54 = {mse_start = 0x83acd20, mse_descr = 80}
-(gdb) p mark_stack[23]
-$55 = {mse_start = 0x83accd0, mse_descr = 80}
-
- The mark stack data comes from: MARK_FROM_MARK_STACK
-
- GC_mark_stack_top = GC_mark_from(GC_mark_stack_top, \
- GC_mark_stack, \
- GC_mark_stack + GC_mark_stack_size);
-
- + need to watch all manipulations of the GC_mark_stack ... (?)
- gc_pmark.h
- + GC_PUSH_ONE_HEAP, GC_PUSH_ONE_STACK (calls)
- -> GC_mark_and_push, GC_mark_and_push_stack
-
- The problem comes from: GC_push_all_stacks ... (pthread_stop_world.c)
-
-#1 0x080fbe2b in GC_push_all_eager (bottom=0xbfffc1b4 "0%G���%@", top=0xbfffce30 "\002") at mark.c:1485
-#2 0x0813a7eb in pthread_push_all_stacks () at pthread_stop_world.c:260
-#3 0x0813a6ad in GC_push_all_stacks () at pthread_stop_world.c:291
-#4 0x080f673b in GC_push_roots (all=1, cold_gc_frame=0xbfffc254 "\200") at mark_rts.c:643
-#5 0x080fd0ea in GC_mark_some (cold_gc_frame=0xbfffc254 "\200") at mark.c:306
-#6 0x080ff51c in GC_stopped_mark (stop_func=0x80febe0 <GC_never_stop_func>) at alloc.c:533
-#7 0x080ff7d8 in GC_try_to_collect_inner (stop_func=0x80febe0 <GC_never_stop_func>) at alloc.c:375
-#8 0x080ff98d in GC_collect_or_expand (needed_blocks=1, ignore_off_page=0) at alloc.c:1035
-#9 0x080ffe23 in GC_allocobj (sz=128, kind=0) at alloc.c:1112
-#10 0x080f9041 in GC_generic_malloc_inner (lb=454, k=0) at malloc.c:136
-#11 0x080f90b4 in GC_generic_malloc (lb=454, k=0) at malloc.c:192
-#12 0x080f9361 in GC_malloc_atomic (lb=454) at malloc.c:270
-#13 0x080c226a in mono_string_new_size (domain=0x81eef00, len=220) at object.c:2081
-#14 0x080d1c18 in ves_icall_System_String_InternalAllocateStr (length=220) at string-icalls.c:634
-
- * pthread_stop_world.c - do we set p->flags & MAIN_THREAD ?
- + bs_lo = p->backing_store_end
- + bs_hi = GC_save_regs_in_stack etc.
-
- * GC_push_all_eager - must get the wrong end of the stick somehow (?)
-
-initially (fine):
-
-Pushing stacks from thread 0x4021abc0
-Stack for thread 0x4021abc0(0x6) = [bfffcd64,bfffd0b0)
-
-later (broken):
-
-Pushing stacks from thread 0x4021abc0
-Stack for thread 0x40b01bb0(0x2) = [40b01594,40b02000)
-Stack for thread 0x4021abc0(0x6) = [bfffc434,bfffd0b0)
-
- hi < lo etc. [!]...
-
- + How does MAIN_THREAD get set (?)
- - surely correct (by Mono)
-
- + Header from pointer: GET_HDR()... GC_find_header(p)
-
- hdr * GC_find_header(h) ptr_t h;
- + does return HDR_INNER(h)
-
-# define HDR_FROM_BI(bi, p) \
- ((bi)->index[((word)(p) >> LOG_HBLKSIZE) & (BOTTOM_SZ - 1)])
-# ifndef HASH_TL
-# define BI(p) (GC_top_index \
- [(word)(p) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE)])
-# define HDR_INNER(p) HDR_FROM_BI(BI(p),p)
-
-
-# define LOG_BOTTOM_SZ 10
-# define BOTTOM_SZ 1<<10
-# define LOG_HBLKSIZE 12
-
- By instrumenting hb_descr setting with:
-
-Set hb_descr to 16 on hdr 0x81eed70
-Set hb_descr to -17 on hdr 0x81efe08
-
-#0 setup_header (hhdr=0x81efe08, sz=4, kind=4, flags=0 '\0') at allchblk.c:243
-#1 0x080fc1e5 in GC_allochblk_nth (sz=4, kind=4, flags=0 '\0', n=6) at allchblk.c:743
-#2 0x080fbd78 in GC_allochblk (sz=4, kind=4, flags=0) at allchblk.c:558
-#3 0x081018a9 in GC_new_hblk (sz=4, kind=4) at new_hblk.c:253
-#4 0x081013d0 in GC_allocobj (sz=4, kind=4) at alloc.c:1103
-#5 0x080f94f6 in GC_generic_malloc_inner (lb=12, k=4) at malloc.c:136
-#6 0x080ff9c6 in GC_gcj_malloc (lb=12, ptr_to_struct_containing_descr=0x81b3b38) at gcj_mlc.c:157
-#7 0x080fa20b in GC_local_gcj_malloc (bytes=12, ptr_to_struct_containing_descr=0x81b3b38) at pthread_support.c:387
-#8 0x080c1117 in mono_object_new_alloc_specific (vtable=0x81b3b38) at object.c:2089
-#9 0x080c127b in mono_object_new_specific (vtable=0x81b3b38) at object.c:2147
-#10 0x080af01f in mono_type_get_object (domain=0x81f0f00, type=0x81c7e34) at reflection.c:5381
-#11 0x080c2094 in mono_class_vtable (domain=0x81f0f00, class=0x81c7d88) at object.c:861
-#12 0x080c20ca in mono_class_vtable (domain=0x81f0f00, class=0x81c7cb8) at object.c:859
-#13 0x080c20ca in mono_class_vtable (domain=0x81f0f00, class=0x81c7be8) at object.c:859
-#14 0x080c3223 in mono_object_new (domain=0x81f0f00, klass=0x81c7be8) at object.c:2108
-#15 0x080af01f in mono_type_get_object (domain=0x81f0f00, type=0x81c550c) at reflection.c:5381
-#16 0x080c2094 in mono_class_vtable (domain=0x81f0f00, class=0x81c5460) at object.c:861
-#17 0x080c20ca in mono_class_vtable (domain=0x81f0f00, class=0x81cc9a0) at object.c:859
-#18 0x080c3223 in mono_object_new (domain=0x81f0f00, klass=0x81cc9a0) at object.c:2108
-#19 0x080a7a1f in mono_runtime_init (domain=0x81f0f00, start_cb=0x81036b0 <mono_thread_start_cb>,
- attach_cb=0x8103760 <mono_thread_attach_cb>) at appdomain.c:96
-#20 0x081053cd in mini_init (filename=0xbfffd37d "ViewSample.exe") at mini.c:10053
-#21 0x0805b99b in mono_main (argc=2, argv=0xbfffce24) at driver.c:837
-#22 0x0805b218 in main (argc=2, argv=0xbfffce24) at main.c:6
-
- So:
-
-(gdb) p GC_obj_kinds[kind].ok_descriptor
-$3 = 4294967279
-(gdb) p GC_obj_kinds[kind]
-$4 = {ok_freelist = 0x81f4000, ok_reclaim_list = 0x8223000, ok_descriptor = 4294967279, ok_relocate_descr = 0, ok_init = 1}
-(gdb) p kind
-$5 = 4
-
- Clearly ok_descriptor must be valid ... - do we not use this
-as a size ?
- allchblk.c (setup_header):
- descr = GC_obj_kinds[kind].ok_descriptor;
- if (...) descr += WORDS_TO_BYTES(sz);
-
- PUSH_OBJ(obj,hhdr) -> sets mse_descr to _descr
-
- Is this:
- GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH);
- responsible !?
-
-/* Predefined kinds: */
-# define PTRFREE 0
-# define NORMAL 1
-# define UNCOLLECTABLE 2
-# ifdef ATOMIC_UNCOLLECTABLE
-# define AUNCOLLECTABLE 3
-# define STUBBORN 4
-# define IS_UNCOLLECTABLE(k) (((k) & ~1) == UNCOLLECTABLE)
-# else
-# define STUBBORN 3
-# define IS_UNCOLLECTABLE(k) ((k) == UNCOLLECTABLE)
-# endif
-
-GC_new_kind_inner screwed up -17
-
-Program received signal SIGSEGV, Segmentation fault.
-[Switching to Thread 1075948480 (LWP 8355)]
-GC_new_kind_inner (fl=0x81f4000, descr=4294967279, adjust=0, clear=1) at misc.c:1128
-1128 *(int *)NULL = 0;
-(gdb) bt
-#0 GC_new_kind_inner (fl=0x81f4000, descr=4294967279, adjust=0, clear=1) at misc.c:1128
-#1 0x080ff8f8 in GC_init_gcj_malloc (mp_index=5, mp=0x0) at gcj_mlc.c:87
-#2 0x080c1886 in mono_class_compute_gc_descriptor (class=0x81cc9a0) at object.c:539
-#3 0x080c1a77 in mono_class_vtable (domain=0x81f0f00, class=0x81cc9a0) at object.c:695
-#4 0x080c3223 in mono_object_new (domain=0x81f0f00, klass=0x81cc9a0) at object.c:2108
-#5 0x080a7a1f in mono_runtime_init (domain=0x81f0f00, start_cb=0x8103720 <mono_thread_start_cb>,
- attach_cb=0x81037d0 <mono_thread_attach_cb>) at appdomain.c:96
-#6 0x0810543d in mini_init (filename=0xbfffd37d "ViewSample.exe") at mini.c:10053
-#7 0x0805b99b in mono_main (argc=2, argv=0xbfffce24) at driver.c:837
-#8 0x0805b218 in main (argc=2, argv=0xbfffce24) at main.c:6
-(gdb)
-
- So - I hypothesize - the kinds are meant to be big/negative - but this is
-compensated for by the size of the allocation.
-
- GC_gcj_kind = GC_new_kind_inner(
- (void **)GC_gcjobjfreelist,
- (((word)(-MARK_DESCR_OFFSET - GC_INDIR_PER_OBJ_BIAS))
- | GC_DS_PER_OBJECT),
- FALSE, TRUE);
-
-
- export GC_IGNORE_GCJ_INFO=1 - and it works ...
-
- My gamble on GC_gcj_kind being broken ...
-
- The problem comes from:
-
-(gdb) bt
-#0 setup_header (hhdr=0x81efe08, sz=4, kind=4, flags=0 '\0') at allchblk.c:245
-#1 0x080fc1ed in GC_allochblk_nth (sz=4, kind=4, flags=0 '\0', n=6) at allchblk.c:744
-#2 0x080fbd80 in GC_allochblk (sz=4, kind=4, flags=0) at allchblk.c:559
-#3 0x081018fd in GC_new_hblk (sz=4, kind=4) at new_hblk.c:253
-#4 0x08101424 in GC_allocobj (sz=4, kind=4) at alloc.c:1103
-#5 0x080f94f6 in GC_generic_malloc_inner (lb=12, k=4) at malloc.c:136
-#6 0x080ffa1a in GC_gcj_malloc (lb=12, ptr_to_struct_containing_descr=0x81b3b38) at gcj_mlc.c:157
-#7 0x080fa20b in GC_local_gcj_malloc (bytes=12, ptr_to_struct_containing_descr=0x81b3b38) at pthread_support.c:387
-#8 0x080c1117 in mono_object_new_alloc_specific (vtable=0x81b3b38) at object.c:2089
-#9 0x080c127b in mono_object_new_specific (vtable=0x81b3b38) at object.c:2147
-#10 0x080af01f in mono_type_get_object (domain=0x81f0f00, type=0x81c7e34) at reflection.c:5381
-#11 0x080c2094 in mono_class_vtable (domain=0x81f0f00, class=0x81c7d88) at object.c:861
-#12 0x080c20ca in mono_class_vtable (domain=0x81f0f00, class=0x81c7cb8) at object.c:859
-#13 0x080c20ca in mono_class_vtable (domain=0x81f0f00, class=0x81c7be8) at object.c:859
-#14 0x080c3223 in mono_object_new (domain=0x81f0f00, klass=0x81c7be8) at object.c:2108
-#15 0x080af01f in mono_type_get_object (domain=0x81f0f00, type=0x81c550c) at reflection.c:5381
-#16 0x080c2094 in mono_class_vtable (domain=0x81f0f00, class=0x81c5460) at object.c:861
-#17 0x080c20ca in mono_class_vtable (domain=0x81f0f00, class=0x81cc9a0) at object.c:859
-#18 0x080c3223 in mono_object_new (domain=0x81f0f00, klass=0x81cc9a0) at object.c:2108
-#19 0x080a7a1f in mono_runtime_init (domain=0x81f0f00, start_cb=0x8103700 <mono_thread_start_cb>,
- attach_cb=0x81037b0 <mono_thread_attach_cb>) at appdomain.c:96
-#20 0x0810541d in mini_init (filename=0xbfffd37d "ViewSample.exe") at mini.c:10053
-#21 0x0805b99b in mono_main (argc=2, argv=0xbfffce24) at driver.c:837
-#22 0x0805b218 in main (argc=2, argv=0xbfffce24) at main.c:6
-(gdb) up
-
- So - then - negative hb_descrs are to be expected (apparently).
-
-process slot: 27
- DS_PER_OBJECT: 0xffffffef
- Object of type 'MonoType' has size 536870913
- DS_BITMAP: 0x20000001
-process slot: 26
- DS_PER_OBJECT: 0xffffffef
- Object of type 'XModel' has size 138021856
- DS_LENGTH: 0x83a0be0
-Assertion failure: mark.c:658
-assertion failure
-
- ...
-
-(gdb) p mark_stack_top
-$1 = (mse *) 0x81e50d0
-(gdb) p *mark_stack_top
-$2 = {mse_start = 0x8240e70, mse_descr = 4294967279}
-(gdb) p *mark_stack_top->mse_start
-$3 = 137267600
-(gdb) p *(MonoVTable **)mark_stack_top->mse_start
-$4 = (struct MonoVTable *) 0x82e8990
-(gdb) p *$4
-$5 = {klass = 0x8398d38, gc_descr = 0x8398ec0, domain = 0x83a0bc0, interface_offsets = 0x83a0ce8, data = 0x0, type = 0x81fffa0,
- max_interface_id = 34, rank = 0 '\0', remote = 0, initialized = 1, vtable = 0x82e89ac}
-(gdb) p *$4->klass
-$6 = {image = 0x8225010, enum_basetype = 0x0, element_class = 0x8398d38, cast_class = 0x8398d38, rank = 0 '\0', inited = 1,
- init_pending = 0, size_inited = 1, valuetype = 0, enumtype = 0, blittable = 1, unicode = 0, wastypebuilder = 0, min_align = 1,
- packing_size = 0, ghcimpl = 0, has_finalize = 0, marshalbyref = 0, contextbound = 0, delegate = 0, gc_descr_inited = 1, has_cctor = 0,
- dummy = 0, has_references = 0, has_static_refs = 0, declsec_flags = 0, exception_type = 0, exception_data = 0x0, parent = 0x0,
- nested_in = 0x0, nested_classes = 0x0, type_token = 33554953, name = 0x40b62892 "XModel",
- name_space = 0x40b62899 "unoidl.com.sun.star.frame", supertypes = 0x83a1988, idepth = 1, interface_count = 1, interface_id = 72,
- max_interface_id = 72, interface_offsets = 0x8397128, interfaces = 0x8352e28, instance_size = 8, class_size = 0, vtable_size = 0,
- flags = 161, field = {first = 911, last = 911, count = 0}, method = {first = 1137, last = 1148, count = 11}, property = {first = 0,
- last = 0, count = 0}, event = {first = 0, last = 0, count = 0}, marshal_info = 0x0, fields = 0x0, properties = 0x0, events = 0x0,
- methods = 0x83985d8, this_arg = {data = {klass = 0x8398d38, type = 0x8398d38, array = 0x8398d38, method = 0x8398d38,
- generic_param = 0x8398d38, generic_class = 0x8398d38}, attrs = 0, type = 18, num_mods = 0, byref = 1, pinned = 0,
- modifiers = 0x8398de4}, byval_arg = {data = {klass = 0x8398d38, type = 0x8398d38, array = 0x8398d38, method = 0x8398d38,
- generic_param = 0x8398d38, generic_class = 0x8398d38}, attrs = 0, type = 18, num_mods = 0, byref = 0, pinned = 0,
- modifiers = 0x8398dec}, generic_class = 0x0, generic_container = 0x0, reflection_info = 0x0, gc_descr = 0x0,
- runtime_info = 0x82470a0, vtable = 0x0}
-(gdb) p mono_class_get_parent($4->klass)
-$7 = (MonoClass *) 0x0
-(gdb)
-
-with:
-
-(gdb) p fprintf(stderr, "0x%x\n", 137989824)
-0x8398ec0
-
- ie. the gc_descr looks dead wrong.
-
-
- ** Frighteningly the gc_descr points to another MonoClass - instead of a GC value [!?]
-
- With more debug printout we see:
-
-Add interface 'XComponentContext'
-Set pvt->gc_descr to 0x30000001: vtable 0x82e8888
-...
- Object of type 'TransparentProxy' vtable 0x82e8888 class 0x81cd9d0 currentp 0x8240e70 has size 805306369 slot 29 on stack
- DS_BITMAP: 0x30000001
-...
- Object of type 'XModel' vtable 0x82e8888 class 0x838a538 currentp 0x8240e70 has size 137930328 slot 26 on stack
- DS_LENGTH: 0x838a658
-
- The instance seems to change type [!?]
-
- Break in:
-
-Hardware watchpoint 3: *$3
-
-Old value = (MonoClass *) 0x81cd9d0
-New value = (MonoClass *) 0x838a538
-0x080c1545 in mono_upgrade_remote_class (domain=0x81f5f00, remote_class=0x82bdbd0, klass=0x838a538) at object.c:1108
-1108 remote_class->interfaces [remote_class->interface_count-1] = klass;
-(gdb) bt
-#0 0x080c1545 in mono_upgrade_remote_class (domain=0x81f5f00, remote_class=0x82bdbd0, klass=0x838a538) at object.c:1108
-#1 0x0809506a in mono_upgrade_remote_class_wrapper (rtype=0x7, tproxy=0x836c120) at marshal.c:6806
-
-From TransparentProxy -> XModel
-
-...
-
-Then - trampling all over the GC data:
-
-Hardware watchpoint 2: *$2
-
-Old value = (void *) 0x30000001
-New value = (void *) 0x838a658
-0x080c1545 in mono_upgrade_remote_class (domain=0x81f5f00, remote_class=0x82bdbd0, klass=0x838a658) at object.c:1108
-1108 remote_class->interfaces [remote_class->interface_count-1] = klass;
-(gdb) bt
-#0 0x080c1545 in mono_upgrade_remote_class (domain=0x81f5f00, remote_class=0x82bdbd0, klass=0x838a658) at object.c:1108
-#1 0x080c4563 in mono_object_isinst_mbyref (obj=0x837ecd8, klass=0x838a658) at object.c:2862
-#2 0x080c655e in ves_icall_type_IsInstanceOfType (type=0x8, obj=0x837ecd8) at icall.c:1189
-