mirror of
https://github.com/corda/corda.git
synced 2025-01-21 03:55:00 +00:00
fix some lambda bugs
For lambdas that implement java.io.Serializable, the compiler emits calls to LambdaMetaFactory.altMetafactory, not LambdaMetaFactory.metafactory, so I've provided a stub implementation that ignores that currently ignores the extra parameters it receives. This also fixes a bug in compiling lambda glue code for lambdas that take longs and/or doubles.
This commit is contained in:
parent
a4d9037ae4
commit
69426b9945
@ -306,4 +306,14 @@ public class LambdaMetafactory {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static CallSite altMetafactory(MethodHandles.Lookup caller,
|
||||||
|
String invokedName,
|
||||||
|
MethodType invokedType,
|
||||||
|
Object... args)
|
||||||
|
throws LambdaConversionException
|
||||||
|
{
|
||||||
|
// todo: handle flags
|
||||||
|
return metafactory(caller, invokedName, invokedType, (MethodType) args[0], (MethodHandle) args[1], (MethodType) args[2]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,8 +242,8 @@ public final class MethodType implements java.io.Serializable {
|
|||||||
ObjectType(aload, areturn, 1),
|
ObjectType(aload, areturn, 1),
|
||||||
IntegerType(iload, ireturn, 1),
|
IntegerType(iload, ireturn, 1),
|
||||||
FloatType(fload, freturn, 1),
|
FloatType(fload, freturn, 1),
|
||||||
LongType(lload, lreturn, 1),
|
LongType(lload, lreturn, 2),
|
||||||
DoubleType(dload, dreturn, 1),
|
DoubleType(dload, dreturn, 2),
|
||||||
VoidType(-1, Assembler.return_, -1);
|
VoidType(-1, Assembler.return_, -1);
|
||||||
|
|
||||||
public final int load;
|
public final int load;
|
||||||
|
@ -6055,8 +6055,6 @@ GcCallSite* resolveDynamic(Thread* t, GcInvocation* invocation)
|
|||||||
GcNoSuchMethodError::Type));
|
GcNoSuchMethodError::Type));
|
||||||
PROTECT(t, bootstrap);
|
PROTECT(t, bootstrap);
|
||||||
|
|
||||||
assertT(t, bootstrap->parameterCount() == 2 + bootstrapArray->length());
|
|
||||||
|
|
||||||
GcLookup* lookup
|
GcLookup* lookup
|
||||||
= makeLookup(t, c, ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC);
|
= makeLookup(t, c, ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC);
|
||||||
PROTECT(t, lookup);
|
PROTECT(t, lookup);
|
||||||
@ -6078,14 +6076,47 @@ GcCallSite* resolveDynamic(Thread* t, GcInvocation* invocation)
|
|||||||
array->setBodyElement(t, argument++, name);
|
array->setBodyElement(t, argument++, name);
|
||||||
array->setBodyElement(t, argument++, type);
|
array->setBodyElement(t, argument++, type);
|
||||||
|
|
||||||
MethodSpecIterator it(
|
const char* spec;
|
||||||
t, reinterpret_cast<const char*>(bootstrap->spec()->body().begin()));
|
GcArray* argArray = array;
|
||||||
|
PROTECT(t, argArray);
|
||||||
|
|
||||||
|
if (::strcmp(reinterpret_cast<char*>(bootstrap->spec()->body().begin()),
|
||||||
|
"(Ljava/lang/invoke/MethodHandles$Lookup;"
|
||||||
|
"Ljava/lang/String;"
|
||||||
|
"Ljava/lang/invoke/MethodType;"
|
||||||
|
"[Ljava/lang/Object;)"
|
||||||
|
"Ljava/lang/invoke/CallSite;") == 0) {
|
||||||
|
// LambdaMetaFactory.altMetafactory
|
||||||
|
array = makeArray(t, bootstrapArray->length() - 1);
|
||||||
|
spec = "(Ljava/lang/invoke/MethodHandles$Lookup;"
|
||||||
|
"Ljava/lang/String;"
|
||||||
|
"Ljava/lang/invoke/MethodType;"
|
||||||
|
"Ljava/lang/invoke/MethodType;"
|
||||||
|
"Ljava/lang/invoke/MethodHandle;"
|
||||||
|
"Ljava/lang/invoke/MethodType;"
|
||||||
|
"I"
|
||||||
|
"I"
|
||||||
|
"[Ljava/lang/Class;"
|
||||||
|
"I"
|
||||||
|
"[Ljava/lang/invoke/MethodType;"
|
||||||
|
")Ljava/lang/invoke/CallSite;";
|
||||||
|
} else if (bootstrap->parameterCount() == 2 + bootstrapArray->length()) {
|
||||||
|
spec = reinterpret_cast<char*>(bootstrap->spec()->body().begin());
|
||||||
|
} else {
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodSpecIterator it(t, spec);
|
||||||
|
|
||||||
for (unsigned i = 0; i < argument; ++i)
|
for (unsigned i = 0; i < argument; ++i)
|
||||||
it.next();
|
it.next();
|
||||||
|
|
||||||
|
if (argArray != array) {
|
||||||
|
argument = 0;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
while (it.hasNext()) {
|
while (i + 1 < bootstrapArray->length() && it.hasNext()) {
|
||||||
const char* p = it.next();
|
const char* p = it.next();
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'L': {
|
case 'L': {
|
||||||
@ -6162,8 +6193,12 @@ GcCallSite* resolveDynamic(Thread* t, GcInvocation* invocation)
|
|||||||
? 0
|
? 0
|
||||||
: makeMethodHandle(t, REF_invokeSpecial, c->loader(), bootstrap, 0);
|
: makeMethodHandle(t, REF_invokeSpecial, c->loader(), bootstrap, 0);
|
||||||
|
|
||||||
|
if (argArray != array) {
|
||||||
|
argArray->setBodyElement(t, 3, array);
|
||||||
|
}
|
||||||
|
|
||||||
return cast<GcCallSite>(
|
return cast<GcCallSite>(
|
||||||
t, t->m->processor->invokeArray(t, bootstrap, handle, array));
|
t, t->m->processor->invokeArray(t, bootstrap, handle, argArray));
|
||||||
}
|
}
|
||||||
|
|
||||||
void noop()
|
void noop()
|
||||||
|
@ -9,6 +9,24 @@ public class InvokeDynamic {
|
|||||||
int operate(int a, int b);
|
int operate(int a, int b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private interface Operation2 {
|
||||||
|
long operate(long a, int b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Pair<A, B> {
|
||||||
|
public final A first;
|
||||||
|
public final B second;
|
||||||
|
|
||||||
|
public Pair(A first, B second) {
|
||||||
|
this.first = first;
|
||||||
|
this.second = second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private interface Supplier<T> extends java.io.Serializable {
|
||||||
|
T get();
|
||||||
|
}
|
||||||
|
|
||||||
private static void expect(boolean v) {
|
private static void expect(boolean v) {
|
||||||
if (! v) throw new RuntimeException();
|
if (! v) throw new RuntimeException();
|
||||||
}
|
}
|
||||||
@ -24,8 +42,19 @@ public class InvokeDynamic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void test() {
|
private void test() {
|
||||||
int c = 2;
|
{ int c = 2;
|
||||||
Operation op = (a, b) -> ((a + b) * c) - foo;
|
Operation op = (a, b) -> ((a + b) * c) - foo;
|
||||||
expect(op.operate(2, 3) == ((2 + 3) * 2) - foo);
|
expect(op.operate(2, 3) == ((2 + 3) * 2) - foo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ int c = 2;
|
||||||
|
Operation2 op = (a, b) -> ((a + b) * c) - foo;
|
||||||
|
expect(op.operate(2, 3) == ((2 + 3) * 2) - foo);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ Supplier<Pair<Long, Double>> s = () -> new Pair<Long, Double>(42L, 77.1D);
|
||||||
|
expect(s.get().first == 42L);
|
||||||
|
expect(s.get().second == 77.1D);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user