mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Support Java 11
This commit is contained in:
parent
d4b145a523
commit
064888c9a1
|
@ -73,6 +73,18 @@ public class JCLPlugin implements TeaVMPlugin {
|
||||||
ValueType.arrayOf(ValueType.object("java.lang.Object")),
|
ValueType.arrayOf(ValueType.object("java.lang.Object")),
|
||||||
ValueType.object("java.lang.invoke.CallSite")), lms);
|
ValueType.object("java.lang.invoke.CallSite")), lms);
|
||||||
|
|
||||||
|
StringConcatFactorySubstritutor stringConcatSubstitutor = new StringConcatFactorySubstritutor();
|
||||||
|
host.add(new MethodReference("java.lang.invoke.StringConcatFactory", "makeConcat",
|
||||||
|
ValueType.object("java.lang.invoke.MethodHandles$Lookup"), ValueType.object("java.lang.String"),
|
||||||
|
ValueType.object("java.lang.invoke.MethodType"), ValueType.object("java.lang.invoke.CallSite")),
|
||||||
|
stringConcatSubstitutor);
|
||||||
|
host.add(new MethodReference("java.lang.invoke.StringConcatFactory", "makeConcatWithConstants",
|
||||||
|
ValueType.object("java.lang.invoke.MethodHandles$Lookup"), ValueType.object("java.lang.String"),
|
||||||
|
ValueType.object("java.lang.invoke.MethodType"), ValueType.object("java.lang.String"),
|
||||||
|
ValueType.arrayOf(ValueType.object("java.lang.Object")),
|
||||||
|
ValueType.object("java.lang.invoke.CallSite")),
|
||||||
|
stringConcatSubstitutor);
|
||||||
|
|
||||||
if (!isBootstrap()) {
|
if (!isBootstrap()) {
|
||||||
host.add(new ScalaHacks());
|
host.add(new ScalaHacks());
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.impl;
|
||||||
|
|
||||||
|
import org.teavm.dependency.BootstrapMethodSubstitutor;
|
||||||
|
import org.teavm.dependency.DynamicCallSite;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.RuntimeConstant;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
import org.teavm.model.emit.ProgramEmitter;
|
||||||
|
import org.teavm.model.emit.ValueEmitter;
|
||||||
|
|
||||||
|
public class StringConcatFactorySubstritutor implements BootstrapMethodSubstitutor {
|
||||||
|
private static final String STRING_BUILDER = "java.lang.StringBuilder";
|
||||||
|
private static final char VALUE_ARGUMENT = '\1';
|
||||||
|
private static final char CONST_ARGUMENT = '\2';
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueEmitter substitute(DynamicCallSite callSite, ProgramEmitter pe) {
|
||||||
|
ValueEmitter sb = pe.construct(STRING_BUILDER);
|
||||||
|
|
||||||
|
if (callSite.getBootstrapMethod().getName().equals("makeConcatWithConstants")) {
|
||||||
|
appendArgumentWithRecipe(sb, callSite);
|
||||||
|
} else {
|
||||||
|
appendSimpleArguments(sb, callSite);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.invokeSpecial("toString", ValueType.object("java.lang.String"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueEmitter appendSimpleArguments(ValueEmitter sb, DynamicCallSite callSite) {
|
||||||
|
int parameterCount = callSite.getCalledMethod().parameterCount();
|
||||||
|
for (int i = 0; i < parameterCount; ++i) {
|
||||||
|
sb = appendArgument(sb, callSite.getCalledMethod().parameterType(i), callSite.getArguments().get(i));
|
||||||
|
}
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueEmitter appendArgumentWithRecipe(ValueEmitter sb, DynamicCallSite callSite) {
|
||||||
|
String recipe = callSite.getBootstrapArguments().get(0).getString();
|
||||||
|
int charCount = recipe.length();
|
||||||
|
int constantIndex = 0;
|
||||||
|
int valueIndex = 0;
|
||||||
|
int paramIndex = 0;
|
||||||
|
StringBuilder acc = new StringBuilder();
|
||||||
|
for (int i = 0; i < charCount; ++i) {
|
||||||
|
char c = recipe.charAt(i);
|
||||||
|
switch (c) {
|
||||||
|
case VALUE_ARGUMENT: {
|
||||||
|
sb = flushAcc(sb, acc);
|
||||||
|
ValueType type = callSite.getCalledMethod().parameterType(paramIndex++);
|
||||||
|
sb = appendArgument(sb, type, callSite.getArguments().get(valueIndex++));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONST_ARGUMENT: {
|
||||||
|
sb = flushAcc(sb, acc);
|
||||||
|
ValueType type = callSite.getCalledMethod().parameterType(paramIndex++);
|
||||||
|
RuntimeConstant poolConstant = callSite.getBootstrapArguments().get(1 + constantIndex++);
|
||||||
|
sb = appendArgument(sb, type, constant(sb.getProgramEmitter(), poolConstant));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
acc.append(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sb = flushAcc(sb, acc);
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueEmitter flushAcc(ValueEmitter sb, StringBuilder acc) {
|
||||||
|
if (acc.length() == 0) {
|
||||||
|
return sb;
|
||||||
|
} else if (acc.length() == 1) {
|
||||||
|
sb = appendArgument(sb, ValueType.CHARACTER, sb.getProgramEmitter().constant(acc.charAt(0))
|
||||||
|
.cast(ValueType.CHARACTER));
|
||||||
|
} else {
|
||||||
|
sb = appendArgument(sb, ValueType.object("java.lang.Object"),
|
||||||
|
sb.getProgramEmitter().constant(acc.toString()));
|
||||||
|
}
|
||||||
|
acc.setLength(0);
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueEmitter appendArgument(ValueEmitter sb, ValueType type, ValueEmitter argument) {
|
||||||
|
if (!(type instanceof ValueType.Primitive)) {
|
||||||
|
type = ValueType.object("java.lang.Object");
|
||||||
|
}
|
||||||
|
MethodReference method = new MethodReference(STRING_BUILDER, "append", type, ValueType.object(STRING_BUILDER));
|
||||||
|
return sb.invokeSpecial(method, argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueEmitter constant(ProgramEmitter pe, RuntimeConstant value) {
|
||||||
|
switch (value.getKind()) {
|
||||||
|
case RuntimeConstant.STRING:
|
||||||
|
return pe.constant(value.getString());
|
||||||
|
case RuntimeConstant.TYPE:
|
||||||
|
return pe.constant(value.getValueType());
|
||||||
|
case RuntimeConstant.INT:
|
||||||
|
return pe.constant(value.getInt());
|
||||||
|
case RuntimeConstant.LONG:
|
||||||
|
return pe.constant(value.getLong());
|
||||||
|
case RuntimeConstant.FLOAT:
|
||||||
|
return pe.constant(value.getFloat());
|
||||||
|
case RuntimeConstant.DOUBLE:
|
||||||
|
return pe.constant(value.getDouble());
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unsupported constant type: " + value.getKind());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ class JCLComparisonVisitor extends ClassVisitor {
|
||||||
private JCLClass jclClass;
|
private JCLClass jclClass;
|
||||||
|
|
||||||
public JCLComparisonVisitor(ClassReaderSource classSource, Map<String, JCLPackage> packageMap) {
|
public JCLComparisonVisitor(ClassReaderSource classSource, Map<String, JCLPackage> packageMap) {
|
||||||
super(Opcodes.ASM5);
|
super(Opcodes.ASM7);
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
this.packageMap = packageMap;
|
this.packageMap = packageMap;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ public class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodHolder parseMethod(MethodNode node, String fileName) {
|
public MethodHolder parseMethod(MethodNode node, String fileName) {
|
||||||
MethodNode nodeWithoutJsr = new MethodNode(Opcodes.ASM5, node.access, node.name, node.desc, node.signature,
|
MethodNode nodeWithoutJsr = new MethodNode(Opcodes.ASM7, node.access, node.name, node.desc, node.signature,
|
||||||
node.exceptions.toArray(new String[0]));
|
node.exceptions.toArray(new String[0]));
|
||||||
JSRInlinerAdapter adapter = new JSRInlinerAdapter(nodeWithoutJsr, node.access, node.name, node.desc,
|
JSRInlinerAdapter adapter = new JSRInlinerAdapter(nodeWithoutJsr, node.access, node.name, node.desc,
|
||||||
node.signature, node.exceptions.toArray(new String[0]));
|
node.signature, node.exceptions.toArray(new String[0]));
|
||||||
|
|
|
@ -435,7 +435,7 @@ public class ProgramParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: invokedynamic support (a great task, involving not only parser, but every layer of TeaVM)
|
// TODO: invokedynamic support (a great task, involving not only parser, but every layer of TeaVM)
|
||||||
private MethodVisitor methodVisitor = new MethodVisitor(Opcodes.ASM5) {
|
private MethodVisitor methodVisitor = new MethodVisitor(Opcodes.ASM7) {
|
||||||
@Override
|
@Override
|
||||||
public void visitVarInsn(int opcode, int local) {
|
public void visitVarInsn(int opcode, int local) {
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
|
|
|
@ -206,7 +206,7 @@ final class TeaVMPluginReader {
|
||||||
PluginDescriptor descriptor;
|
PluginDescriptor descriptor;
|
||||||
|
|
||||||
public PluginDescriptorFiller(PluginDescriptor descriptor) {
|
public PluginDescriptorFiller(PluginDescriptor descriptor) {
|
||||||
super(Opcodes.ASM5);
|
super(Opcodes.ASM7);
|
||||||
this.descriptor = descriptor;
|
this.descriptor = descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,12 +223,12 @@ final class TeaVMPluginReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private AnnotationVisitor readClassArray(Consumer<String[]> resultConsumer) {
|
private AnnotationVisitor readClassArray(Consumer<String[]> resultConsumer) {
|
||||||
return new AnnotationVisitor(Opcodes.ASM5) {
|
return new AnnotationVisitor(Opcodes.ASM7) {
|
||||||
@Override
|
@Override
|
||||||
public AnnotationVisitor visitArray(String name) {
|
public AnnotationVisitor visitArray(String name) {
|
||||||
List<String> values = new ArrayList<>();
|
List<String> values = new ArrayList<>();
|
||||||
if (name.equals("value")) {
|
if (name.equals("value")) {
|
||||||
return new AnnotationVisitor(Opcodes.ASM5) {
|
return new AnnotationVisitor(Opcodes.ASM7) {
|
||||||
@Override
|
@Override
|
||||||
public void visit(String name, Object value) {
|
public void visit(String name, Object value) {
|
||||||
values.add(((Type) value).getClassName());
|
values.add(((Type) value).getClassName());
|
||||||
|
|
|
@ -129,7 +129,7 @@ public class MetaprogrammingClassLoader extends ClassLoader {
|
||||||
boolean compileTime;
|
boolean compileTime;
|
||||||
|
|
||||||
CompileTimeClassVisitor() {
|
CompileTimeClassVisitor() {
|
||||||
super(Opcodes.ASM5, null);
|
super(Opcodes.ASM7, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -46,7 +46,7 @@ public class MetaprogrammingInstrumentation {
|
||||||
|
|
||||||
class ClassTransformer extends ClassVisitor {
|
class ClassTransformer extends ClassVisitor {
|
||||||
ClassTransformer(ClassVisitor cv) {
|
ClassTransformer(ClassVisitor cv) {
|
||||||
super(Opcodes.ASM5, cv);
|
super(Opcodes.ASM7, cv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -60,7 +60,7 @@ public class MetaprogrammingInstrumentation {
|
||||||
private boolean instrumented;
|
private boolean instrumented;
|
||||||
|
|
||||||
MethodTransformer(MethodVisitor mv) {
|
MethodTransformer(MethodVisitor mv) {
|
||||||
super(Opcodes.ASM5, mv);
|
super(Opcodes.ASM7, mv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
13
pom.xml
13
pom.xml
|
@ -71,7 +71,8 @@
|
||||||
<selenium.version>2.47.2</selenium.version>
|
<selenium.version>2.47.2</selenium.version>
|
||||||
<jackson.version>2.6.2</jackson.version>
|
<jackson.version>2.6.2</jackson.version>
|
||||||
<idea.version>2017.3.5</idea.version>
|
<idea.version>2017.3.5</idea.version>
|
||||||
<asm.version>6.1.1</asm.version>
|
<asm.version>7.0</asm.version>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
<rhino.version>1.7.7</rhino.version>
|
<rhino.version>1.7.7</rhino.version>
|
||||||
|
|
||||||
<teavm.test.incremental>false</teavm.test.incremental>
|
<teavm.test.incremental>false</teavm.test.incremental>
|
||||||
|
@ -216,16 +217,16 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.7.0</version>
|
<version>3.8.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>1.8</source>
|
<source>${java.version}</source>
|
||||||
<target>1.8</target>
|
<target>${java.version}</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<version>3.0.0</version>
|
<version>3.0.1</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>build-javadoc</id>
|
<id>build-javadoc</id>
|
||||||
|
@ -289,7 +290,7 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.felix</groupId>
|
<groupId>org.apache.felix</groupId>
|
||||||
<artifactId>maven-bundle-plugin</artifactId>
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
<version>2.5.3</version>
|
<version>4.1.0</version>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
|
|
@ -162,6 +162,16 @@ public class VMTest {
|
||||||
assertEquals("SECOND ", ClassWithStaticField.foo(false));
|
assertEquals("SECOND ", ClassWithStaticField.foo(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void stringConcat() {
|
||||||
|
assertEquals("(23)", surroundWithParentheses(23));
|
||||||
|
assertEquals("(42)", surroundWithParentheses(42));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String surroundWithParentheses(int value) {
|
||||||
|
return "(" + value + ")";
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void variableReadInCatchBlock() {
|
public void variableReadInCatchBlock() {
|
||||||
int n = foo();
|
int n = foo();
|
||||||
|
|
|
@ -85,7 +85,7 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-plugin-plugin</artifactId>
|
<artifactId>maven-plugin-plugin</artifactId>
|
||||||
<version>3.5.1</version>
|
<version>3.6.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
|
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
|
||||||
<goalPrefix>teavm</goalPrefix>
|
<goalPrefix>teavm</goalPrefix>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user