fix bootimage build

We now detect both metafactory and altMetafactory lambdas when
bootimage-compiling invokedynamic instructions, as well as make
allowance for the same lambda being invoked by multiple invokedynamic
instructions (as is the case for Serializable lambdas).
This commit is contained in:
Joel Dice 2016-12-05 17:41:02 -07:00
parent 138699e203
commit 678d7debda
3 changed files with 159 additions and 119 deletions

View File

@ -27,4 +27,6 @@ public class ClassAddendum extends Addendum {
public Pair enclosingMethod; public Pair enclosingMethod;
public VMMethod[] bootstrapMethodTable; public VMMethod[] bootstrapMethodTable;
public VMMethod[] bootstrapLambdaTable;
} }

View File

@ -4040,15 +4040,26 @@ bool isLambda(Thread* t,
return vm::strcmp(reinterpret_cast<const int8_t*>( return vm::strcmp(reinterpret_cast<const int8_t*>(
"java/lang/invoke/LambdaMetafactory"), "java/lang/invoke/LambdaMetafactory"),
bootstrap->class_()->name()->body().begin()) == 0 bootstrap->class_()->name()->body().begin()) == 0
and vm::strcmp(reinterpret_cast<const int8_t*>("metafactory"), and ((vm::strcmp(reinterpret_cast<const int8_t*>("metafactory"),
bootstrap->name()->body().begin()) == 0 bootstrap->name()->body().begin()) == 0
and vm::strcmp( and vm::strcmp(
reinterpret_cast<const int8_t*>( reinterpret_cast<const int8_t*>(
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/" "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/"
"String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/" "String;Ljava/lang/invoke/MethodType;Ljava/lang/"
"MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/" "invoke/"
"MethodType;Ljava/lang/invoke/MethodHandle;Ljava/"
"lang/"
"invoke/MethodType;)Ljava/lang/invoke/CallSite;"), "invoke/MethodType;)Ljava/lang/invoke/CallSite;"),
bootstrap->spec()->body().begin()) == 0; bootstrap->spec()->body().begin()) == 0)
or (vm::strcmp(reinterpret_cast<const int8_t*>("altMetafactory"),
bootstrap->name()->body().begin()) == 0
and vm::strcmp(
reinterpret_cast<const int8_t*>(
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/"
"lang/"
"String;Ljava/lang/invoke/MethodType;[Ljava/lang/"
"Object;)Ljava/lang/invoke/CallSite;"),
bootstrap->spec()->body().begin()) == 0));
} }
void compile(MyThread* t, void compile(MyThread* t,
@ -5133,6 +5144,16 @@ loop:
GcClass* c = context->method->class_(); GcClass* c = context->method->class_();
PROTECT(t, c); PROTECT(t, c);
GcMethod* target
= c->addendum()->bootstrapLambdaTable()
? cast<GcMethod>(
t,
cast<GcArray>(t, c->addendum()->bootstrapLambdaTable())
->body()[invocation->bootstrap()])
: nullptr;
PROTECT(t, target);
if (target == nullptr) {
GcCharArray* bootstrapArray = cast<GcCharArray>( GcCharArray* bootstrapArray = cast<GcCharArray>(
t, t,
cast<GcArray>(t, c->addendum()->bootstrapMethodTable()) cast<GcArray>(t, c->addendum()->bootstrapMethodTable())
@ -5141,7 +5162,8 @@ loop:
if (isLambda(t, c->loader(), bootstrapArray, invocation)) { if (isLambda(t, c->loader(), bootstrapArray, invocation)) {
if (bc->hostVM == 0) { if (bc->hostVM == 0) {
throwNew(t, throwNew(
t,
GcVirtualMachineError::Type, GcVirtualMachineError::Type,
"lambda expression encountered, but host VM is not " "lambda expression encountered, but host VM is not "
"available; use -hostvm option to bootimage-generator to " "available; use -hostvm option to bootimage-generator to "
@ -5149,16 +5171,18 @@ loop:
} }
JNIEnv* e; JNIEnv* e;
if (bc->hostVM->vtable->AttachCurrentThread(bc->hostVM, &e, 0) == 0) { if (bc->hostVM->vtable->AttachCurrentThread(bc->hostVM, &e, 0)
== 0) {
e->vtable->PushLocalFrame(e, 256); e->vtable->PushLocalFrame(e, 256);
jclass lmfClass jclass lmfClass = e->vtable->FindClass(
= e->vtable->FindClass(e, "java/lang/invoke/LambdaMetafactory"); e, "java/lang/invoke/LambdaMetafactory");
jmethodID makeLambda = e->vtable->GetStaticMethodID( jmethodID makeLambda = e->vtable->GetStaticMethodID(
e, e,
lmfClass, lmfClass,
"makeLambda", "makeLambda",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/" "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/"
"String;Ljava/"
"lang/String;Ljava/lang/String;Ljava/lang/String;I)[B"); "lang/String;Ljava/lang/String;Ljava/lang/String;I)[B");
GcReference* reference = cast<GcReference>( GcReference* reference = cast<GcReference>(
@ -5232,14 +5256,24 @@ loop:
invocation->template_()->spec()->body().begin(), invocation->template_()->spec()->body().begin(),
invocation->template_()->spec()->length()); invocation->template_()->spec()->length());
GcMethod* target = resolveMethod( target = resolveMethod(
t, lambdaClass, "make", RUNTIME_ARRAY_BODY(spec)); t, lambdaClass, "make", RUNTIME_ARRAY_BODY(spec));
bool tailCall = isTailCall(t, code, ip, context->method, target); GcArray* table
compileDirectInvoke(t, frame, target, tailCall); = cast<GcArray>(t, c->addendum()->bootstrapLambdaTable());
if (table == nullptr) {
table = makeArray(
t,
cast<GcArray>(t, c->addendum()->bootstrapMethodTable())
->length());
c->addendum()->setBootstrapLambdaTable(t, table);
}
table->setBodyElement(t, invocation->bootstrap(), target);
} else { } else {
throwNew( throwNew(t,
t, GcVirtualMachineError::Type, "unable to attach to host VM"); GcVirtualMachineError::Type,
"unable to attach to host VM");
} }
} else { } else {
throwNew(t, throwNew(t,
@ -5247,6 +5281,10 @@ loop:
"invokedynamic not supported for AOT-compiled code except " "invokedynamic not supported for AOT-compiled code except "
"in the case of lambda expressions"); "in the case of lambda expressions");
} }
}
bool tailCall = isTailCall(t, code, ip, context->method, target);
compileDirectInvoke(t, frame, target, tailCall);
} else { } else {
unsigned index = addDynamic(t, invocation); unsigned index = addDynamic(t, invocation);

View File

@ -1220,7 +1220,7 @@ GcClassAddendum* getClassAddendum(Thread* t, GcClass* class_, GcSingleton* pool)
if (addendum == 0) { if (addendum == 0) {
PROTECT(t, class_); PROTECT(t, class_);
addendum = makeClassAddendum(t, pool, 0, 0, 0, 0, -1, 0, 0, 0); addendum = makeClassAddendum(t, pool, 0, 0, 0, 0, -1, 0, 0, 0, 0);
setField(t, class_, ClassAddendum, addendum); setField(t, class_, ClassAddendum, addendum);
} }
return addendum; return addendum;