Minimizes amount of generated code to represent virtual methods

This commit is contained in:
konsoletyper 2014-03-02 11:02:09 +04:00
parent 04de57627f
commit a2d9663901
2 changed files with 55 additions and 37 deletions

View File

@ -228,6 +228,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
} }
writer.ws().append("});").newLine().outdent(); writer.ws().append("});").newLine().outdent();
List<MethodNode> nonInitMethods = new ArrayList<>(); List<MethodNode> nonInitMethods = new ArrayList<>();
List<MethodNode> virtualMethods = new ArrayList<>();
if (!cls.getModifiers().contains(NodeModifier.INTERFACE)) { if (!cls.getModifiers().contains(NodeModifier.INTERFACE)) {
writer.append("function ").appendClass(cls.getName()).append("_$clinit()").ws() writer.append("function ").appendClass(cls.getName()).append("_$clinit()").ws()
.append("{").softNewLine().indent(); .append("{").softNewLine().indent();
@ -252,8 +253,10 @@ public class Renderer implements ExprVisitor, StatementVisitor {
writer.outdent().append("}").newLine(); writer.outdent().append("}").newLine();
for (MethodNode method : cls.getMethods()) { for (MethodNode method : cls.getMethods()) {
cls.getMethods(); cls.getMethods();
if (!method.getModifiers().contains(NodeModifier.STATIC) || method.isOriginalNamePreserved()) { if (!method.getModifiers().contains(NodeModifier.STATIC)) {
renderDeclaration(method); virtualMethods.add(method);
} else if (method.isOriginalNamePreserved()) {
renderStaticDeclaration(method);
} }
} }
if (stubNames.size() > 0) { if (stubNames.size() > 0) {
@ -271,6 +274,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
for (MethodNode method : nonInitMethods) { for (MethodNode method : nonInitMethods) {
renderBody(method, false); renderBody(method, false);
} }
renderVirtualDeclarations(cls.getName(), virtualMethods);
} catch (NamingException e) { } catch (NamingException e) {
throw new RenderingException("Error rendering class " + cls.getName() + ". See a cause for details", e); throw new RenderingException("Error rendering class " + cls.getName() + ". See a cause for details", e);
} catch (IOException e) { } catch (IOException e) {
@ -327,45 +331,46 @@ public class Renderer implements ExprVisitor, StatementVisitor {
writer.outdent().append("}").newLine(); writer.outdent().append("}").newLine();
} }
public void renderDeclaration(MethodNode method) throws RenderingException, IOException { private void renderVirtualDeclarations(String className, List<MethodNode> methods)
try { throws NamingException, IOException {
if (method.getModifiers().contains(NodeModifier.STATIC)) { for (MethodNode method : methods) {
renderStaticDeclaration(method); MethodReference ref = method.getReference();
if (ref.getDescriptor().getName().equals("<init>")) {
renderInitializer(method);
}
}
if (methods.isEmpty()) {
return;
}
writer.append("$rt_virtualMethods(").appendClass(className).indent();
for (MethodNode method : methods) {
MethodReference ref = method.getReference();
writer.append(",").newLine();
if (method.isOriginalNamePreserved()) {
writer.append("[\"").appendMethod(ref).append("\",").ws().append("\"").append(ref.getName())
.append("\"]");
} else { } else {
renderVirtualDeclaration(method); writer.append("\"").appendMethod(ref).append("\"");
} }
} catch (NamingException e) { writer.append(",").ws().append("function(");
throw new RenderingException("Error rendering method " + method.getReference() + ". " + for (int i = 1; i <= ref.parameterCount(); ++i) {
"See cause for details", e); if (i > 1) {
} writer.append(",").ws();
} }
writer.append(variableName(i));
private void renderVirtualDeclaration(MethodNode method) throws NamingException, IOException {
MethodReference ref = method.getReference();
if (ref.getDescriptor().getName().equals("<init>")) {
renderInitializer(method);
}
writer.appendClass(ref.getClassName()).append(".prototype.").appendMethod(ref)
.ws().append("=").ws().append("function(");
for (int i = 1; i <= ref.parameterCount(); ++i) {
if (i > 1) {
writer.append(", ");
} }
writer.append(variableName(i)); writer.append(")").ws().append("{").ws();
} if (ref.getDescriptor().getResultType() != ValueType.VOID) {
writer.append(")").ws().append("{").softNewLine().indent(); writer.append("return ");
writer.append("return ").appendMethodBody(ref).append("("); }
writer.append("this"); writer.appendMethodBody(ref).append("(");
for (int i = 1; i <= ref.parameterCount(); ++i) { writer.append("this");
writer.append(",").ws().append(variableName(i)); for (int i = 1; i <= ref.parameterCount(); ++i) {
} writer.append(",").ws().append(variableName(i));
writer.append(");").softNewLine(); }
writer.outdent().append("}").newLine(); writer.append(");").ws().append("}");
if (method.isOriginalNamePreserved()) {
writer.appendClass(ref.getClassName()).append(".prototype.").append(ref.getName()).ws().append("=")
.ws().appendClass(ref.getClassName()).append(".prototype.").appendMethod(ref)
.append(';').newLine();
} }
writer.append(");").newLine().outdent();
} }
private void renderStaticDeclaration(MethodNode method) throws NamingException, IOException { private void renderStaticDeclaration(MethodNode method) throws NamingException, IOException {

View File

@ -387,6 +387,19 @@ function $rt_declClass(cls, data) {
cls.prototype.constructor = cls; cls.prototype.constructor = cls;
cls.$clinit = data.clinit; cls.$clinit = data.clinit;
} }
function $rt_virtualMethods(cls) {
for (var i = 1; i < arguments.length; i += 2) {
var name = arguments[i];
var func = arguments[i + 1];
if (typeof name == 'string') {
cls.prototype[name] = func;
} else {
for (var j = 0; j < name.length; ++j) {
cls.prototype[name[j]] = func;
}
}
}
}
Long = function(lo, hi) { Long = function(lo, hi) {
this.lo = lo | 0; this.lo = lo | 0;