зеркало из https://github.com/mozilla/gecko-dev.git
186 строки
5.2 KiB
C++
186 строки
5.2 KiB
C++
/* -*- 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
|