avoid garbage collection from e.g. divideLong thunk

It is dangerous to initiate a GC from a thunk like divideLong (which
was possible when allocating a new ArithmeticException to signal
divide-by-zero) since we don't currently generate a GC root frame map
for the return address of the thunk call.  Instead, we use the backup
heap area if there is room, or else throw a pre-allocated exception
instead.
This commit is contained in:
Joel Dice 2011-01-31 21:18:55 -07:00
parent 2a5e556e09
commit 635f5ba7e6

View File

@ -2430,13 +2430,49 @@ absoluteInt(int32_t a)
return a > 0 ? a : -a;
}
unsigned
traceSize(Thread* t)
{
class Counter: public Processor::StackVisitor {
public:
Counter(): count(0) { }
virtual bool visit(Processor::StackWalker*) {
++ count;
return true;
}
unsigned count;
} counter;
t->m->processor->walkStack(t, &counter);
return FixedSizeOfArray + (counter.count * ArrayElementSizeOfArray)
+ (counter.count * FixedSizeOfTraceElement);
}
void NO_RETURN
throwArithmetic(MyThread* t)
{
if (ensure(t, FixedSizeOfArithmeticException + traceSize(t))) {
atomicOr(&(t->flags), Thread::TracingFlag);
THREAD_RESOURCE0(t, atomicAnd(&(t->flags), ~Thread::TracingFlag));
throwNew(t, Machine::ArithmeticExceptionType);
} else {
// not enough memory available for a new exception and stack trace
// -- use a preallocated instance instead
throw_(t, root(t, Machine::ArithmeticException));
}
}
int64_t
divideLong(MyThread* t, int64_t b, int64_t a)
{
if (LIKELY(b)) {
return a / b;
} else {
throwNew(t, Machine::ArithmeticExceptionType);
throwArithmetic(t);
}
}
@ -2446,7 +2482,7 @@ divideInt(MyThread* t, int32_t b, int32_t a)
if (LIKELY(b)) {
return a / b;
} else {
throwNew(t, Machine::ArithmeticExceptionType);
throwArithmetic(t);
}
}
@ -2456,7 +2492,7 @@ moduloLong(MyThread* t, int64_t b, int64_t a)
if (LIKELY(b)) {
return a % b;
} else {
throwNew(t, Machine::ArithmeticExceptionType);
throwArithmetic(t);
}
}
@ -2466,7 +2502,7 @@ moduloInt(MyThread* t, int32_t b, int32_t a)
if (LIKELY(b)) {
return a % b;
} else {
throwNew(t, Machine::ArithmeticExceptionType);
throwArithmetic(t);
}
}
@ -2656,27 +2692,6 @@ makeMultidimensionalArray(MyThread* t, object class_, int32_t dimensions,
(t, class_, static_cast<uintptr_t*>(t->stack) + offset, dimensions));
}
unsigned
traceSize(Thread* t)
{
class Counter: public Processor::StackVisitor {
public:
Counter(): count(0) { }
virtual bool visit(Processor::StackWalker*) {
++ count;
return true;
}
unsigned count;
} counter;
t->m->processor->walkStack(t, &counter);
return FixedSizeOfArray + (counter.count * ArrayElementSizeOfArray)
+ (counter.count * FixedSizeOfTraceElement);
}
void NO_RETURN
throwArrayIndexOutOfBounds(MyThread* t)
{