JS: reduce size of declaration of classes without fields

This commit is contained in:
Alexey Andreev 2020-03-03 12:47:06 +03:00
parent c1891a1908
commit 146776ff55
3 changed files with 81 additions and 34 deletions

View File

@ -129,6 +129,17 @@ class NameFrequencyEstimator extends RecursiveVisitor implements MethodNodeVisit
for (String iface : cls.getClassHolder().getInterfaces()) {
consumer.consume(iface);
}
boolean hasFields = false;
for (FieldHolder field : cls.getClassHolder().getFields()) {
if (!field.hasModifier(ElementModifier.STATIC)) {
hasFields = true;
break;
}
}
if (!hasFields) {
consumer.consumeFunction("$rt_classWithoutFields");
}
}
@Override

View File

@ -252,7 +252,8 @@ public class Renderer implements RenderingManager {
"$rt_isInstance", "$rt_nativeThread", "$rt_suspending", "$rt_resuming", "$rt_invalidPointer",
"$rt_s", "$rt_eraseClinit", "$rt_imul", "$rt_wrapException", "$rt_checkBounds",
"$rt_checkUpperBound", "$rt_checkLowerBound", "$rt_wrapFunction0", "$rt_wrapFunction1",
"$rt_wrapFunction2", "$rt_wrapFunction3", "$rt_wrapFunction4" };
"$rt_wrapFunction2", "$rt_wrapFunction3", "$rt_wrapFunction4",
"$rt_classWithoutFields" };
boolean first = true;
for (String name : names) {
if (!first) {
@ -303,10 +304,6 @@ public class Renderer implements RenderingManager {
ScopedName jsName = naming.getNameFor(cls.getName());
debugEmitter.addClass(jsName.value, cls.getName(), cls.getParentName());
try {
renderFunctionDeclaration(jsName);
writer.append("()").ws().append("{")
.indent().softNewLine();
boolean thisAliased = false;
List<FieldHolder> nonStaticFields = new ArrayList<>();
List<FieldHolder> staticFields = new ArrayList<>();
for (FieldHolder field : cls.getClassHolder().getFields()) {
@ -316,6 +313,45 @@ public class Renderer implements RenderingManager {
nonStaticFields.add(field);
}
}
if (nonStaticFields.isEmpty() && !cls.getClassHolder().getName().equals("java.lang.Object")) {
renderShortClassFunctionDeclaration(cls, jsName);
} else {
renderFullClassFunctionDeclaration(cls, jsName, nonStaticFields);
}
for (FieldHolder field : staticFields) {
Object value = field.getInitialValue();
if (value == null) {
value = getDefaultValue(field.getType());
}
FieldReference fieldRef = new FieldReference(cls.getName(), field.getName());
if (value instanceof String) {
context.lookupString((String) value);
postponedFieldInitializers.add(new PostponedFieldInitializer(fieldRef, (String) value));
value = null;
}
ScopedName fieldName = naming.getFullNameFor(fieldRef);
if (fieldName.scoped) {
writer.append(naming.getScopeName()).append(".");
} else {
writer.append("var ");
}
writer.append(fieldName.value).ws().append("=").ws();
context.constantToString(writer, value);
writer.append(";").softNewLine();
}
} catch (IOException e) {
throw new RenderingException("IO error occurred", e);
}
}
private void renderFullClassFunctionDeclaration(PreparedClass cls, ScopedName jsName,
List<FieldHolder> nonStaticFields) throws IOException {
boolean thisAliased = false;
renderFunctionDeclaration(jsName);
writer.append("()").ws().append("{").indent().softNewLine();
if (nonStaticFields.size() > 1) {
thisAliased = true;
writer.append("var a").ws().append("=").ws().append("this;").ws();
@ -347,32 +383,21 @@ public class Renderer implements RenderingManager {
writer.append(";");
}
writer.newLine();
for (FieldHolder field : staticFields) {
Object value = field.getInitialValue();
if (value == null) {
value = getDefaultValue(field.getType());
}
FieldReference fieldRef = new FieldReference(cls.getName(), field.getName());
if (value instanceof String) {
context.lookupString((String) value);
postponedFieldInitializers.add(new PostponedFieldInitializer(fieldRef, (String) value));
value = null;
}
ScopedName fieldName = naming.getFullNameFor(fieldRef);
if (fieldName.scoped) {
private void renderShortClassFunctionDeclaration(PreparedClass cls, ScopedName jsName) throws IOException {
if (jsName.scoped) {
writer.append(naming.getScopeName()).append(".");
} else {
writer.append("var ");
}
writer.append(fieldName.value).ws().append("=").ws();
context.constantToString(writer, value);
writer.append(";").softNewLine();
}
} catch (IOException e) {
throw new RenderingException("IO error occurred", e);
writer.append(jsName.value).ws().append("=").ws().appendFunction("$rt_classWithoutFields").append("(");
if (cls.getClassHolder().hasModifier(ElementModifier.INTERFACE)) {
writer.append("0");
} else if (!cls.getParentName().equals("java.lang.Object")) {
writer.appendClass(cls.getParentName());
}
writer.append(");").newLine();
}
private void renderMethodBodies(PreparedClass cls) throws RenderingException {

View File

@ -700,3 +700,14 @@ function $rt_checkLowerBound(index) {
}
return index;
}
function $rt_classWithoutFields(superclass) {
if (superclass === 0) {
return function() {};
}
if (superclass === void 0) {
superclass = $rt_objcls();
}
return function() {
superclass.call(this);
};
}