Changeset 509
- Timestamp:
- 01/14/11 19:46:57 (1 year ago)
- Files:
-
- trunk/import/object.di (modified) (1 diff)
- trunk/src/object_.d (modified) (2 diffs)
- trunk/src/rt/deh.d (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/import/object.di
r491 r509 326 326 this(string msg, Throwable next = null); 327 327 this(string msg, string file, size_t line, Throwable next = null); 328 Throwable bypassedException; 328 329 } 329 330 trunk/src/object_.d
r491 r509 1341 1341 { 1342 1342 super(msg, next); 1343 bypassedException = null; 1343 1344 } 1344 1345 … … 1346 1347 { 1347 1348 super(msg, file, line, next); 1348 } 1349 bypassedException = null; 1350 } 1351 /// The first Exception which was bypassed when this Error was thrown, 1352 /// or null if no Exceptions were pending. 1353 Throwable bypassedException; 1349 1354 } 1350 1355 trunk/src/rt/deh.d
r503 r509 351 351 * exception, having its EXCEPTION_COLLATERAL bit set, or else will be caught. 352 352 * If it is caught, a D exception object is created, containing all of the 353 * collateral exceptions ,353 * collateral exceptions. 354 354 * 355 355 * There are many subtleties in this design: … … 363 363 * So we cannot store the collision information in the exception record. 364 364 * (4) it's important that this list is thread-local. 365 *366 * Every member of this list will suffer one of two fates:367 * (1) it will be caught successfully.368 * In this case it is popped from the list.369 * The previous head of the list, and the previous Throwable chain, are restored.370 * (2) it will collide with the previous exception.371 * In this case, it gets added to the active Throwable chain, and then discarded.372 * (in which case its Throwable chain will be added to the Throwable chain of373 * the previous exception, and then this exception will be popped from the list).374 *375 * Note:376 365 */ 377 366 … … 424 413 DCatchBlock *pcb; 425 414 uint ncatches; // number of catches in the current handler 426 Object pti; 427 ClassInfo ci; 428 429 ci = null; // only compute it if we need it 415 416 /* The Master or Boss exception controls which catch() clause will 417 * catch the exception. If all collateral exceptions are derived from 418 * Exception, the boss is the first exception thrown. Otherwise, 419 * the first Error is the boss. 420 * But, if an Error (or non-Exception Throwable) is thrown as a collateral 421 * exception, it will take priority over an Exception. 422 */ 423 EXCEPTION_RECORD * master = null; // The Master exception. 424 ClassInfo masterClassInfo; // Class info of the Master exception. 425 426 masterClassInfo = null; // only compute it if we need it 430 427 431 428 // walk through handler table, checking each handler … … 440 437 pci = cast(DCatchInfo *)(cast(ubyte *)handlerTable + phi.cioffset); 441 438 ncatches = pci.ncatches; 439 442 440 for (i = 0; i < ncatches; i++) 443 441 { 444 442 pcb = &pci.catch_block[i]; 445 // If there are collided unwinds, they must ALL match the translation code446 443 int match = 0; 447 444 EXCEPTION_RECORD * er = exceptionRecord; 448 do 445 // We need to check all the collateral exceptions. 446 for(;;) 449 447 { 450 if ( !ci)448 if (er.ExceptionCode == STATUS_DIGITAL_MARS_D_EXCEPTION) 451 449 { 452 // This code must match the translation code 453 if (er.ExceptionCode == STATUS_DIGITAL_MARS_D_EXCEPTION) 454 { 455 // printf("ei[0] = %p\n", exceptionRecord.ExceptionInformation[0]); 456 ci = (**(cast(ClassInfo **)(er.ExceptionInformation[0]))); 457 } 458 else 459 ci = Throwable.typeinfo; 450 // printf("ei[0] = %p\n", er.ExceptionInformation[0]); 451 ClassInfo ci = (**(cast(ClassInfo **)(er.ExceptionInformation[0]))); 452 // If we've reached the oldest exception without 453 // finding an Error, this one must be the master. 454 if (!master && !(er.ExceptionFlags & EXCEPTION_COLLATERAL)) 455 { 456 master = er; 457 masterClassInfo = ci; 458 break; 459 } 460 if (_d_isbaseof(ci, Error.classinfo)) 461 { // It's derived from Error. This _may_ be the master. 462 master = er; 463 masterClassInfo = ci; 464 } // Else it's a collateral Exception 460 465 } 461 match = _d_isbaseof(ci, pcb.type); 462 // We need to check all the collateral exceptions 463 if (er.ExceptionFlags & EXCEPTION_COLLATERAL) { 464 // Walk to the next collateral exception. 465 if (er.ExceptionRecord) 466 er = er.ExceptionRecord; 467 else // It is collateral for an existing exception chain 468 // for which we've already found the catch{}. It is 469 // possible that the new collateral makes the old catch 470 // invalid. 471 er = inflightExceptionList; 472 ci = null; 466 else 467 { // Non-D exception. It will become an Error. 468 masterClassInfo = Error.typeinfo; 469 master = er; 473 470 } 474 else break; // if no collateral exceptions, we're done. 475 } while(match); 476 477 if (match) 471 // End the loop if this was the original exception 472 if (! (er.ExceptionFlags & EXCEPTION_COLLATERAL)) 473 break; 474 475 // Now get the next collateral exception. 476 if (er.ExceptionRecord) 477 er = er.ExceptionRecord; 478 else // It is collateral for an existing exception chain 479 // for which we've already found the catch{}. It is 480 // possible that the new collateral makes the old catch 481 // invalid. 482 er = inflightExceptionList; 483 } 484 if (_d_isbaseof(masterClassInfo, pcb.type)) 478 485 { 479 // Matched the catch type, so we've found the catch handler 480 // for this exception. 486 // Matched the catch type, so we've found the catch 487 // handler for this exception. 488 // BEWARE: We don't yet know if the catch handler will 489 // actually be executed. If there's an unwind collision, 490 // this call may be abandoned: the calls to 491 // _global_unwind and _local_unwind may never return, 492 // and the contents of the local variables will be lost. 493 481 494 // We need to add this exception to the list of in-flight 482 495 // exceptions, in case something collides with it. … … 487 500 originalException.ExceptionRecord = inflightExceptionList; 488 501 } 489 490 502 inflightExceptionList = exceptionRecord; 491 503 … … 495 507 // Call all the finally blocks skipped in this frame 496 508 _d_local_unwind(handlerTable, frame, ndx, &searchCollisionExceptionHandler); 497 509 510 498 511 frame.table_index = prev_ndx; // we are out of this handler 499 512 500 513 // Now create the D exception from the SEH exception record chain. 501 // Note that since non-Throwables are throwable(!), the chain might be incomplete.502 514 EXCEPTION_RECORD * z = exceptionRecord; 503 515 Throwable prev = null; 504 while (z && (z.ExceptionFlags & EXCEPTION_COLLATERAL)) 516 Error masterError = null; 517 Throwable pti; 518 519 for(;;) 505 520 { 506 Throwable w = cast(Throwable)_d_translate_se_to_d_exception(z); 507 if (w) // if throwable 508 { 509 w.next = prev; 510 prev = w; 521 Throwable w = _d_translate_se_to_d_exception(z); 522 if (z == master && (z.ExceptionFlags & EXCEPTION_COLLATERAL)) 523 { // if it is a short-circuit master, save it 524 masterError = cast(Error)w; 511 525 } 526 Throwable a = w; 527 while (a.next) 528 a = a.next; 529 a.next = prev; 530 prev = w; 531 if (!(z.ExceptionFlags & EXCEPTION_COLLATERAL)) 532 break; 512 533 z = z.ExceptionRecord; 513 534 } 514 pti = _d_translate_se_to_d_exception(z); 515 if (cast(Throwable)pti) 516 (cast(Throwable)pti).next = prev; 517 // else it wasn't throwable. (This happens in the test suite eh2.d, test1) 518 535 // Reached the end. Now add the Master, if any. 536 if (masterError) 537 { 538 masterError.bypassedException = prev; 539 pti = masterError; 540 } 541 else 542 { 543 pti = prev; 544 } 519 545 // Pop the exception from the list of in-flight exceptions 520 546 inflightExceptionList = z.ExceptionRecord; … … 568 594 void _d_throwc(Object h) 569 595 { 596 // @@@ TODO @@@ Signature should change: h will always be a Throwable. 597 570 598 //printf("_d_throw(h = %p, &h = %p)\n", h, &h); 571 599 //printf("\tvptr = %p\n", *(void **)h); … … 578 606 579 607 /*********************************** 580 * Converts a Windows Structured Exception code to a D ExceptionObject.581 */ 582 583 Object_d_translate_se_to_d_exception(EXCEPTION_RECORD *exceptionRecord)584 { 585 Objectpti;608 * Converts a Windows Structured Exception code to a D Throwable Object. 609 */ 610 611 Throwable _d_translate_se_to_d_exception(EXCEPTION_RECORD *exceptionRecord) 612 { 613 Throwable pti; 586 614 // BUG: what if _d_newclass() throws an out of memory exception? 587 615 … … 589 617 case STATUS_DIGITAL_MARS_D_EXCEPTION: 590 618 // Generated D exception 591 pti = cast( Object)cast(void *)(exceptionRecord.ExceptionInformation[0]);619 pti = cast(Throwable)cast(void *)(exceptionRecord.ExceptionInformation[0]); 592 620 break; 593 621
