mirror of
https://github.com/corda/corda.git
synced 2025-03-11 15:04:14 +00:00
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:
parent
2a5e556e09
commit
635f5ba7e6
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user