Lines 19-24
Link Here
|
19 |
# include <stdio.h> |
19 |
# include <stdio.h> |
20 |
# include "private/gc_pmark.h" |
20 |
# include "private/gc_pmark.h" |
21 |
|
21 |
|
|
|
22 |
#if defined(MSWIN32) && defined(__GNUC__) |
23 |
# include <excpt.h> |
24 |
#endif |
25 |
|
22 |
/* We put this here to minimize the risk of inlining. */ |
26 |
/* We put this here to minimize the risk of inlining. */ |
23 |
/*VARARGS*/ |
27 |
/*VARARGS*/ |
24 |
#ifdef __WATCOMC__ |
28 |
#ifdef __WATCOMC__ |
Lines 261-280
Link Here
|
261 |
/* remains valid until all marking is complete. */ |
265 |
/* remains valid until all marking is complete. */ |
262 |
/* A zero value indicates that it's OK to miss some */ |
266 |
/* A zero value indicates that it's OK to miss some */ |
263 |
/* register values. */ |
267 |
/* register values. */ |
264 |
GC_bool GC_mark_some(cold_gc_frame) |
268 |
/* We hold the allocation lock. In the case of */ |
265 |
ptr_t cold_gc_frame; |
269 |
/* 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 |
266 |
{ |
281 |
{ |
267 |
#if defined(MSWIN32) && !defined(__GNUC__) |
|
|
268 |
/* Windows 98 appears to asynchronously create and remove writable */ |
269 |
/* memory mappings, for reasons we haven't yet understood. Since */ |
270 |
/* we look for writable regions to determine the root set, we may */ |
271 |
/* try to mark from an address range that disappeared since we */ |
272 |
/* started the collection. Thus we have to recover from faults here. */ |
273 |
/* This code does not appear to be necessary for Windows 95/NT/2000. */ |
274 |
/* Note that this code should never generate an incremental GC write */ |
275 |
/* fault. */ |
276 |
__try { |
277 |
#endif /* defined(MSWIN32) && !defined(__GNUC__) */ |
278 |
switch(GC_mark_state) { |
282 |
switch(GC_mark_state) { |
279 |
case MS_NONE: |
283 |
case MS_NONE: |
280 |
return(FALSE); |
284 |
return(FALSE); |
Lines 395-417
Link Here
|
395 |
ABORT("GC_mark_some: bad state"); |
399 |
ABORT("GC_mark_some: bad state"); |
396 |
return(FALSE); |
400 |
return(FALSE); |
397 |
} |
401 |
} |
398 |
#if defined(MSWIN32) && !defined(__GNUC__) |
402 |
} |
399 |
} __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? |
403 |
|
400 |
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { |
404 |
|
401 |
# ifdef CONDPRINT |
405 |
#ifdef MSWIN32 |
402 |
if (GC_print_stats) { |
406 |
|
403 |
GC_printf0("Caught ACCESS_VIOLATION in marker. " |
407 |
# ifdef __GNUC__ |
404 |
"Memory mapping disappeared.\n"); |
408 |
|
|
|
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 |
|
405 |
} |
513 |
} |
406 |
# endif /* CONDPRINT */ |
514 |
|
407 |
/* We have bad roots on the stack. Discard mark stack. */ |
515 |
# else /* __GNUC__ */ |
408 |
/* Rescan from marked objects. Redetermine roots. */ |
516 |
|
409 |
GC_invalidate_mark_state(); |
517 |
rm_handler: |
410 |
scan_ptr = 0; |
518 |
/* Uninstall the exception handler */ |
411 |
return FALSE; |
519 |
asm volatile ("mov %0, %%fs:0" : : "r" (er.ex_reg.prev)); |
|
|
520 |
|
521 |
# endif /* __GNUC__ */ |
522 |
|
523 |
return ret_val; |
412 |
} |
524 |
} |
413 |
#endif /* defined(MSWIN32) && !defined(__GNUC__) */ |
525 |
#endif /* MSWIN32 */ |
414 |
} |
|
|
415 |
|
526 |
|
416 |
|
527 |
|
417 |
GC_bool GC_mark_stack_empty() |
528 |
GC_bool GC_mark_stack_empty() |