load bootstrap classes in findInterfaceMethod

In afbd4ff, I made a low-risk, but very specific fix for a more
general problem: "bootstrap" classes (i.e. classes which the VM has
built-in knowledge of) need to be loaded from the classpath before any
of their methods are called.  Based on recent testing, I found there were
more cases than I previously thought where the VM tries to call methods on
"unloaded" bootstrap classes, so we needed a more general solution to
the problem.

This commit addresses it by closing the last (known) loophole by which
methods might be called on bootstrap classes: invokeinterface, and its
helper method findInterfaceMethod.  The fix is to check for bootstrap
classes in findInterfaceMethod and load the full versions if
necessary.  This process may lead to garbage collection and/or thrown
exceptions, which made me nervous about cases of direct or indirect
calls to findInterfaceMethod not expecting those events, which is why
I hadn't used that approach earlier.  However, it turns out there were
only a few places that made non-GC-safe calls to findInterfaceMethod,
and a bit of code rearrangement fixed that.
This commit is contained in:
Joel Dice 2015-02-06 13:50:59 -07:00
parent 21e6bd8598
commit 7a4cae0dde
4 changed files with 17 additions and 22 deletions

View File

@ -2675,7 +2675,12 @@ inline GcMethod* findInterfaceMethod(Thread* t,
GcMethod* method,
GcClass* class_)
{
assertT(t, (class_->vmFlags() & BootstrapFlag) == 0);
if (UNLIKELY(class_->vmFlags() & BootstrapFlag)) {
PROTECT(t, method);
PROTECT(t, class_);
resolveSystemClass(t, roots(t)->bootLoader(), class_->name());
}
GcClass* interface = method->class_();
GcArray* itable = cast<GcArray>(t, class_->interfaceTable());

View File

@ -2452,19 +2452,10 @@ object makeJconstructor(Thread* t,
}
#endif // HAVE_JexecutableHasRealParameterData
void resolveBootstrap(Thread* t, Gc::Type type)
{
if (vm::type(t, type)->vmFlags() & BootstrapFlag) {
resolveSystemClass(t, roots(t)->bootLoader(), vm::type(t, type)->name());
}
}
object makeJmethod(Thread* t, GcMethod* vmMethod, int index)
{
PROTECT(t, vmMethod);
resolveBootstrap(t, GcJmethod::Type);
object name
= intern(t,
t->m->classpath->makeString(
@ -2567,8 +2558,6 @@ object makeJconstructor(Thread* t, GcMethod* vmMethod, int index)
{
PROTECT(t, vmMethod);
resolveBootstrap(t, GcJconstructor::Type);
unsigned parameterCount;
unsigned returnTypeSpec;
object parameterTypes = resolveParameterJTypes(t,
@ -2649,8 +2638,6 @@ object makeJfield(Thread* t, GcField* vmField, int index)
{
PROTECT(t, vmField);
resolveBootstrap(t, GcJfield::Type);
object name
= intern(t,
t->m->classpath->makeString(

View File

@ -8639,8 +8639,6 @@ class MyProcessor : public Processor {
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
method = findMethod(t, method, this_);
const char* spec = reinterpret_cast<char*>(method->spec()->body().begin());
unsigned size = method->parameterFootprint();
@ -8656,6 +8654,8 @@ class MyProcessor : public Processor {
PROTECT(t, method);
method = findMethod(t, method, this_);
compile(static_cast<MyThread*>(t),
local::codeAllocator(static_cast<MyThread*>(t)),
0,
@ -8677,8 +8677,6 @@ class MyProcessor : public Processor {
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
method = findMethod(t, method, this_);
const char* spec = reinterpret_cast<char*>(method->spec()->body().begin());
unsigned size = method->parameterFootprint();
@ -8694,6 +8692,8 @@ class MyProcessor : public Processor {
PROTECT(t, method);
method = findMethod(t, method, this_);
compile(static_cast<MyThread*>(t),
local::codeAllocator(static_cast<MyThread*>(t)),
0,
@ -8716,8 +8716,6 @@ class MyProcessor : public Processor {
assertT(t, ((method->flags() & ACC_STATIC) == 0) xor (this_ == 0));
method = findMethod(t, method, this_);
const char* spec = reinterpret_cast<char*>(method->spec()->body().begin());
unsigned size = method->parameterFootprint();
@ -8734,6 +8732,8 @@ class MyProcessor : public Processor {
PROTECT(t, method);
method = findMethod(t, method, this_);
compile(static_cast<MyThread*>(t),
local::codeAllocator(static_cast<MyThread*>(t)),
0,

View File

@ -1,4 +1,4 @@
public class Threads implements Runnable {
public class Threads implements Runnable {
private static boolean success = false;
private static void expect(boolean v) {
@ -6,6 +6,9 @@ public class Threads implements Runnable {
}
public static void main(String[] args) throws Exception {
((Thread.UncaughtExceptionHandler) Thread.currentThread().getThreadGroup())
.uncaughtException(Thread.currentThread(), new Exception());
{ Threads test = new Threads();
Thread thread = new Thread(test);
@ -41,7 +44,7 @@ public class Threads implements Runnable {
// do nothing
}
};
thread.start();
thread.join();
}