mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +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);
|
GcJclass* getDeclaringClass(Thread* t, GcClass* c);
|
||||||
|
|
||||||
|
GcCallSite* resolveDynamic(Thread* t, GcInvocation* invocation);
|
||||||
|
|
||||||
inline bool emptyMethod(Thread* t UNUSED, GcMethod* method)
|
inline bool emptyMethod(Thread* t UNUSED, GcMethod* method)
|
||||||
{
|
{
|
||||||
return ((method->flags() & ACC_NATIVE) == 0)
|
return ((method->flags() & ACC_NATIVE) == 0)
|
||||||
|
136
src/compile.cpp
136
src/compile.cpp
@ -58,7 +58,7 @@ namespace {
|
|||||||
|
|
||||||
namespace local {
|
namespace local {
|
||||||
|
|
||||||
const bool DebugCompile = true;
|
const bool DebugCompile = false;
|
||||||
const bool DebugNatives = false;
|
const bool DebugNatives = false;
|
||||||
const bool DebugCallTable = false;
|
const bool DebugCallTable = false;
|
||||||
const bool DebugMethodTree = false;
|
const bool DebugMethodTree = false;
|
||||||
@ -7278,140 +7278,6 @@ uint64_t compileVirtualMethod(MyThread* t)
|
|||||||
return reinterpret_cast<uintptr_t>(compileVirtualMethod2(t, class_, index));
|
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)
|
void* linkDynamicMethod2(MyThread* t, unsigned index)
|
||||||
{
|
{
|
||||||
GcInvocation* invocation
|
GcInvocation* invocation
|
||||||
|
@ -1981,6 +1981,34 @@ loop:
|
|||||||
}
|
}
|
||||||
goto 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: {
|
case invokeinterface: {
|
||||||
uint16_t index = codeReadInt16(t, code, ip);
|
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;
|
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()
|
void noop()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,9 @@ public class InvokeDynamic {
|
|||||||
Operation op = (a, b) -> a + b - c;
|
Operation op = (a, b) -> a + b - c;
|
||||||
expect(op.operate(2, 3) == (2 + 3) - 4);
|
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() {
|
private void test() {
|
||||||
|
Loading…
Reference in New Issue
Block a user