home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-04-21 | 13.0 KB | 393 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWExcRun.cpp
- // Release Version: $ 1.0d1 $
- //
- // Creation Date: 3/28/94
- //
- // Copyright: © 1994 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include <string.h>
-
- #ifndef FWEXCRUN_H
- #include "FWExcRun.h"
- #endif
-
- #ifndef FWDELSTA_H
- #include "FWDelSta.h"
- #endif
-
- #ifndef FWTRYBLO_H
- #include "FWTryBlo.h"
- #endif
-
- #ifndef FWPRIDEB_H
- #include "FWPriDeb.h"
- #endif
-
- #ifndef FWPRIMEM_H
- #include "FWPriMem.h"
- #endif
-
- #ifndef FWNEWHEL_H
- #include "FWNewHel.h"
- #endif
-
- #ifndef FWONSTAC_H
- #include "FWOnStac.h"
- #endif
-
- #ifdef FW_BUILD_MAC
- #pragma segment BEL
- #endif
-
- //========================================================================================
- // Functions for "unexpected" and "terminate"
- //
- // See ARM, Section 15.6
- //========================================================================================
-
- extern "C" void abort ();
-
- static void DefaultTerminate();
- static void DefaultUnexpected();
-
- static void DefaultTerminate()
- {
- abort();
- }
-
- static void DefaultUnexpected()
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- PFV pfCurrentTerminate = globals.gCurrentTerminate;
- (*pfCurrentTerminate)();
- }
-
- void terminate()
- {
- FW_PRIV_DEBUGGER_BREAK();
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- PFV pfCurrentTerminate = globals.gCurrentTerminate;
- (*pfCurrentTerminate)();
- }
-
- void unexpected()
- {
- FW_PRIV_DEBUGGER_BREAK();
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- PFV pfCurrentUnexpected = globals.gCurrentUnexpected;
- (*pfCurrentUnexpected)();
- }
-
- PFV set_terminate(PFV terminate)
- {
- return _FW_CExceptionRuntime::SetTerminate(terminate);
- }
-
- PFV set_unexpected(PFV unexpected)
- {
- return _FW_CExceptionRuntime::SetUnexpected(unexpected);
- }
-
- #ifdef FW_BUILD_WIN32S
- _FW_PrivIsOnStack(void * p)
- {
- char localVar;
- return &localVar <= p && p <= &localVar + 16000;
- }
- #endif
-
- //========================================================================================
- // CLASS _FW_CExceptionRuntime
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::Initialize
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::Initialize(FW_SPrivExceptionGlobals& globals)
- {
- #ifdef FW_DEBUG
- // verify our _FW_PrivIsOnStack routine
- int local;
- static int gGlobal;
- void* code = (void*) _FW_CExceptionRuntime::Initialize;
- FW_PRIV_ASSERT(_FW_PrivIsOnStack(&local));
- FW_PRIV_ASSERT(!_FW_PrivIsOnStack(&gGlobal));
- FW_PRIV_ASSERT(!_FW_PrivIsOnStack(code));
- #endif
-
- globals.gExceptionBufferSize = kDefaultExceptionBufferSize;
- globals.gExceptionBuffer = ::FW_PrimitiveAllocateBlock(kDefaultExceptionBufferSize);
- globals.gCurrentTerminate = DefaultTerminate;
- globals.gCurrentUnexpected = DefaultUnexpected;
-
- #ifdef FW_DEBUG
- SetBreakOnThrow(NULL);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::Terminate
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::Terminate()
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- ::FW_PrimitiveFreeBlock(globals.gExceptionBuffer);
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::SetTerminate
- //----------------------------------------------------------------------------------------
- PFV _FW_CExceptionRuntime::SetTerminate(PFV newTerminate)
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- PFV oldTerminate = globals.gCurrentTerminate;
- globals.gCurrentTerminate = newTerminate;
- return oldTerminate;
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::SetUnexpected
- //----------------------------------------------------------------------------------------
- PFV _FW_CExceptionRuntime::SetUnexpected(PFV newUnexpected)
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- PFV oldUnexpected = globals.gCurrentUnexpected;
- globals.gCurrentUnexpected = newUnexpected;
- return oldUnexpected;
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::CaughtException
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::CaughtException(FW_SPrivExceptionGlobals& globals, _FW_CException * caughtException)
- {
- globals.gThrownException->Delete();
- globals.gCaughtException = caughtException;
- globals.gThrownException = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::CaughtEverythingException
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::CaughtEverythingException(FW_SPrivExceptionGlobals& globals)
- {
- globals.gCaughtException = globals.gThrownException;
- globals.gThrownException = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::CaughtNoInstanceException
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::CaughtNoInstanceException(FW_SPrivExceptionGlobals& globals)
- {
- globals.gCaughtException = globals.gThrownException;
- globals.gThrownException = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::CaughtReferenceException
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::CaughtReferenceException(FW_SPrivExceptionGlobals& globals)
- {
- globals.gCaughtException = globals.gThrownException;
- globals.gThrownException = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::PrimitiveThrow
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::PrimitiveThrow(const _FW_CException & thrownException)
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
-
- // Should never have an exception on the way in
- FW_PRIV_ASSERT(globals.gThrownException == NULL);
-
- _FW_CTryBlockContext *context = globals.gCurrentContext;
- FW_PRIV_ASSERT(context!=NULL);
- if (context->fPriorContext == NULL)
- {
- terminate();
- abort(); // Terminate should never return
- }
-
- if (_FW_CDeleteStack::IsClassExpectedInContext(context, thrownException.PrivVirtualGetClassInfo()))
- {
- // If someone had caught an exception delete that exception
- // because we are going to bypass the destructor for it.
- if (globals.gCaughtException != NULL)
- {
- globals.gCaughtException->Delete();
- globals.gCaughtException = 0;
- }
-
- // Copy the original into our exception buffer
- thrownException.Copy(globals.gExceptionBuffer, globals.gExceptionBufferSize);
-
- // We have a thrown exception so point gThrownException at it.
- globals.gThrownException = (_FW_CException*)globals.gExceptionBuffer;
-
- // We have copied the original so delete it.
- ((_FW_CException &)thrownException).Delete();
-
- DeleteObjectsInContextAndJump(globals, context);
- }
- else
- {
- unexpected();
- }
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::PrimitiveThrowSame
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::PrimitiveThrowSame()
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
-
- FW_PRIV_ASSERT(globals.gCaughtException != NULL);
- if (globals.gCaughtException == NULL)
- {
- abort(); // Can't throwsame if nothing is currently caught
- }
-
- _FW_CTryBlockContext * context = globals.gCurrentContext;
- FW_PRIV_ASSERT(context != NULL);
- if (context->fPriorContext == NULL)
- {
- terminate();
- abort(); // Terminate should never return but if it does we will abort
- }
-
- _FW_CException *caughtException = globals.gCaughtException;
-
- if (_FW_CDeleteStack::IsClassExpectedInContext(context, caughtException->PrivVirtualGetClassInfo()))
- {
- if (caughtException != (_FW_CException *)globals.gExceptionBuffer)
- {
- // The exception is in the stack frame so copy it to our exception buffer,
- // delete the original and then pass the copy along.
- caughtException->Copy(globals.gExceptionBuffer, globals.gExceptionBufferSize);
- caughtException->Delete();
- globals.gThrownException = (_FW_CException*)globals.gExceptionBuffer;
- }
- else
- {
- // The exception is already in our buffer
- globals.gThrownException = (_FW_CException*)globals.gCaughtException;
- }
-
- globals.gCaughtException = 0;
-
- DeleteObjectsInContextAndJump(globals, context);
- }
- else
- {
- unexpected();
- }
- }
-
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::Throw
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::Throw(const _FW_CException & thrownException)
- {
- PrimitiveThrow(thrownException);
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::ThrowSame
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::ThrowSame()
- {
- PrimitiveThrowSame();
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::ThrowConstructor
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::ThrowConstructor(_FW_CException & thrownException)
- {
- PrimitiveThrow(thrownException);
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::ThrowSameConstructor
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::ThrowSameConstructor()
- {
- PrimitiveThrowSame();
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::KeepThrowing
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::KeepThrowing(FW_SPrivExceptionGlobals& globals)
- {
- _FW_CTryBlockContext *context = globals.gCurrentContext;
- FW_PRIV_ASSERT(context!=NULL);
- if (_FW_CDeleteStack::IsClassExpectedInContext(context, globals.gThrownException->PrivVirtualGetClassInfo()))
- {
- DeleteObjectsInContextAndJump(globals, context);
- }
- else
- {
- unexpected();
- }
- }
-
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::ResetExceptionBufferSize
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::ResetExceptionBufferSize(size_t newSize)
- {
- FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
- void *p = ::FW_PrimitiveResizeBlock(globals.gExceptionBuffer, newSize);
- FW_PRIV_ASSERT(p != NULL);
- globals.gExceptionBuffer = p;
- globals.gExceptionBufferSize = newSize;
- }
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::DeleteObjectsInContextAndJump
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::DeleteObjectsInContextAndJump(FW_SPrivExceptionGlobals& globals,
- _FW_CTryBlockContext * context)
- {
- #ifdef FW_DEBUG
- _FW_CException *thrownException = globals.gThrownException;
- FW_ClassReference breakExceptionKind = globals.gBreakExceptionKind;
- if (breakExceptionKind!=NULL && thrownException->__IsKindOf(breakExceptionKind))
- FW_PRIV_DEBUGGER_STRING("Throwing an exception");
- #endif
-
- _FW_CDeleteStack::PopOffAndDeleteObjectsInContext(globals, context);
-
- jmp_buf *jumpBuffer = context->fJumpBuffer;
- // context->_FW_CTryBlockContext::~_FW_CTryBlockContext();
- context->~_FW_CTryBlockContext();
- ::longjmp(*jumpBuffer, 1);
- }
-
-
- //----------------------------------------------------------------------------------------
- // _FW_CExceptionRuntime::EndConstructor
- //----------------------------------------------------------------------------------------
- void _FW_CExceptionRuntime::EndConstructor(_FW_CAutoDestructObject *object, size_t size)
- {
- if (_FW_PrivIsOnStack(object))
- _FW_CDeleteStack::Push(object);
- else
- {
- _FW_CPrivNewHelper *helper = _FW_CPrivNewHelper::TopNewHelper();
- if (helper!=NULL && helper->IsWatching(object))
- helper->UpdateForEndConstructor(object, size);
- }
- }
-