mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +00:00
add invokedynamic support to interpreter
This commit is contained in:
parent
8a7944d25c
commit
66712a8cff
@ -2349,6 +2349,8 @@ GcClass* findLoadedClass(Thread* t, GcClassLoader* loader, GcByteArray* spec);
|
||||
|
||||
GcJclass* getDeclaringClass(Thread* t, GcClass* c);
|
||||
|
||||
GcCallSite* resolveDynamic(Thread* t, GcInvocation* invocation);
|
||||
|
||||
inline bool emptyMethod(Thread* t UNUSED, GcMethod* method)
|
||||
{
|
||||
return ((method->flags() & ACC_NATIVE) == 0)
|
||||
|
136
src/compile.cpp
136
src/compile.cpp
@ -58,7 +58,7 @@ namespace {
|
||||
|
||||
namespace local {
|
||||
|
||||
const bool DebugCompile = true;
|
||||
const bool DebugCompile = false;
|
||||
const bool DebugNatives = false;
|
||||
const bool DebugCallTable = false;
|
||||
const bool DebugMethodTree = false;
|
||||
@ -7278,140 +7278,6 @@ uint64_t compileVirtualMethod(MyThread* t)
|
||||
return reinterpret_cast<uintptr_t>(compileVirtualMethod2(t, class_, index));
|
||||
}
|
||||
|
||||
GcCallSite* resolveDynamic(MyThread* t, GcInvocation* invocation)
|
||||
{
|
||||
PROTECT(t, invocation);
|
||||
|
||||
GcClass* c = invocation->class_();
|
||||
PROTECT(t, c);
|
||||
|
||||
GcCharArray* bootstrapArray = cast<GcCharArray>(
|
||||
t,
|
||||
cast<GcArray>(t, c->addendum()->bootstrapMethodTable())
|
||||
->body()[invocation->bootstrap()]);
|
||||
|
||||
PROTECT(t, bootstrapArray);
|
||||
|
||||
GcMethod* bootstrap = cast<GcMethod>(t,
|
||||
resolve(t,
|
||||
c->loader(),
|
||||
invocation->pool(),
|
||||
bootstrapArray->body()[0],
|
||||
findMethodInClass,
|
||||
GcNoSuchMethodError::Type));
|
||||
PROTECT(t, bootstrap);
|
||||
|
||||
assertT(t, bootstrap->parameterCount() == 2 + bootstrapArray->length());
|
||||
|
||||
GcLookup* lookup
|
||||
= makeLookup(t, c, ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC);
|
||||
PROTECT(t, lookup);
|
||||
|
||||
GcByteArray* nameBytes = invocation->template_()->name();
|
||||
GcString* name
|
||||
= t->m->classpath->makeString(t, nameBytes, 0, nameBytes->length() - 1);
|
||||
PROTECT(t, name);
|
||||
|
||||
GcMethodType* type = makeMethodType(
|
||||
t, c->loader(), invocation->template_()->spec(), 0, 0, 0);
|
||||
PROTECT(t, type);
|
||||
|
||||
GcArray* array = makeArray(t, bootstrap->parameterCount());
|
||||
PROTECT(t, array);
|
||||
|
||||
unsigned argument = 0;
|
||||
array->setBodyElement(t, argument++, lookup);
|
||||
array->setBodyElement(t, argument++, name);
|
||||
array->setBodyElement(t, argument++, type);
|
||||
|
||||
MethodSpecIterator it(
|
||||
t, reinterpret_cast<const char*>(bootstrap->spec()->body().begin()));
|
||||
|
||||
for (unsigned i = 0; i < argument; ++i)
|
||||
it.next();
|
||||
|
||||
unsigned i = 0;
|
||||
while (it.hasNext()) {
|
||||
const char* p = it.next();
|
||||
switch (*p) {
|
||||
case 'L': {
|
||||
const char* const methodType = "Ljava/lang/invoke/MethodType;";
|
||||
const char* const methodHandle = "Ljava/lang/invoke/MethodHandle;";
|
||||
if (strncmp(p, methodType, strlen(methodType)) == 0) {
|
||||
GcMethodType* type = makeMethodType(
|
||||
t,
|
||||
c->loader(),
|
||||
cast<GcByteArray>(
|
||||
t,
|
||||
singletonObject(
|
||||
t, invocation->pool(), bootstrapArray->body()[i + 1])),
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
|
||||
array->setBodyElement(t, i + argument, type);
|
||||
} else if (strncmp(p, methodHandle, strlen(methodHandle)) == 0) {
|
||||
GcReference* reference = cast<GcReference>(
|
||||
t,
|
||||
singletonObject(
|
||||
t, invocation->pool(), bootstrapArray->body()[i + 1]));
|
||||
int kind = reference->kind();
|
||||
|
||||
GcMethod* method = cast<GcMethod>(t,
|
||||
resolve(t,
|
||||
c->loader(),
|
||||
invocation->pool(),
|
||||
bootstrapArray->body()[i + 1],
|
||||
findMethodInClass,
|
||||
GcNoSuchMethodError::Type));
|
||||
|
||||
GcMethodHandle* handle
|
||||
= makeMethodHandle(t, kind, c->loader(), method, 0);
|
||||
|
||||
array->setBodyElement(t, i + argument, handle);
|
||||
} else {
|
||||
abort(t);
|
||||
}
|
||||
} break;
|
||||
|
||||
case 'I':
|
||||
case 'F': {
|
||||
GcInt* box = makeInt(
|
||||
t,
|
||||
singletonValue(t, invocation->pool(), bootstrapArray->body()[i + 1]));
|
||||
|
||||
array->setBodyElement(t, i + argument, box);
|
||||
} break;
|
||||
|
||||
case 'J':
|
||||
case 'D': {
|
||||
uint64_t v;
|
||||
memcpy(
|
||||
&v,
|
||||
&singletonValue(t, invocation->pool(), bootstrapArray->body()[i + 1]),
|
||||
8);
|
||||
|
||||
GcLong* box = makeLong(t, v);
|
||||
|
||||
array->setBodyElement(t, i + argument, box);
|
||||
} break;
|
||||
|
||||
default:
|
||||
abort(t);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
GcMethodHandle* handle
|
||||
= (bootstrap->flags() & ACC_STATIC)
|
||||
? 0
|
||||
: makeMethodHandle(t, REF_invokeSpecial, c->loader(), bootstrap, 0);
|
||||
|
||||
return cast<GcCallSite>(
|
||||
t, t->m->processor->invokeArray(t, bootstrap, handle, array));
|
||||
}
|
||||
|
||||
void* linkDynamicMethod2(MyThread* t, unsigned index)
|
||||
{
|
||||
GcInvocation* invocation
|
||||
|
@ -1981,6 +1981,34 @@ loop:
|
||||
}
|
||||
goto loop;
|
||||
|
||||
case invokedynamic: {
|
||||
uint16_t index = codeReadInt16(t, code, ip);
|
||||
|
||||
ip += 2;
|
||||
|
||||
GcInvocation* invocation = cast<GcInvocation>(t, singletonObject(t, code->pool(), index - 1));
|
||||
|
||||
GcCallSite* site = invocation->site();
|
||||
|
||||
loadMemoryBarrier();
|
||||
|
||||
if (site == 0) {
|
||||
PROTECT(t, invocation);
|
||||
|
||||
invocation->setClass(t, frameMethod(t, frame)->class_());
|
||||
|
||||
site = resolveDynamic(t, invocation);
|
||||
PROTECT(t, site);
|
||||
|
||||
storeStoreMemoryBarrier();
|
||||
|
||||
invocation->setSite(t, site);
|
||||
site->setInvocation(t, invocation);
|
||||
}
|
||||
|
||||
method = site->target()->method();
|
||||
} goto invoke;
|
||||
|
||||
case invokeinterface: {
|
||||
uint16_t index = codeReadInt16(t, code, ip);
|
||||
|
||||
|
134
src/machine.cpp
134
src/machine.cpp
@ -6032,6 +6032,140 @@ GcJclass* getDeclaringClass(Thread* t, GcClass* c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
GcCallSite* resolveDynamic(Thread* t, GcInvocation* invocation)
|
||||
{
|
||||
PROTECT(t, invocation);
|
||||
|
||||
GcClass* c = invocation->class_();
|
||||
PROTECT(t, c);
|
||||
|
||||
GcCharArray* bootstrapArray = cast<GcCharArray>(
|
||||
t,
|
||||
cast<GcArray>(t, c->addendum()->bootstrapMethodTable())
|
||||
->body()[invocation->bootstrap()]);
|
||||
|
||||
PROTECT(t, bootstrapArray);
|
||||
|
||||
GcMethod* bootstrap = cast<GcMethod>(t,
|
||||
resolve(t,
|
||||
c->loader(),
|
||||
invocation->pool(),
|
||||
bootstrapArray->body()[0],
|
||||
findMethodInClass,
|
||||
GcNoSuchMethodError::Type));
|
||||
PROTECT(t, bootstrap);
|
||||
|
||||
assertT(t, bootstrap->parameterCount() == 2 + bootstrapArray->length());
|
||||
|
||||
GcLookup* lookup
|
||||
= makeLookup(t, c, ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC);
|
||||
PROTECT(t, lookup);
|
||||
|
||||
GcByteArray* nameBytes = invocation->template_()->name();
|
||||
GcString* name
|
||||
= t->m->classpath->makeString(t, nameBytes, 0, nameBytes->length() - 1);
|
||||
PROTECT(t, name);
|
||||
|
||||
GcMethodType* type = makeMethodType(
|
||||
t, c->loader(), invocation->template_()->spec(), 0, 0, 0);
|
||||
PROTECT(t, type);
|
||||
|
||||
GcArray* array = makeArray(t, bootstrap->parameterCount());
|
||||
PROTECT(t, array);
|
||||
|
||||
unsigned argument = 0;
|
||||
array->setBodyElement(t, argument++, lookup);
|
||||
array->setBodyElement(t, argument++, name);
|
||||
array->setBodyElement(t, argument++, type);
|
||||
|
||||
MethodSpecIterator it(
|
||||
t, reinterpret_cast<const char*>(bootstrap->spec()->body().begin()));
|
||||
|
||||
for (unsigned i = 0; i < argument; ++i)
|
||||
it.next();
|
||||
|
||||
unsigned i = 0;
|
||||
while (it.hasNext()) {
|
||||
const char* p = it.next();
|
||||
switch (*p) {
|
||||
case 'L': {
|
||||
const char* const methodType = "Ljava/lang/invoke/MethodType;";
|
||||
const char* const methodHandle = "Ljava/lang/invoke/MethodHandle;";
|
||||
if (strncmp(p, methodType, strlen(methodType)) == 0) {
|
||||
GcMethodType* type = makeMethodType(
|
||||
t,
|
||||
c->loader(),
|
||||
cast<GcByteArray>(
|
||||
t,
|
||||
singletonObject(
|
||||
t, invocation->pool(), bootstrapArray->body()[i + 1])),
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
|
||||
array->setBodyElement(t, i + argument, type);
|
||||
} else if (strncmp(p, methodHandle, strlen(methodHandle)) == 0) {
|
||||
GcReference* reference = cast<GcReference>(
|
||||
t,
|
||||
singletonObject(
|
||||
t, invocation->pool(), bootstrapArray->body()[i + 1]));
|
||||
int kind = reference->kind();
|
||||
|
||||
GcMethod* method = cast<GcMethod>(t,
|
||||
resolve(t,
|
||||
c->loader(),
|
||||
invocation->pool(),
|
||||
bootstrapArray->body()[i + 1],
|
||||
findMethodInClass,
|
||||
GcNoSuchMethodError::Type));
|
||||
|
||||
GcMethodHandle* handle
|
||||
= makeMethodHandle(t, kind, c->loader(), method, 0);
|
||||
|
||||
array->setBodyElement(t, i + argument, handle);
|
||||
} else {
|
||||
abort(t);
|
||||
}
|
||||
} break;
|
||||
|
||||
case 'I':
|
||||
case 'F': {
|
||||
GcInt* box = makeInt(
|
||||
t,
|
||||
singletonValue(t, invocation->pool(), bootstrapArray->body()[i + 1]));
|
||||
|
||||
array->setBodyElement(t, i + argument, box);
|
||||
} break;
|
||||
|
||||
case 'J':
|
||||
case 'D': {
|
||||
uint64_t v;
|
||||
memcpy(
|
||||
&v,
|
||||
&singletonValue(t, invocation->pool(), bootstrapArray->body()[i + 1]),
|
||||
8);
|
||||
|
||||
GcLong* box = makeLong(t, v);
|
||||
|
||||
array->setBodyElement(t, i + argument, box);
|
||||
} break;
|
||||
|
||||
default:
|
||||
abort(t);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
GcMethodHandle* handle
|
||||
= (bootstrap->flags() & ACC_STATIC)
|
||||
? 0
|
||||
: makeMethodHandle(t, REF_invokeSpecial, c->loader(), bootstrap, 0);
|
||||
|
||||
return cast<GcCallSite>(
|
||||
t, t->m->processor->invokeArray(t, bootstrap, handle, array));
|
||||
}
|
||||
|
||||
void noop()
|
||||
{
|
||||
}
|
||||
|
@ -18,7 +18,9 @@ public class InvokeDynamic {
|
||||
Operation op = (a, b) -> a + b - c;
|
||||
expect(op.operate(2, 3) == (2 + 3) - 4);
|
||||
|
||||
new InvokeDynamic(3).test();
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
new InvokeDynamic(i).test();
|
||||
}
|
||||
}
|
||||
|
||||
private void test() {
|
||||
|
Loading…
Reference in New Issue
Block a user