mirror of
https://github.com/corda/corda.git
synced 2025-01-01 02:36:44 +00:00
add support for openjdk=$JDK8_HOME
All tests pass for the process=compile build. Next step: process=interpret.
This commit is contained in:
parent
2465459079
commit
8a7944d25c
@ -1,6 +1,9 @@
|
||||
language: cpp
|
||||
cache: apt
|
||||
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
@ -45,6 +45,8 @@ public class Classes {
|
||||
|
||||
public static native VMClass toVMClass(Class c);
|
||||
|
||||
public static native VMMethod toVMMethod(Method m);
|
||||
|
||||
private static native VMClass resolveVMClass(ClassLoader loader, byte[] spec)
|
||||
throws ClassNotFoundException;
|
||||
|
||||
|
@ -155,7 +155,19 @@ public class LambdaMetafactory {
|
||||
write1(out, p.position() + 1);
|
||||
}
|
||||
|
||||
write1(out, invokestatic);
|
||||
switch (implementation.kind) {
|
||||
case MethodHandle.REF_invokeStatic:
|
||||
write1(out, invokestatic);
|
||||
break;
|
||||
|
||||
case MethodHandle.REF_invokeSpecial:
|
||||
write1(out, invokespecial);
|
||||
break;
|
||||
|
||||
default: throw new AssertionError
|
||||
("todo: implement per http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.3.5");
|
||||
}
|
||||
|
||||
write2(out, ConstantPool.addMethodRef
|
||||
(pool,
|
||||
Classes.makeString(implementation.method.class_.name, 0,
|
||||
@ -213,11 +225,9 @@ public class LambdaMetafactory {
|
||||
try {
|
||||
methodTable.add
|
||||
(new MethodData
|
||||
(Modifier.STATIC,
|
||||
(Modifier.PUBLIC | Modifier.STATIC,
|
||||
ConstantPool.addUtf8(pool, "make"),
|
||||
ConstantPool.addUtf8(pool, Classes.makeString
|
||||
(invokedType.spec, 0,
|
||||
invokedType.spec.length - 1)),
|
||||
ConstantPool.addUtf8(pool, invokedType.toMethodDescriptorString()),
|
||||
makeFactoryCode(pool, className, constructorSpec, invokedType)));
|
||||
|
||||
methodTable.add
|
||||
@ -231,9 +241,7 @@ public class LambdaMetafactory {
|
||||
(new MethodData
|
||||
(Modifier.PUBLIC,
|
||||
ConstantPool.addUtf8(pool, invokedName),
|
||||
ConstantPool.addUtf8(pool, Classes.makeString
|
||||
(methodType.spec, 0,
|
||||
methodType.spec.length - 1)),
|
||||
ConstantPool.addUtf8(pool, methodType.toMethodDescriptorString()),
|
||||
makeInvocationCode(pool, className, constructorSpec, invokedType,
|
||||
methodType, methodImplementation)));
|
||||
} catch (IOException e) {
|
||||
@ -262,10 +270,11 @@ public class LambdaMetafactory {
|
||||
try {
|
||||
return new CallSite
|
||||
(new MethodHandle
|
||||
(invokedType.loader, avian.SystemClassLoader.getClass
|
||||
(avian.Classes.defineVMClass
|
||||
(invokedType.loader, classData, 0, classData.length))
|
||||
.getMethod("make", invokedType.parameterArray()).vmMethod));
|
||||
(MethodHandle.REF_invokeStatic, invokedType.loader, Classes.toVMMethod
|
||||
(avian.SystemClassLoader.getClass
|
||||
(avian.Classes.defineVMClass
|
||||
(invokedType.loader, classData, 0, classData.length))
|
||||
.getMethod("make", invokedType.parameterArray()))));
|
||||
} catch (NoSuchMethodException e) {
|
||||
AssertionError error = new AssertionError();
|
||||
error.initCause(e);
|
||||
|
@ -1,18 +1,35 @@
|
||||
package java.lang.invoke;
|
||||
|
||||
import avian.Classes;
|
||||
|
||||
public class MethodHandle {
|
||||
static final int REF_invokeStatic = 6;
|
||||
static final int REF_invokeSpecial = 7;
|
||||
|
||||
final int kind;
|
||||
private final ClassLoader loader;
|
||||
final avian.VMMethod method;
|
||||
private volatile MethodType type;
|
||||
|
||||
MethodHandle(ClassLoader loader, avian.VMMethod method) {
|
||||
MethodHandle(int kind, ClassLoader loader, avian.VMMethod method) {
|
||||
this.kind = kind;
|
||||
this.loader = loader;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return new java.lang.reflect.Method(method).toString();
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (method.class_ != null) {
|
||||
sb.append(Classes.makeString(method.class_.name, 0,
|
||||
method.class_.name.length - 1));
|
||||
sb.append(".");
|
||||
}
|
||||
sb.append(Classes.makeString(method.name, 0,
|
||||
method.name.length - 1));
|
||||
sb.append(Classes.makeString(method.spec, 0,
|
||||
method.spec.length - 1));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public MethodType type() {
|
||||
if (type == null) {
|
||||
|
@ -2,12 +2,18 @@ package java.lang.invoke;
|
||||
|
||||
import static avian.Assembler.*;
|
||||
|
||||
import avian.Assembler;
|
||||
import avian.Classes;
|
||||
import avian.VMClass;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public final class MethodType implements java.io.Serializable {
|
||||
private static final char[] Primitives = new char[] {
|
||||
'V', 'Z', 'B', 'C', 'S', 'I', 'F', 'J', 'D'
|
||||
};
|
||||
|
||||
final ClassLoader loader;
|
||||
final byte[] spec;
|
||||
private volatile List<Parameter> parameters;
|
||||
@ -19,6 +25,77 @@ public final class MethodType implements java.io.Serializable {
|
||||
this.spec = spec;
|
||||
}
|
||||
|
||||
public String toMethodDescriptorString() {
|
||||
return Classes.makeString(spec, 0, spec.length - 1);
|
||||
}
|
||||
|
||||
private static String spec(Class c) {
|
||||
if (c.isPrimitive()) {
|
||||
VMClass vmc = Classes.toVMClass(c);
|
||||
for (char p: Primitives) {
|
||||
if (vmc == Classes.primitiveClass(p)) {
|
||||
return String.valueOf(p);
|
||||
}
|
||||
}
|
||||
throw new AssertionError();
|
||||
} else if (c.isArray()) {
|
||||
return "[" + spec(c.getComponentType());
|
||||
} else {
|
||||
return "L" + c.getName().replace('.', '/') + ";";
|
||||
}
|
||||
}
|
||||
|
||||
private MethodType(Class rtype,
|
||||
Class ... ptypes)
|
||||
{
|
||||
loader = rtype.getClassLoader();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('(');
|
||||
parameters = new ArrayList(ptypes.length);
|
||||
int position = 0;
|
||||
for (int i = 0; i < ptypes.length; ++i) {
|
||||
String spec = spec(ptypes[i]);
|
||||
sb.append(spec);
|
||||
|
||||
Type type = type(spec);
|
||||
|
||||
parameters.add(new Parameter(i,
|
||||
position,
|
||||
spec,
|
||||
ptypes[i],
|
||||
type.load));
|
||||
|
||||
position += type.size;
|
||||
}
|
||||
sb.append(')');
|
||||
|
||||
footprint = position;
|
||||
|
||||
String spec = spec(rtype);
|
||||
sb.append(spec);
|
||||
|
||||
result = new Result(spec, rtype, type(spec).return_);
|
||||
|
||||
this.spec = sb.toString().getBytes();
|
||||
}
|
||||
|
||||
public static MethodType methodType(Class rtype,
|
||||
Class ptype0,
|
||||
Class ... ptypes)
|
||||
{
|
||||
Class[] array = new Class[ptypes.length + 1];
|
||||
array[0] = ptype0;
|
||||
System.arraycopy(ptypes, 0, array, 1, ptypes.length);
|
||||
return methodType(rtype, array);
|
||||
}
|
||||
|
||||
public static MethodType methodType(Class rtype,
|
||||
Class ... ptypes)
|
||||
{
|
||||
return new MethodType(rtype, ptypes);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return Classes.makeString(spec, 0, spec.length - 1);
|
||||
}
|
||||
@ -53,21 +130,14 @@ public final class MethodType implements java.io.Serializable {
|
||||
int index = 0;
|
||||
int position = 0;
|
||||
for (i = 1; spec[i] != ')'; ++i) {
|
||||
int start = i;
|
||||
switch (spec[i]) {
|
||||
case 'L': {
|
||||
int start = i;
|
||||
++ i;
|
||||
while (spec[i] != ';') ++ i;
|
||||
|
||||
list.add(new Parameter
|
||||
(index,
|
||||
position,
|
||||
Classes.makeString(spec, start, (i - start) + 1),
|
||||
aload));
|
||||
} break;
|
||||
|
||||
case '[': {
|
||||
int start = i;
|
||||
++ i;
|
||||
while (spec[i] == '[') ++ i;
|
||||
|
||||
@ -80,12 +150,6 @@ public final class MethodType implements java.io.Serializable {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
list.add(new Parameter
|
||||
(index,
|
||||
position,
|
||||
Classes.makeString(spec, start, (i - start) + 1),
|
||||
aload));
|
||||
} break;
|
||||
|
||||
case 'Z':
|
||||
@ -93,107 +157,38 @@ public final class MethodType implements java.io.Serializable {
|
||||
case 'S':
|
||||
case 'C':
|
||||
case 'I':
|
||||
list.add(new Parameter
|
||||
(index,
|
||||
position,
|
||||
Classes.makeString(spec, i, 1),
|
||||
iload));
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
list.add(new Parameter
|
||||
(index,
|
||||
position,
|
||||
Classes.makeString(spec, i, 1),
|
||||
fload));
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
list.add(new Parameter
|
||||
(index,
|
||||
position,
|
||||
Classes.makeString(spec, i, 1),
|
||||
lload));
|
||||
|
||||
++ position;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
list.add(new Parameter
|
||||
(index,
|
||||
position,
|
||||
Classes.makeString(spec, i, 1),
|
||||
dload));
|
||||
|
||||
++ position;
|
||||
break;
|
||||
|
||||
default: throw new AssertionError();
|
||||
}
|
||||
|
||||
String paramSpec = Classes.makeString(spec, start, (i - start) + 1);
|
||||
Type type = type(paramSpec);
|
||||
|
||||
list.add(new Parameter
|
||||
(index,
|
||||
position,
|
||||
paramSpec,
|
||||
Classes.forCanonicalName(loader, paramSpec),
|
||||
type.load));
|
||||
|
||||
++ index;
|
||||
++ position;
|
||||
position += type.size;
|
||||
}
|
||||
|
||||
footprint = position;
|
||||
|
||||
++ i;
|
||||
|
||||
switch (spec[i]) {
|
||||
case 'L': {
|
||||
int start = i;
|
||||
++ i;
|
||||
while (spec[i] != ';') ++ i;
|
||||
|
||||
result = new Result
|
||||
(Classes.makeString(spec, start, (i - start) + 1), areturn);
|
||||
} break;
|
||||
|
||||
case '[': {
|
||||
int start = i;
|
||||
++ i;
|
||||
while (spec[i] == '[') ++ i;
|
||||
|
||||
switch (spec[i]) {
|
||||
case 'L':
|
||||
++ i;
|
||||
while (spec[i] != ';') ++ i;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
result = new Result(Classes.makeString(spec, start, (i - start) + 1),
|
||||
areturn);
|
||||
} break;
|
||||
|
||||
case 'V':
|
||||
result = new Result(Classes.makeString(spec, i, 1), return_);
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
case 'B':
|
||||
case 'S':
|
||||
case 'C':
|
||||
case 'I':
|
||||
result = new Result(Classes.makeString(spec, i, 1), ireturn);
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
result = new Result(Classes.makeString(spec, i, 1), freturn);
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
result = new Result(Classes.makeString(spec, i, 1), lreturn);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
result = new Result(Classes.makeString(spec, i, 1), dreturn);
|
||||
break;
|
||||
|
||||
default: throw new AssertionError();
|
||||
}
|
||||
String paramSpec = Classes.makeString(spec, i, spec.length - i - 1);
|
||||
Type type = type(paramSpec);
|
||||
|
||||
result = new Result(paramSpec,
|
||||
Classes.forCanonicalName(loader, paramSpec),
|
||||
type.return_);
|
||||
|
||||
parameters = list;
|
||||
}
|
||||
@ -207,7 +202,55 @@ public final class MethodType implements java.io.Serializable {
|
||||
return result;
|
||||
}
|
||||
|
||||
public class Parameter {
|
||||
private static Type type(String spec) {
|
||||
switch (spec.charAt(0)) {
|
||||
case 'L':
|
||||
case '[':
|
||||
return Type.ObjectType;
|
||||
|
||||
case 'Z':
|
||||
case 'B':
|
||||
case 'S':
|
||||
case 'C':
|
||||
case 'I':
|
||||
return Type.IntegerType;
|
||||
|
||||
case 'F':
|
||||
return Type.FloatType;
|
||||
|
||||
case 'J':
|
||||
return Type.LongType;
|
||||
|
||||
case 'D':
|
||||
return Type.DoubleType;
|
||||
|
||||
case 'V':
|
||||
return Type.VoidType;
|
||||
|
||||
default: throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
private static enum Type {
|
||||
ObjectType(aload, areturn, 1),
|
||||
IntegerType(iload, ireturn, 1),
|
||||
FloatType(fload, freturn, 1),
|
||||
LongType(lload, lreturn, 1),
|
||||
DoubleType(dload, dreturn, 1),
|
||||
VoidType(-1, Assembler.return_, -1);
|
||||
|
||||
public final int load;
|
||||
public final int return_;
|
||||
public final int size;
|
||||
|
||||
private Type(int load, int return_, int size) {
|
||||
this.load = load;
|
||||
this.return_ = return_;
|
||||
this.size = size;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Parameter {
|
||||
private final int index;
|
||||
private final int position;
|
||||
private final String spec;
|
||||
@ -217,12 +260,13 @@ public final class MethodType implements java.io.Serializable {
|
||||
private Parameter(int index,
|
||||
int position,
|
||||
String spec,
|
||||
Class type,
|
||||
int load)
|
||||
{
|
||||
this.index = index;
|
||||
this.position = position;
|
||||
this.spec = spec;
|
||||
this.type = Classes.forCanonicalName(loader, spec);
|
||||
this.type = type;
|
||||
this.load = load;
|
||||
}
|
||||
|
||||
@ -243,14 +287,14 @@ public final class MethodType implements java.io.Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
public class Result {
|
||||
public static class Result {
|
||||
private final String spec;
|
||||
private final Class type;
|
||||
private final int return_;
|
||||
|
||||
public Result(String spec, int return_) {
|
||||
public Result(String spec, Class type, int return_) {
|
||||
this.spec = spec;
|
||||
this.type = Classes.forCanonicalName(loader, spec);
|
||||
this.type = type;
|
||||
this.return_ = return_;
|
||||
}
|
||||
|
||||
|
@ -58,18 +58,6 @@ public class Method<T> extends AccessibleObject implements Member {
|
||||
private String getSpec() {
|
||||
return getSpec(vmMethod);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (vmMethod.class_ != null) {
|
||||
sb.append(Classes.makeString(vmMethod.class_.name, 0,
|
||||
vmMethod.class_.name.length - 1));
|
||||
sb.append(".");
|
||||
}
|
||||
sb.append(getName());
|
||||
sb.append(getSpec());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String getSpec(VMMethod vmMethod) {
|
||||
return Classes.makeString(vmMethod.spec, 0, vmMethod.spec.length - 1);
|
||||
|
7
makefile
7
makefile
@ -1473,7 +1473,12 @@ ifneq ($(classpath),avian)
|
||||
$(classpath-src)/avian/VMField.java \
|
||||
$(classpath-src)/avian/VMMethod.java \
|
||||
$(classpath-src)/avian/avianvmresource/Handler.java \
|
||||
$(classpath-src)/avian/file/Handler.java
|
||||
$(classpath-src)/avian/file/Handler.java \
|
||||
$(classpath-src)/java/lang/invoke/MethodHandle.java \
|
||||
$(classpath-src)/java/lang/invoke/MethodHandles.java \
|
||||
$(classpath-src)/java/lang/invoke/MethodType.java \
|
||||
$(classpath-src)/java/lang/invoke/LambdaMetafactory.java \
|
||||
$(classpath-src)/java/lang/invoke/CallSite.java
|
||||
|
||||
ifeq ($(openjdk),)
|
||||
classpath-sources := $(classpath-sources) \
|
||||
|
@ -263,6 +263,16 @@ const unsigned ACC_INTERFACE = 1 << 9;
|
||||
const unsigned ACC_ABSTRACT = 1 << 10;
|
||||
const unsigned ACC_STRICT = 1 << 11;
|
||||
|
||||
const unsigned REF_getField = 1;
|
||||
const unsigned REF_getStatic = 2;
|
||||
const unsigned REF_putField = 3;
|
||||
const unsigned REF_putStatic = 4;
|
||||
const unsigned REF_invokeVirtual = 5;
|
||||
const unsigned REF_invokeStatic = 6;
|
||||
const unsigned REF_invokeSpecial = 7;
|
||||
const unsigned REF_newInvokeSpecial = 8;
|
||||
const unsigned REF_invokeInterface = 9;
|
||||
|
||||
const int AVIAN_JNI_COMMIT = 1;
|
||||
const int AVIAN_JNI_ABORT = 2;
|
||||
|
||||
|
@ -113,6 +113,13 @@ extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
cast<GcJclass>(t, reinterpret_cast<object>(arguments[0]))->vmClass());
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT int64_t JNICALL
|
||||
Avian_avian_Classes_toVMMethod(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
return reinterpret_cast<intptr_t>(t->m->classpath->getVMMethod(
|
||||
t, cast<GcJmethod>(t, reinterpret_cast<object>(arguments[0]))));
|
||||
}
|
||||
|
||||
extern "C" AVIAN_EXPORT void JNICALL
|
||||
Avian_avian_Classes_initialize(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
|
@ -484,6 +484,7 @@ class MyClasspath : public Classpath {
|
||||
}
|
||||
|
||||
oarray = charArray;
|
||||
offset = 0;
|
||||
} else {
|
||||
expect(t, objectClass(t, oarray) == type(t, GcCharArray::Type));
|
||||
}
|
||||
|
@ -7351,6 +7351,12 @@ GcCallSite* resolveDynamic(MyThread* t, GcInvocation* invocation)
|
||||
|
||||
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(),
|
||||
@ -7359,7 +7365,8 @@ GcCallSite* resolveDynamic(MyThread* t, GcInvocation* invocation)
|
||||
findMethodInClass,
|
||||
GcNoSuchMethodError::Type));
|
||||
|
||||
GcMethodHandle* handle = makeMethodHandle(t, c->loader(), method, 0);
|
||||
GcMethodHandle* handle
|
||||
= makeMethodHandle(t, kind, c->loader(), method, 0);
|
||||
|
||||
array->setBodyElement(t, i + argument, handle);
|
||||
} else {
|
||||
@ -7396,9 +7403,10 @@ GcCallSite* resolveDynamic(MyThread* t, GcInvocation* invocation)
|
||||
++i;
|
||||
}
|
||||
|
||||
GcMethodHandle* handle = (bootstrap->flags() & ACC_STATIC)
|
||||
? 0
|
||||
: makeMethodHandle(t, c->loader(), bootstrap, 0);
|
||||
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));
|
||||
|
@ -1,4 +1,10 @@
|
||||
public class InvokeDynamic {
|
||||
private final int foo;
|
||||
|
||||
private InvokeDynamic(int foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
private interface Operation {
|
||||
int operate(int a, int b);
|
||||
}
|
||||
@ -10,6 +16,14 @@ public class InvokeDynamic {
|
||||
public static void main(String[] args) {
|
||||
int c = 4;
|
||||
Operation op = (a, b) -> a + b - c;
|
||||
expect(op.operate(2, 3) == 1);
|
||||
expect(op.operate(2, 3) == (2 + 3) - 4);
|
||||
|
||||
new InvokeDynamic(3).test();
|
||||
}
|
||||
|
||||
private void test() {
|
||||
int c = 2;
|
||||
Operation op = (a, b) -> ((a + b) * c) - foo;
|
||||
expect(op.operate(2, 3) == ((2 + 3) * 2) - foo);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user