Changeset 509
- Timestamp:
- 01/15/11 00:46:57 (14 years ago)
- Files:
-
- trunk/import/object.di (modified) (1 diff)
- trunk/src/object_.d (modified) (1 diff)
- trunk/src/rt/deh.d (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/import/object.di
r491 r509 318 318 { 319 319 this(string msg, Throwable next = null); 320 320 this(string msg, string file, size_t line, Throwable next = null); 321 321 } 322 322 323 323 324 324 class Error : Throwable 325 325 { 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 330 331 extern (C) 331 332 { 332 333 // from druntime/src/compiler/dmd/aaA.d 333 334 334 335 size_t _aaLen(void* p); 335 336 void* _aaGet(void** pp, TypeInfo keyti, size_t valuesize, ...); 336 337 void* _aaGetRvalue(void* p, TypeInfo keyti, size_t valuesize, ...); 337 338 void* _aaIn(void* p, TypeInfo keyti); trunk/src/object_.d
r491 r509 1333 1333 super(msg, file, line, next); 1334 1334 } 1335 1335 } 1336 1336 1337 1337 1338 1338 class Error : Throwable 1339 1339 { 1340 1340 this(string msg, Throwable next = null) 1341 1341 { 1342 1342 super(msg, next); 1343 bypassedException = null; 1343 1344 } 1344 1345 1345 1346 this(string msg, string file, size_t line, Throwable next = null) 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 1351 1356 1352 1357 /////////////////////////////////////////////////////////////////////////////// 1353 1358 // ModuleInfo 1354 1359 /////////////////////////////////////////////////////////////////////////////// 1355 1360 1356 1361 1357 1362 enum 1358 1363 { trunk/src/rt/deh.d
r503 r509 343 343 * The 'ExceptionRecord' member of the EXCEPTION_RECORD struct is used to 344 344 * store a link to the earlier member on the list. 345 345 * All exceptions which have found their catch handler are linked into this 346 346 * list. The exceptions which collided are marked by setting a bit in the 347 347 * ExceptionFlags. I've called this bit EXCEPTION_COLLATERAL. It has never 348 348 * been used by Microsoft. 349 349 * 350 350 * Every member of the list will either eventually collide with the next earlier 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: 356 356 * (1) The exception records are all on the stack, so it's not possible to 357 357 * modify them very much. In particular, we have very little choice about how 358 358 * unwinding works, so we have to leave all the exception records essentially 359 359 * intact. 360 360 * (2) The length of an exception record is not constant. System exceptions 361 361 * are shorter than D exceptions, for example. 362 362 * (3) System exceptions don't have any space for a pointer to a D object. 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 378 367 EXCEPTION_RECORD * inflightExceptionList = null; 379 368 380 369 /*********************************** 381 370 * Find the first non-collateral exception in the list. If the last 382 371 * entry in the list has the EXCEPTION_COLLATERAL bit set, it means 383 372 * that this fragment will collide with the top exception in the 384 373 * inflightException list. 385 374 */ … … 416 405 _d_local_unwind(handlerTable, frame, -1, &unwindCollisionExceptionHandler); 417 406 } 418 407 else 419 408 { 420 409 // Jump to catch block if matching one is found 421 410 int ndx,prev_ndx,i; 422 411 DHandlerInfo *phi; 423 412 DCatchInfo *pci; 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 432 429 // with an index smaller than the current table_index 433 430 for (ndx = frame.table_index; ndx != -1; ndx = prev_ndx) 434 431 { 435 432 phi = &handlerTable.handler_info[ndx]; 436 433 prev_ndx = phi.prev_index; 437 434 if (phi.cioffset) 438 435 { 439 436 // this is a catch handler (no finally) 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. 483 496 EXCEPTION_RECORD * originalException = skipCollateralExceptions(exceptionRecord); 484 497 if (originalException.ExceptionRecord is null 485 498 && !(exceptionRecord is inflightExceptionList)) 486 499 { 487 500 originalException.ExceptionRecord = inflightExceptionList; 488 501 } 489 502 490 503 inflightExceptionList = exceptionRecord; 491 504 492 505 // Have system call all finally blocks in intervening frames 493 506 _d_global_unwind(frame, exceptionRecord); 494 507 495 508 // Call all the finally blocks skipped in this frame 496 509 _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; 521 547 522 548 int regebp; 523 549 // Initialize catch variable 524 550 regebp = cast(int)&frame.ebp; // EBP for this frame 525 551 *cast(Object *)(regebp + (pcb.bpoffset)) = pti; 526 552 527 553 // Jump to catch block. Does not return. 528 554 { … … 560 586 *exceptionObject = _d_translate_se_to_d_exception(eptrs.ExceptionRecord); 561 587 return retval; 562 588 } 563 589 564 590 /*********************************** 565 591 * Throw a D object. 566 592 */ 567 593 extern(C) 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); 572 600 _d_createTrace(h); 573 601 //_d_setUnhandled(h); 574 602 RaiseException(STATUS_DIGITAL_MARS_D_EXCEPTION, 575 603 EXCEPTION_NONCONTINUABLE, 576 604 1, cast(void *)&h); 577 605 } 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 588 616 switch (exceptionRecord.ExceptionCode) { 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 594 622 case STATUS_INTEGER_DIVIDE_BY_ZERO: 595 623 pti = new Error("Integer Divide by Zero"); 596 624 break; 597 625 598 626 case STATUS_FLOAT_DIVIDE_BY_ZERO: 599 627 pti = new Error("Float Divide by Zero"); 600 628 break; 601 629
