mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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.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()) {
|
||||
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;
|
||||
|
||||
public JCLComparisonVisitor(ClassReaderSource classSource, Map<String, JCLPackage> packageMap) {
|
||||
super(Opcodes.ASM5);
|
||||
super(Opcodes.ASM7);
|
||||
this.classSource = classSource;
|
||||
this.packageMap = packageMap;
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public class Parser {
|
|||
}
|
||||
|
||||
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]));
|
||||
JSRInlinerAdapter adapter = new JSRInlinerAdapter(nodeWithoutJsr, node.access, node.name, node.desc,
|
||||
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)
|
||||
private MethodVisitor methodVisitor = new MethodVisitor(Opcodes.ASM5) {
|
||||
private MethodVisitor methodVisitor = new MethodVisitor(Opcodes.ASM7) {
|
||||
@Override
|
||||
public void visitVarInsn(int opcode, int local) {
|
||||
switch (opcode) {
|
||||
|
|
|
@ -206,7 +206,7 @@ final class TeaVMPluginReader {
|
|||
PluginDescriptor descriptor;
|
||||
|
||||
public PluginDescriptorFiller(PluginDescriptor descriptor) {
|
||||
super(Opcodes.ASM5);
|
||||
super(Opcodes.ASM7);
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
|
@ -223,12 +223,12 @@ final class TeaVMPluginReader {
|
|||
}
|
||||
|
||||
private AnnotationVisitor readClassArray(Consumer<String[]> resultConsumer) {
|
||||
return new AnnotationVisitor(Opcodes.ASM5) {
|
||||
return new AnnotationVisitor(Opcodes.ASM7) {
|
||||
@Override
|
||||
public AnnotationVisitor visitArray(String name) {
|
||||
List<String> values = new ArrayList<>();
|
||||
if (name.equals("value")) {
|
||||
return new AnnotationVisitor(Opcodes.ASM5) {
|
||||
return new AnnotationVisitor(Opcodes.ASM7) {
|
||||
@Override
|
||||
public void visit(String name, Object value) {
|
||||
values.add(((Type) value).getClassName());
|
||||
|
|
|
@ -129,7 +129,7 @@ public class MetaprogrammingClassLoader extends ClassLoader {
|
|||
boolean compileTime;
|
||||
|
||||
CompileTimeClassVisitor() {
|
||||
super(Opcodes.ASM5, null);
|
||||
super(Opcodes.ASM7, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -46,7 +46,7 @@ public class MetaprogrammingInstrumentation {
|
|||
|
||||
class ClassTransformer extends ClassVisitor {
|
||||
ClassTransformer(ClassVisitor cv) {
|
||||
super(Opcodes.ASM5, cv);
|
||||
super(Opcodes.ASM7, cv);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -60,7 +60,7 @@ public class MetaprogrammingInstrumentation {
|
|||
private boolean instrumented;
|
||||
|
||||
MethodTransformer(MethodVisitor mv) {
|
||||
super(Opcodes.ASM5, mv);
|
||||
super(Opcodes.ASM7, mv);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
13
pom.xml
13
pom.xml
|
@ -71,7 +71,8 @@
|
|||
<selenium.version>2.47.2</selenium.version>
|
||||
<jackson.version>2.6.2</jackson.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>
|
||||
|
||||
<teavm.test.incremental>false</teavm.test.incremental>
|
||||
|
@ -216,16 +217,16 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.7.0</version>
|
||||
<version>3.8.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.0.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>build-javadoc</id>
|
||||
|
@ -289,7 +290,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>2.5.3</version>
|
||||
<version>4.1.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
|
|
@ -162,6 +162,16 @@ public class VMTest {
|
|||
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
|
||||
public void variableReadInCatchBlock() {
|
||||
int n = foo();
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-plugin-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<version>3.6.0</version>
|
||||
<configuration>
|
||||
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
|
||||
<goalPrefix>teavm</goalPrefix>
|
||||
|
|
Loading…
Reference in New Issue
Block a user