mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
JS: merge let statements to get better minification; rewrite some Array methods to generate less dependencies on runtime
This commit is contained in:
parent
717bbf4a57
commit
21137c57a3
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.lang.reflect;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Set;
|
||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||
import org.teavm.backend.javascript.spi.Generator;
|
||||
import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||
|
@ -31,6 +33,55 @@ public class ArrayNativeGenerator implements Generator {
|
|||
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
|
||||
if (methodRef.getName().equals("newInstanceImpl")) {
|
||||
generateNewInstance(context, writer);
|
||||
return;
|
||||
}
|
||||
template.builder(methodRef.getName()).withContext(context).build().write(writer, 0);
|
||||
}
|
||||
|
||||
private void generateNewInstance(GeneratorContext context, SourceWriter writer) {
|
||||
var dependency = context.getDependency().getMethod(new MethodReference(Array.class, "newInstance", Class.class,
|
||||
int.class, Object.class));
|
||||
template.builder("newInstanceImpl")
|
||||
.withContext(context)
|
||||
.withFragment("primitiveArrays", (w, p) -> {
|
||||
w.append("switch").ws().append("(").append(context.getParameterName(1)).append(")")
|
||||
.appendBlockStart();
|
||||
var length = context.getParameterName(2);
|
||||
var types = Set.of(dependency.getResult().getTypes());
|
||||
if (types.contains("[Z")) {
|
||||
writeArrayClause(w, "$rt_booleanArrayCls", "$rt_createBooleanArray", length);
|
||||
}
|
||||
if (types.contains("[B")) {
|
||||
writeArrayClause(w, "$rt_byteArrayCls", "$rt_createByteArray", length);
|
||||
}
|
||||
if (types.contains("[C")) {
|
||||
writeArrayClause(w, "$rt_charArrayCls", "$rt_createCharArray", length);
|
||||
}
|
||||
if (types.contains("[S")) {
|
||||
writeArrayClause(w, "$rt_shortArrayCls", "$rt_createShortArray", length);
|
||||
}
|
||||
if (types.contains("[I")) {
|
||||
writeArrayClause(w, "$rt_intArrayCls", "$rt_createIntArray", length);
|
||||
}
|
||||
if (types.contains("[J")) {
|
||||
writeArrayClause(w, "$rt_longArrayCls", "$rt_createLongArray", length);
|
||||
}
|
||||
if (types.contains("~F")) {
|
||||
writeArrayClause(w, "$rt_floatArrayCls", "$rt_createFloatArray", length);
|
||||
}
|
||||
if (types.contains("~D")) {
|
||||
writeArrayClause(w, "$rt_doubleArrayCls", "$rt_createDoubleArray", length);
|
||||
}
|
||||
w.appendBlockEnd();
|
||||
})
|
||||
.build()
|
||||
.write(writer, 0);
|
||||
}
|
||||
|
||||
private void writeArrayClause(SourceWriter writer, String test, String construct, String length) {
|
||||
writer.append("case ").appendFunction(test).append(":").ws().append("return ")
|
||||
.appendFunction(construct).append("(").append(length).append(");").softNewLine();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,16 +23,7 @@ function getLength(array) {
|
|||
|
||||
function newInstanceImpl(type, length) {
|
||||
if (type.$meta.primitive) {
|
||||
switch (type) {
|
||||
case $rt_booleanArrayCls: return $rt_createBooleanArray(length);
|
||||
case $rt_byteArrayCls: return $rt_createByteArray(length);
|
||||
case $rt_shortArrayCls: return $rt_createShortArray(length);
|
||||
case $rt_charArrayCls: return $rt_createCharArray(length);
|
||||
case $rt_intArrayCls: return $rt_createIntArray(length);
|
||||
case $rt_longArrayCls: return $rt_createLongArray(length);
|
||||
case $rt_floatArrayCls: return $rt_createFloatArray(length);
|
||||
case $rt_doubleArrayCls: return $rt_createDoubleArray(length);
|
||||
}
|
||||
teavm_fragment("primitiveArrays");
|
||||
}
|
||||
return $rt_createArray(type, length);
|
||||
}
|
||||
|
|
|
@ -343,17 +343,9 @@ public class Renderer implements RenderingManager {
|
|||
if (clinit != null && context.isDynamicInitializer(cls.getName())) {
|
||||
renderCallClinit(clinit, cls);
|
||||
}
|
||||
if (!cls.hasModifier(ElementModifier.INTERFACE)
|
||||
&& !cls.hasModifier(ElementModifier.ABSTRACT)) {
|
||||
for (var method : cls.getMethods()) {
|
||||
if (!method.hasModifier(ElementModifier.STATIC)) {
|
||||
if (method.getName().equals("<init>")) {
|
||||
renderInitializer(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var needsInitializers = !cls.hasModifier(ElementModifier.INTERFACE)
|
||||
&& !cls.hasModifier(ElementModifier.ABSTRACT);
|
||||
var hasLet = false;
|
||||
for (var method : cls.getMethods()) {
|
||||
if (!filterMethod(method)) {
|
||||
|
@ -366,6 +358,11 @@ public class Renderer implements RenderingManager {
|
|||
writer.append(",").newLine();
|
||||
}
|
||||
renderBody(method, decompiler);
|
||||
if (needsInitializers && !method.hasModifier(ElementModifier.STATIC)
|
||||
&& method.getName().equals("<init>")) {
|
||||
writer.append(",").newLine();
|
||||
renderInitializer(method);
|
||||
}
|
||||
}
|
||||
if (hasLet) {
|
||||
writer.append(";").newLine();
|
||||
|
@ -699,7 +696,7 @@ public class Renderer implements RenderingManager {
|
|||
private void renderInitializer(MethodReader method) {
|
||||
MethodReference ref = method.getReference();
|
||||
writer.emitMethod(ref.getDescriptor());
|
||||
writer.append("let ").appendInit(ref).ws().append("=").ws();
|
||||
writer.appendInit(ref).ws().append("=").ws();
|
||||
if (ref.parameterCount() != 1) {
|
||||
writer.append("(");
|
||||
}
|
||||
|
@ -724,8 +721,7 @@ public class Renderer implements RenderingManager {
|
|||
}
|
||||
writer.append(");").softNewLine();
|
||||
writer.append("return " + instanceName + ";").softNewLine();
|
||||
writer.outdent().append("};");
|
||||
writer.newLine();
|
||||
writer.outdent().append("}");
|
||||
writer.emitMethod(null);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.mozilla.javascript.ast.AstRoot;
|
|||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||
import org.teavm.backend.javascript.codegen.SourceWriterSink;
|
||||
import org.teavm.backend.javascript.templating.AstRemoval;
|
||||
import org.teavm.backend.javascript.templating.LetJoiner;
|
||||
import org.teavm.backend.javascript.templating.RemovablePartsFinder;
|
||||
import org.teavm.backend.javascript.templating.TemplatingAstTransformer;
|
||||
import org.teavm.backend.javascript.templating.TemplatingAstWriter;
|
||||
|
@ -105,11 +106,14 @@ public class RuntimeRenderer {
|
|||
|
||||
public void removeUnusedParts() {
|
||||
var removal = new AstRemoval(removablePartsFinder.getAllRemovableParts());
|
||||
var letJoiner = new LetJoiner();
|
||||
for (var part : runtimeAstParts) {
|
||||
removal.visit(part);
|
||||
letJoiner.visit(part);
|
||||
}
|
||||
for (var part : epilogueAstParts) {
|
||||
removal.visit(part);
|
||||
letJoiner.visit(part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright 2023 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.backend.javascript.templating;
|
||||
|
||||
import org.mozilla.javascript.ast.AstNode;
|
||||
import org.mozilla.javascript.ast.AstRoot;
|
||||
import org.mozilla.javascript.ast.Block;
|
||||
import org.mozilla.javascript.ast.FunctionNode;
|
||||
import org.mozilla.javascript.ast.IfStatement;
|
||||
import org.mozilla.javascript.ast.Scope;
|
||||
import org.mozilla.javascript.ast.VariableDeclaration;
|
||||
import org.teavm.backend.javascript.ast.AstVisitor;
|
||||
|
||||
public class LetJoiner extends AstVisitor {
|
||||
@Override
|
||||
public void visit(Block node) {
|
||||
visitMany(node);
|
||||
super.visit(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Scope node) {
|
||||
visitMany(node);
|
||||
super.visit(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(AstRoot node) {
|
||||
visitMany(node);
|
||||
super.visit(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(FunctionNode node) {
|
||||
visitMany(node.getBody());
|
||||
super.visit(node);
|
||||
}
|
||||
|
||||
private void visitMany(AstNode node) {
|
||||
VariableDeclaration previous = null;
|
||||
for (var childNode = node.getFirstChild(); childNode != null; ) {
|
||||
var nextNode = childNode.getNext();
|
||||
var child = (AstNode) childNode;
|
||||
if (child instanceof VariableDeclaration) {
|
||||
var decl = (VariableDeclaration) childNode;
|
||||
if (previous != null && previous.getType() == decl.getType()) {
|
||||
previous.getVariables().addAll(decl.getVariables());
|
||||
node.removeChild(decl);
|
||||
} else {
|
||||
previous = decl;
|
||||
}
|
||||
} else {
|
||||
previous = null;
|
||||
}
|
||||
childNode = nextNode;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -145,7 +145,7 @@ let $rt_arraycls = cls => {
|
|||
str += "]";
|
||||
return str;
|
||||
};
|
||||
$rt_setCloneMethod(JavaArray.prototype, function() {
|
||||
JavaArray.prototype[teavm_javaVirtualMethod('clone()Ljava/lang/Object;')] = function() {
|
||||
let dataCopy;
|
||||
if ('slice' in this.data) {
|
||||
dataCopy = this.data.slice();
|
||||
|
@ -156,7 +156,7 @@ let $rt_arraycls = cls => {
|
|||
}
|
||||
}
|
||||
return new ($rt_arraycls(this.type))(dataCopy);
|
||||
});
|
||||
};
|
||||
let name = "[" + cls.$meta.binaryName;
|
||||
JavaArray.$meta = {
|
||||
item: cls,
|
||||
|
@ -694,22 +694,8 @@ let $dbg_class = obj => {
|
|||
cls = cls.$meta.item;
|
||||
}
|
||||
let clsName = "";
|
||||
if (cls === $rt_booleancls) {
|
||||
clsName = "boolean";
|
||||
} else if (cls === $rt_bytecls) {
|
||||
clsName = "byte";
|
||||
} else if (cls === $rt_shortcls) {
|
||||
clsName = "short";
|
||||
} else if (cls === $rt_charcls) {
|
||||
clsName = "char";
|
||||
} else if (cls === $rt_intcls) {
|
||||
clsName = "int";
|
||||
} else if (cls === $rt_longcl) {
|
||||
clsName = "long";
|
||||
} else if (cls === $rt_floatcls) {
|
||||
clsName = "float";
|
||||
} else if (cls === $rt_doublecls) {
|
||||
clsName = "double";
|
||||
if (cls.$meta.primitive) {
|
||||
clsName = cls.$meta.name;
|
||||
} else {
|
||||
clsName = cls.$meta ? (cls.$meta.name || ("a/" + cls.name)) : "@" + cls.name;
|
||||
}
|
||||
|
@ -853,8 +839,6 @@ let $rt_substring = (string, start, end) => {
|
|||
}
|
||||
let $rt_substringSink = 0;
|
||||
|
||||
let $rt_setCloneMethod = (target, method) => target[teavm_javaVirtualMethod('clone()Ljava/lang/Object;')] = method;
|
||||
|
||||
let $rt_cls = (cls) => teavm_javaMethod("java.lang.Class",
|
||||
"getClass(Lorg/teavm/platform/PlatformClass;)Ljava/lang/Class;")(cls);
|
||||
let $rt_str = str => str === null ? null : teavm_javaConstructor("java.lang.String", "(Ljava/lang/Object;)V")(str);
|
||||
|
|
Loading…
Reference in New Issue
Block a user