add support for openjdk=$JDK8_HOME

All tests pass for the process=compile build.  Next step: process=interpret.
This commit is contained in:
Joel Dice
2015-08-06 13:24:06 -06:00
parent 2465459079
commit 8a7944d25c
12 changed files with 247 additions and 139 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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_;
}