/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ // // simon // #include "JavaVM.h" #include "ExceptionTable.h" #include "CatchAssert.h" #include "LogModule.h" UT_DEFINE_LOG_MODULE(ExceptionTable); //----------------------------------------------------------------------------------------------------------- // ExceptionTableBuilder // METHOD addEntry // In/Out: index -- created handler must be at or after stated index // In newEntry -- entry to add to exception table // Assumptions: entries must be added in ascending scheduled node order void ExceptionTableBuilder:: addEntry(Uint32& index, ExceptionTableEntry& newEntry) { Uint32 tableSize = eTable.size(); // iterate through exception table trying to find an existing entry we can coalesce with for(; index < tableSize; index++) { ExceptionTableEntry& ete = eTable[index]; // can't coalesce if handler, type or policy differ if( (ete.pHandler != newEntry.pHandler) || (ete.pExceptionType != newEntry.pExceptionType)) continue; // we require that the above noted assumption has been met assert(ete.pEnd <= newEntry.pStart); // extend range of existing exception table entry (coalesce) if possible if(ete.pEnd == newEntry.pStart) { ete.pEnd = newEntry.pEnd; // coalesce ranges #ifdef DEBUG_LOG UT_LOG(ExceptionTable, PR_LOG_ALWAYS, ("merge")); newEntry.print(UT_LOG_MODULE(ExceptionTable)); #endif return; // index will point to index of table entry that was extended } } // coalesce wasn't possible, so insert eTable.append(newEntry); #ifdef DEBUG_LOG UT_LOG(ExceptionTable, PR_LOG_ALWAYS, ("add ")); newEntry.print(UT_LOG_MODULE(ExceptionTable)); #endif // index will be correctly set from end of 'for' loop } //----------------------------------------------------------------------------------------------------------- #ifdef DEBUG // check important assumption that array is sorted and valid // if it is not then nested trys will probably fail void ExceptionTableBuilder:: checkInOrder() { if(eTable.begin() == eTable.end()) return; ExceptionTableEntry *curr, *next, *last; curr= eTable.begin(); last = eTable.end() - 1; while(curr < last) { next = curr + 1; assert(curr->pStart <= curr->pEnd); // sanity check assert(curr->pStart <= next->pStart); // ensure that items are sorted by pStart field curr = next; } } #endif // DEBUG //----------------------------------------------------------------------------------------------------------- // Constructor // builds an exception table in the specified pool ExceptionTable:: ExceptionTable(ExceptionTableBuilder eBuilder, Pool& inPool) { numberofEntries = eBuilder.getNumberofEntries(); start = eBuilder.start; if(numberofEntries == 0) { mEntries = NULL; } else { Uint32 i; mEntries = new(inPool) ExceptionTableEntry[numberofEntries]; for(i = 0; i < numberofEntries; i++) mEntries[i] = eBuilder.getEntry(i); Uint32 sz = eBuilder.getNumberofAPoints(); asynchPoints = new(inPool) Uint32[sz]; for(i = 0; i < sz; i++) asynchPoints[i] = eBuilder.getAEntry(i); } } // In: thrown object // In: PC/EIP of // Out: pointer to an ExceptionTableEntry that matches the thrown object (or NULL if no match) ExceptionTableEntry* ExceptionTable:: findCatchHandler(const Uint8* pc, const JavaObject& inObject) { const Class& clazz = inObject.getClass(); // scan through the handler list in _reverse_ looking for a match // reverse scanning is needed to properly respect nested try blocks if(numberofEntries > 0) for(Int32 i = numberofEntries - 1; i >= 0; i--) { ExceptionTableEntry* tableEntry = mEntries + i; if( (pc >= start + tableEntry->pStart) && (pc < start + tableEntry->pEnd) && clazz.implements( *(tableEntry->pExceptionType) ) ) return tableEntry; } return NULL; } //----------------------------------------------------------------------------------------------------------- // DEBUG code #ifdef DEBUG_LOG void ExceptionTable:: print(LogModuleObject &f) { if(numberofEntries == 0) { UT_OBJECTLOG(f, PR_LOG_ALWAYS, ("The exception table is empty.\n")); } else { UT_OBJECTLOG(f, PR_LOG_ALWAYS, ("(begin-offset, end-offset) -> handler-offset (exception caught)\n")); for(Uint32 i = 0; i < numberofEntries; i++) mEntries[i].print(f); } } void ExceptionTable:: printShort(LogModuleObject &f) { if(numberofEntries != 0) for(Uint32 i = 0; i < numberofEntries; i++) { UT_OBJECTLOG(f, PR_LOG_ALWAYS, ("\t")); mEntries[i].print(f,start); } } #endif // DEBUG