Skip to content

Commit b05445e

Browse files
committed
fix invokedynamic in default interface methods for bootimage builds
The old code mistakenly attached the bootstrap method table to the class in which it was declared, rather than the invocation(s) where it was used, which caused confusion and crashes when compiling invokedynamic in default interface methods for bootimage builds. This fixes it.
1 parent 98980aa commit b05445e

File tree

5 files changed

+67
-47
lines changed

5 files changed

+67
-47
lines changed

classpath/avian/ClassAddendum.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,4 @@ public class ClassAddendum extends Addendum {
2525
public byte[] enclosingClass;
2626

2727
public Pair enclosingMethod;
28-
29-
public VMMethod[] bootstrapMethodTable;
30-
31-
public VMMethod[] bootstrapLambdaTable;
3228
}

src/compile.cpp

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5145,20 +5145,20 @@ void compile(MyThread* t,
51455145
GcClass* c = context->method->class_();
51465146
PROTECT(t, c);
51475147

5148-
GcMethod* target
5149-
= c->addendum()->bootstrapLambdaTable()
5150-
? cast<GcMethod>(
5151-
t,
5152-
cast<GcArray>(t, c->addendum()->bootstrapLambdaTable())
5153-
->body()[invocation->bootstrap()])
5154-
: nullptr;
5148+
// We use the second half of the bootstrap method table as a
5149+
// cache for already-synthesized lambdas:
5150+
GcMethod* target = cast<GcMethod>(
5151+
t, invocation->bootstrapMethodTable()
5152+
->body()[(invocation->bootstrapMethodTable()->length() / 2)
5153+
+ invocation->bootstrap()]);
51555154
PROTECT(t, target);
51565155

51575156
if (target == nullptr) {
5157+
// Not cached, so now we need to synthesize it:
5158+
51585159
GcCharArray* bootstrapArray = cast<GcCharArray>(
5159-
t,
5160-
cast<GcArray>(t, c->addendum()->bootstrapMethodTable())
5161-
->body()[invocation->bootstrap()]);
5160+
t, cast<GcArray>(t, invocation->bootstrapMethodTable())
5161+
->body()[invocation->bootstrap()]);
51625162
PROTECT(t, bootstrapArray);
51635163

51645164
if (isLambda(t, c->loader(), bootstrapArray, invocation)) {
@@ -5263,17 +5263,13 @@ void compile(MyThread* t,
52635263
target = resolveMethod(
52645264
t, lambdaClass, "make", RUNTIME_ARRAY_BODY(spec));
52655265

5266-
GcArray* table
5267-
= cast<GcArray>(t, c->addendum()->bootstrapLambdaTable());
5268-
if (table == nullptr) {
5269-
table = makeArray(
5270-
t,
5271-
cast<GcArray>(t, c->addendum()->bootstrapMethodTable())
5272-
->length());
5273-
c->addendum()->setBootstrapLambdaTable(t, table);
5274-
}
5275-
5276-
table->setBodyElement(t, invocation->bootstrap(), target);
5266+
// Now cache it so we don't try to re-synthesize it
5267+
// later.
5268+
invocation->bootstrapMethodTable()->setBodyElement(
5269+
t,
5270+
(invocation->bootstrapMethodTable()->length() / 2)
5271+
+ invocation->bootstrap(),
5272+
target);
52775273
} else {
52785274
throwNew(t,
52795275
GcVirtualMachineError::Type,

src/machine.cpp

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -877,9 +877,11 @@ unsigned parsePoolEntry(Thread* t,
877877
Stream& s,
878878
uint32_t* index,
879879
GcSingleton* pool,
880+
GcList* invocations,
880881
unsigned i)
881882
{
882883
PROTECT(t, pool);
884+
PROTECT(t, invocations);
883885

884886
s.setPosition(index[i]);
885887

@@ -921,7 +923,7 @@ unsigned parsePoolEntry(Thread* t,
921923
case CONSTANT_Class: {
922924
if (singletonObject(t, pool, i) == 0) {
923925
unsigned si = s.read2() - 1;
924-
parsePoolEntry(t, s, index, pool, si);
926+
parsePoolEntry(t, s, index, pool, invocations, si);
925927

926928
GcReference* value = makeReference(
927929
t, 0, 0, cast<GcByteArray>(t, singletonObject(t, pool, si)), 0);
@@ -937,7 +939,7 @@ unsigned parsePoolEntry(Thread* t,
937939
case CONSTANT_String: {
938940
if (singletonObject(t, pool, i) == 0) {
939941
unsigned si = s.read2() - 1;
940-
parsePoolEntry(t, s, index, pool, si);
942+
parsePoolEntry(t, s, index, pool, invocations, si);
941943

942944
object value
943945
= parseUtf8(t, cast<GcByteArray>(t, singletonObject(t, pool, si)));
@@ -958,8 +960,8 @@ unsigned parsePoolEntry(Thread* t,
958960
unsigned ni = s.read2() - 1;
959961
unsigned ti = s.read2() - 1;
960962

961-
parsePoolEntry(t, s, index, pool, ni);
962-
parsePoolEntry(t, s, index, pool, ti);
963+
parsePoolEntry(t, s, index, pool, invocations, ni);
964+
parsePoolEntry(t, s, index, pool, invocations, ti);
963965

964966
GcByteArray* name = cast<GcByteArray>(t, singletonObject(t, pool, ni));
965967
GcByteArray* type = cast<GcByteArray>(t, singletonObject(t, pool, ti));
@@ -984,8 +986,8 @@ unsigned parsePoolEntry(Thread* t,
984986
unsigned ci = s.read2() - 1;
985987
unsigned nti = s.read2() - 1;
986988

987-
parsePoolEntry(t, s, index, pool, ci);
988-
parsePoolEntry(t, s, index, pool, nti);
989+
parsePoolEntry(t, s, index, pool, invocations, ci);
990+
parsePoolEntry(t, s, index, pool, invocations, nti);
989991

990992
GcByteArray* className
991993
= cast<GcReference>(t, singletonObject(t, pool, ci))->name();
@@ -1015,7 +1017,7 @@ unsigned parsePoolEntry(Thread* t,
10151017
unsigned kind = s.read1();
10161018
unsigned ri = s.read2() - 1;
10171019

1018-
parsePoolEntry(t, s, index, pool, ri);
1020+
parsePoolEntry(t, s, index, pool, invocations, ri);
10191021

10201022
GcReference* value = cast<GcReference>(t, singletonObject(t, pool, ri));
10211023

@@ -1040,7 +1042,7 @@ unsigned parsePoolEntry(Thread* t,
10401042
if (singletonObject(t, pool, i) == 0) {
10411043
unsigned ni = s.read2() - 1;
10421044

1043-
parsePoolEntry(t, s, index, pool, ni);
1045+
parsePoolEntry(t, s, index, pool, invocations, ni);
10441046

10451047
pool->setBodyElement(
10461048
t, i, reinterpret_cast<uintptr_t>(singletonObject(t, pool, ni)));
@@ -1052,7 +1054,7 @@ unsigned parsePoolEntry(Thread* t,
10521054
unsigned bootstrap = s.read2();
10531055
unsigned nti = s.read2() - 1;
10541056

1055-
parsePoolEntry(t, s, index, pool, nti);
1057+
parsePoolEntry(t, s, index, pool, invocations, nti);
10561058

10571059
GcPair* nameAndType = cast<GcPair>(t, singletonObject(t, pool, nti));
10581060

@@ -1086,9 +1088,12 @@ unsigned parsePoolEntry(Thread* t,
10861088
0);
10871089

10881090
object value = reinterpret_cast<object>(
1089-
makeInvocation(t, bootstrap, -1, 0, pool, template_, 0));
1091+
makeInvocation(t, bootstrap, -1, 0, pool, template_, 0, 0));
1092+
PROTECT(t, value);
10901093

10911094
pool->setBodyElement(t, i, reinterpret_cast<uintptr_t>(value));
1095+
1096+
listAppend(t, invocations, value);
10921097
}
10931098
return 1;
10941099

@@ -1097,8 +1102,10 @@ unsigned parsePoolEntry(Thread* t,
10971102
}
10981103
}
10991104

1100-
GcSingleton* parsePool(Thread* t, Stream& s)
1105+
GcSingleton* parsePool(Thread* t, Stream& s, GcList* invocations)
11011106
{
1107+
PROTECT(t, invocations);
1108+
11021109
unsigned count = s.read2() - 1;
11031110
GcSingleton* pool = makeSingletonOfSize(t, count + poolMaskSize(count));
11041111
PROTECT(t, pool);
@@ -1184,7 +1191,7 @@ GcSingleton* parsePool(Thread* t, Stream& s)
11841191
unsigned end = s.position();
11851192

11861193
for (unsigned i = 0; i < count;) {
1187-
i += parsePoolEntry(t, s, index, pool, i);
1194+
i += parsePoolEntry(t, s, index, pool, invocations, i);
11881195
}
11891196

11901197
s.setPosition(end);
@@ -1220,7 +1227,7 @@ GcClassAddendum* getClassAddendum(Thread* t, GcClass* class_, GcSingleton* pool)
12201227
if (addendum == 0) {
12211228
PROTECT(t, class_);
12221229

1223-
addendum = makeClassAddendum(t, pool, 0, 0, 0, 0, -1, 0, 0, 0, 0);
1230+
addendum = makeClassAddendum(t, pool, 0, 0, 0, 0, -1, 0, 0);
12241231
setField(t, class_, ClassAddendum, addendum);
12251232
}
12261233
return addendum;
@@ -2753,10 +2760,12 @@ void parseMethodTable(Thread* t, Stream& s, GcClass* class_, GcSingleton* pool)
27532760
void parseAttributeTable(Thread* t,
27542761
Stream& s,
27552762
GcClass* class_,
2756-
GcSingleton* pool)
2763+
GcSingleton* pool,
2764+
GcList* invocations)
27572765
{
27582766
PROTECT(t, class_);
27592767
PROTECT(t, pool);
2768+
PROTECT(t, invocations);
27602769

27612770
unsigned attributeCount = s.read2();
27622771
for (unsigned j = 0; j < attributeCount; ++j) {
@@ -2814,7 +2823,7 @@ void parseAttributeTable(Thread* t,
28142823
} else if (vm::strcmp(reinterpret_cast<const int8_t*>("BootstrapMethods"),
28152824
name->body().begin()) == 0) {
28162825
unsigned count = s.read2();
2817-
GcArray* array = makeArray(t, count);
2826+
GcArray* array = makeArray(t, count * 2);
28182827
PROTECT(t, array);
28192828

28202829
for (unsigned i = 0; i < count; ++i) {
@@ -2828,8 +2837,10 @@ void parseAttributeTable(Thread* t,
28282837
array->setBodyElement(t, i, element);
28292838
}
28302839

2831-
GcClassAddendum* addendum = getClassAddendum(t, class_, pool);
2832-
addendum->setBootstrapMethodTable(t, array);
2840+
for (GcPair* p = cast<GcPair>(t, invocations->front()); p;
2841+
p = cast<GcPair>(t, p->second())) {
2842+
cast<GcInvocation>(t, p->first())->setBootstrapMethodTable(t, array);
2843+
}
28332844
} else if (vm::strcmp(reinterpret_cast<const int8_t*>("EnclosingMethod"),
28342845
name->body().begin()) == 0) {
28352846
int16_t enclosingClass = s.read2();
@@ -4757,7 +4768,10 @@ GcClass* parseClass(Thread* t,
47574768
fprintf(stderr, "read class (minor %d major %d)\n", minorVer, majorVer);
47584769
}
47594770

4760-
GcSingleton* pool = parsePool(t, s);
4771+
GcList* invocations = makeList(t, 0, 0, 0);
4772+
PROTECT(t, invocations);
4773+
4774+
GcSingleton* pool = parsePool(t, s, invocations);
47614775
PROTECT(t, pool);
47624776

47634777
unsigned flags = s.read2();
@@ -4812,7 +4826,7 @@ GcClass* parseClass(Thread* t,
48124826

48134827
parseMethodTable(t, s, class_, pool);
48144828

4815-
parseAttributeTable(t, s, class_, pool);
4829+
parseAttributeTable(t, s, class_, pool, invocations);
48164830

48174831
GcArray* vtable = cast<GcArray>(t, class_->virtualTable());
48184832
unsigned vtableLength = (vtable ? vtable->length() : 0);
@@ -6080,9 +6094,8 @@ GcCallSite* resolveDynamic(Thread* t, GcInvocation* invocation)
60806094

60816095
// First element points to the bootstrap method. The rest are static data passed to the BSM.
60826096
GcCharArray* bootstrapArray = cast<GcCharArray>(
6083-
t,
6084-
cast<GcArray>(t, c->addendum()->bootstrapMethodTable())
6085-
->body()[invocation->bootstrap()]);
6097+
t, cast<GcArray>(t, invocation->bootstrapMethodTable())
6098+
->body()[invocation->bootstrap()]);
60866099

60876100
PROTECT(t, bootstrapArray);
60886101

src/types.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
(class class)
9090
(singleton pool)
9191
(method template)
92+
(field array bootstrapMethodTable)
9293
(callSite site))
9394

9495
(type triple

test/InvokeDynamic.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ private static Integer addBoxed(Integer a, Integer b) {
103103
private interface Marker {
104104
}
105105

106+
private interface MyFunction<T, R> {
107+
R apply(T t);
108+
109+
default <V> MyFunction<T, V> andThen(MyFunction<? super R, ? extends V> after) {
110+
return t -> after.apply(apply(t));
111+
}
112+
}
113+
106114
private void test() {
107115
{ int c = 2;
108116
Operation op = (a, b) -> ((a + b) * c) - foo;
@@ -180,5 +188,11 @@ private void test() {
180188
{ Supplier<java.util.List<String>> s = java.util.ArrayList<String>::new;
181189
java.util.List<String> list = s.get();
182190
}
191+
192+
{
193+
MyFunction<Integer, Integer> addTwo = x -> x + 2;
194+
MyFunction<Integer, Integer> mulTwo = x -> x * 2;
195+
expect(addTwo.andThen(mulTwo).apply(7) == 18);
196+
}
183197
}
184198
}

0 commit comments

Comments
 (0)