19 |
# include <stdio.h> |
# include <stdio.h> |
20 |
# include "private/gc_pmark.h" |
# include "private/gc_pmark.h" |
21 |
|
|
22 |
|
#if defined(MSWIN32) && defined(__GNUC__) |
23 |
|
# include <excpt.h> |
24 |
|
#endif |
25 |
|
|
26 |
/* We put this here to minimize the risk of inlining. */ |
/* We put this here to minimize the risk of inlining. */ |
27 |
/*VARARGS*/ |
/*VARARGS*/ |
28 |
#ifdef __WATCOMC__ |
#ifdef __WATCOMC__ |
265 |
/* remains valid until all marking is complete. */ |
/* remains valid until all marking is complete. */ |
266 |
/* A zero value indicates that it's OK to miss some */ |
/* A zero value indicates that it's OK to miss some */ |
267 |
/* register values. */ |
/* register values. */ |
268 |
GC_bool GC_mark_some(cold_gc_frame) |
/* We hold the allocation lock. In the case of */ |
269 |
ptr_t cold_gc_frame; |
/* incremental collection, the world may not be stopped.*/ |
270 |
|
#ifdef MSWIN32 |
271 |
|
/* For win32, this is called after we establish a structured */ |
272 |
|
/* exception handler, in case Windows unmaps one of our root */ |
273 |
|
/* segments. See below. In either case, we acquire the */ |
274 |
|
/* allocator lock long before we get here. */ |
275 |
|
GC_bool GC_mark_some_inner(cold_gc_frame) |
276 |
|
ptr_t cold_gc_frame; |
277 |
|
#else |
278 |
|
GC_bool GC_mark_some(cold_gc_frame) |
279 |
|
ptr_t cold_gc_frame; |
280 |
|
#endif |
281 |
{ |
{ |
|
#if defined(MSWIN32) && !defined(__GNUC__) |
|
|
/* Windows 98 appears to asynchronously create and remove writable */ |
|
|
/* memory mappings, for reasons we haven't yet understood. Since */ |
|
|
/* we look for writable regions to determine the root set, we may */ |
|
|
/* try to mark from an address range that disappeared since we */ |
|
|
/* started the collection. Thus we have to recover from faults here. */ |
|
|
/* This code does not appear to be necessary for Windows 95/NT/2000. */ |
|
|
/* Note that this code should never generate an incremental GC write */ |
|
|
/* fault. */ |
|
|
__try { |
|
|
#endif /* defined(MSWIN32) && !defined(__GNUC__) */ |
|
282 |
switch(GC_mark_state) { |
switch(GC_mark_state) { |
283 |
case MS_NONE: |
case MS_NONE: |
284 |
return(FALSE); |
return(FALSE); |
399 |
ABORT("GC_mark_some: bad state"); |
ABORT("GC_mark_some: bad state"); |
400 |
return(FALSE); |
return(FALSE); |
401 |
} |
} |
402 |
#if defined(MSWIN32) && !defined(__GNUC__) |
} |
403 |
} __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? |
|
404 |
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { |
|
405 |
# ifdef CONDPRINT |
#ifdef MSWIN32 |
406 |
if (GC_print_stats) { |
|
407 |
GC_printf0("Caught ACCESS_VIOLATION in marker. " |
# ifdef __GNUC__ |
408 |
"Memory mapping disappeared.\n"); |
|
409 |
|
typedef struct { |
410 |
|
EXCEPTION_REGISTRATION ex_reg; |
411 |
|
void *alt_path; |
412 |
|
} ext_ex_regn; |
413 |
|
|
414 |
|
|
415 |
|
static EXCEPTION_DISPOSITION mark_ex_handler( |
416 |
|
struct _EXCEPTION_RECORD *ex_rec, |
417 |
|
void *est_frame, |
418 |
|
struct _CONTEXT *context, |
419 |
|
void *disp_ctxt) |
420 |
|
{ |
421 |
|
if (ex_rec->ExceptionCode == STATUS_ACCESS_VIOLATION) { |
422 |
|
ext_ex_regn *xer = (ext_ex_regn *)est_frame; |
423 |
|
|
424 |
|
/* Unwind from the inner function assuming the standard */ |
425 |
|
/* function prologue. */ |
426 |
|
/* Assumes code has not been compiled with */ |
427 |
|
/* -fomit-frame-pointer. */ |
428 |
|
context->Esp = context->Ebp; |
429 |
|
context->Ebp = *((DWORD *)context->Esp); |
430 |
|
context->Esp = context->Esp - 8; |
431 |
|
|
432 |
|
/* Resume execution at the "real" handler within the */ |
433 |
|
/* wrapper function. */ |
434 |
|
context->Eip = (DWORD )(xer->alt_path); |
435 |
|
|
436 |
|
return ExceptionContinueExecution; |
437 |
|
|
438 |
|
} else { |
439 |
|
return ExceptionContinueSearch; |
440 |
|
} |
441 |
|
} |
442 |
|
# endif /* __GNUC__ */ |
443 |
|
|
444 |
|
|
445 |
|
GC_bool GC_mark_some(cold_gc_frame) |
446 |
|
ptr_t cold_gc_frame; |
447 |
|
{ |
448 |
|
GC_bool ret_val; |
449 |
|
|
450 |
|
# ifndef __GNUC__ |
451 |
|
/* Windows 98 appears to asynchronously create and remove */ |
452 |
|
/* writable memory mappings, for reasons we haven't yet */ |
453 |
|
/* understood. Since we look for writable regions to */ |
454 |
|
/* determine the root set, we may try to mark from an */ |
455 |
|
/* address range that disappeared since we started the */ |
456 |
|
/* collection. Thus we have to recover from faults here. */ |
457 |
|
/* This code does not appear to be necessary for Windows */ |
458 |
|
/* 95/NT/2000. Note that this code should never generate */ |
459 |
|
/* an incremental GC write fault. */ |
460 |
|
|
461 |
|
__try { |
462 |
|
|
463 |
|
# else /* __GNUC__ */ |
464 |
|
|
465 |
|
/* Manually install an exception handler since GCC does */ |
466 |
|
/* not yet support Structured Exception Handling (SEH) on */ |
467 |
|
/* Win32. */ |
468 |
|
|
469 |
|
ext_ex_regn er; |
470 |
|
|
471 |
|
er.alt_path = &&handle_ex; |
472 |
|
er.ex_reg.handler = mark_ex_handler; |
473 |
|
asm volatile ("movl %%fs:0, %0" : "=r" (er.ex_reg.prev)); |
474 |
|
asm volatile ("movl %0, %%fs:0" : : "r" (&er)); |
475 |
|
|
476 |
|
# endif /* __GNUC__ */ |
477 |
|
|
478 |
|
ret_val = GC_mark_some_inner(cold_gc_frame); |
479 |
|
|
480 |
|
# ifndef __GNUC__ |
481 |
|
|
482 |
|
} __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? |
483 |
|
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { |
484 |
|
|
485 |
|
# else /* __GNUC__ */ |
486 |
|
|
487 |
|
/* Prevent GCC from considering the following code unreachable */ |
488 |
|
/* and thus eliminating it. */ |
489 |
|
if (er.alt_path != 0) |
490 |
|
goto rm_handler; |
491 |
|
|
492 |
|
handle_ex: |
493 |
|
/* Execution resumes from here on an access violation. */ |
494 |
|
|
495 |
|
# endif /* __GNUC__ */ |
496 |
|
|
497 |
|
# ifdef CONDPRINT |
498 |
|
if (GC_print_stats) { |
499 |
|
GC_printf0("Caught ACCESS_VIOLATION in marker. " |
500 |
|
"Memory mapping disappeared.\n"); |
501 |
|
} |
502 |
|
# endif /* CONDPRINT */ |
503 |
|
|
504 |
|
/* We have bad roots on the stack. Discard mark stack. */ |
505 |
|
/* Rescan from marked objects. Redetermine roots. */ |
506 |
|
GC_invalidate_mark_state(); |
507 |
|
scan_ptr = 0; |
508 |
|
|
509 |
|
ret_val = FALSE; |
510 |
|
|
511 |
|
# ifndef __GNUC__ |
512 |
|
|
513 |
} |
} |
514 |
# endif /* CONDPRINT */ |
|
515 |
/* We have bad roots on the stack. Discard mark stack. */ |
# else /* __GNUC__ */ |
516 |
/* Rescan from marked objects. Redetermine roots. */ |
|
517 |
GC_invalidate_mark_state(); |
rm_handler: |
518 |
scan_ptr = 0; |
/* Uninstall the exception handler */ |
519 |
return FALSE; |
asm volatile ("mov %0, %%fs:0" : : "r" (er.ex_reg.prev)); |
520 |
|
|
521 |
|
# endif /* __GNUC__ */ |
522 |
|
|
523 |
|
return ret_val; |
524 |
} |
} |
525 |
#endif /* defined(MSWIN32) && !defined(__GNUC__) */ |
#endif /* MSWIN32 */ |
|
} |
|
526 |
|
|
527 |
|
|
528 |
GC_bool GC_mark_stack_empty() |
GC_bool GC_mark_stack_empty() |