Author: max
Date: 2007-08-30 14:00:06 -0700 (Thu, 30 Aug 2007)
New Revision: 6291
Modified:
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/kernel/dhtml/LzContextMenu.js
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/kernel/dhtml/LzInputTextSprite.js
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/kernel/dhtml/LzTextSprite.js
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
openlaszlo/branches/wafflecone/lps/includes/source/embednew.js
openlaszlo/branches/wafflecone/lps/includes/source/iframemanager.js
Log:
Change 20070830-maxcarlson-Y by [EMAIL PROTECTED] on 2007-08-30 13:30:47 PDT
in /Users/maxcarlson/openlaszlo/waffleconeclean
for http://svn.openlaszlo.org/openlaszlo/branches/wafflecone
Bugs Fixed:
LPP-4513 'Compiler Improvements to address performance'
Technical Reviewer: max
QA Reviewer:
Doc Reviewer: (pending)
Details:
This change was already reviewed and approved by Tucker.
CodeGenerator.java, JavascriptGenerator.java - Inline calls to
setAttribute() when called as the script compiler, unless #pragma
"passThrough=true". Only inline setAttribute when called as lzsc
(i.e., when compiling scripts such as LFC and lps/includes)
LzContextMenu.js, LzTextSprite.js, LzInputTextSprite.js,
embednew.js, iframemanager.js - Call Lz.__setAttr() instead of
div.setAttribute(...). Add __setAttr() method to be used so
div.setAttribute() isn't inlined.
Tests:
All demos run as before (but faster in swf and dhtml). smokecheck
also runs and passes now.
http://localhost:8080/wafflecone/my-apps/copy-of-hello.lzx is 62k
compressed in dhtml (was 60k), 92k compressed in swf7 (was 89k) and
93k compressed in swf8 (was 90k). This change will benefit animators
and alignment constraints now. We can always manually inline/optimize to
bring the size down later. I recommend taking this for now.
Modified:
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/kernel/dhtml/LzContextMenu.js
===================================================================
---
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/kernel/dhtml/LzContextMenu.js
2007-08-30 20:59:44 UTC (rev 6290)
+++
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/kernel/dhtml/LzContextMenu.js
2007-08-30 21:00:06 UTC (rev 6291)
@@ -57,8 +57,8 @@
var s = document.getElementById('lzcontextmenu')
if (! s) {
s = document.createElement('div');
- s.setAttribute('id', 'lzcontextmenu');
- s.setAttribute('style', 'display: none');
+ Lz.__setAttr(s, 'id', 'lzcontextmenu');
+ Lz.__setAttr(s, 'style', 'display: none');
document.body.appendChild(s);
}
if (this.onmenuopen.ready) this.onmenuopen.sendEvent(this);
Modified:
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/kernel/dhtml/LzInputTextSprite.js
===================================================================
---
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/kernel/dhtml/LzInputTextSprite.js
2007-08-30 20:59:44 UTC (rev 6290)
+++
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/kernel/dhtml/LzInputTextSprite.js
2007-08-30 21:00:06 UTC (rev 6291)
@@ -40,15 +40,15 @@
//Debug.write('Multiline', this, this.multiline, this.owner.multiline);
if (this.owner && this.owner.password) {
this.__LzInputDiv = document.createElement('input');
- this.__LzInputDiv.setAttribute('type', 'password');
+ Lz.__setAttr(this.__LzInputDiv, 'type', 'password');
} else if (this.owner && this.owner.multiline) {
this.__LzInputDiv = document.createElement('textarea');
} else {
this.__LzInputDiv = document.createElement('input');
- this.__LzInputDiv.setAttribute('type', 'text');
+ Lz.__setAttr(this.__LzInputDiv, 'type', 'text');
}
if (this.quirks.firefox_autocomplete_bug) {
- this.__LzInputDiv.setAttribute('autocomplete', 'off');
+ Lz.__setAttr(this.__LzInputDiv, 'autocomplete', 'off');
}
this.__LzInputDiv.owner = this;
if (this.quirks.emulate_flash_font_metrics) {
@@ -61,9 +61,11 @@
} else {
this.__LzInputDiv.className = 'lzinputtext';
}
- if (this.owner) this.__LzInputDiv.setAttribute('name', this.owner.name);
+ if (this.owner) {
+ Lz.__setAttr(this.__LzInputDiv, 'name', this.owner.name);
+ }
if (t == null) t = '';
- this.__LzInputDiv.setAttribute('value', t);
+ Lz.__setAttr(this.__LzInputDiv, 'value', t);
if (this.quirks.fix_clickable) {
if (this.quirks.fix_ie_clickable) {
this.__LZinputclickdiv = document.createElement('img');
Modified:
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/kernel/dhtml/LzTextSprite.js
===================================================================
--- openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/kernel/dhtml/LzTextSprite.js
2007-08-30 20:59:44 UTC (rev 6290)
+++ openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/kernel/dhtml/LzTextSprite.js
2007-08-30 21:00:06 UTC (rev 6291)
@@ -299,7 +299,7 @@
var mdiv = _textsizecache[tagname];
if (mdiv == null) {
mdiv = document.createElement(tagname);
- mdiv.setAttribute('style', style);
+ Lz.__setAttr(mdiv, 'style', style);
document.body.appendChild(mdiv);
_textsizecache[tagname] = mdiv;
}
Modified:
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java
===================================================================
---
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java
2007-08-30 20:59:44 UTC (rev 6290)
+++
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java
2007-08-30 21:00:06 UTC (rev 6291)
@@ -1833,6 +1833,31 @@
return false;
}
+ private static SimpleNode parseFragment(String code) {
+ if (code.equals("\"\"") || code == null) {
+ code = "";
+ }
+ code =
+ "{" +
+ "\n#pragma 'warnUndefinedReferences=false'\n" +
+ "\n#file CodeGenerator.parseFragment\n#line 0\n" +
+ code +
+ "}";
+ // Extract the statement list from the program
+ try {
+ return (new Compiler.Parser()).parse(code).get(0);
+ } catch (ParseException e) {
+ System.err.println("while compiling " + code);
+ throw e;
+ }
+ }
+
+ // TODO: [2007-08-20 ptw] Replace with Java 1.5 UUID
+ private Random rand = new Random();
+ private Integer UUID() {
+ return new Integer(rand.nextInt(Integer.MAX_VALUE));
+ }
+
public boolean visitCallExpression(SimpleNode node, boolean isReferenced,
SimpleNode[] children) {
SimpleNode fnexpr = children[0];
SimpleNode[] args = children[1].getChildren();
@@ -1926,70 +1951,83 @@
// them.
// FIXME: [2002-12-03 ptw] This substitution is not correct
// because it does not verify that the method being inlined is
- // actually ViewsystemNode.setAttribute.
- // TODO: [2004-03-29 ptw] Enable this optimization for swf 7 by
- // allocating some temp registers if it is worth it
- if (fnexpr instanceof ASTPropertyIdentifierReference &&
- "setAttribute".equals(((ASTIdentifier)fnexpr.get(1)).getName()) &&
- arglen == 2 &&
- (! options.getBoolean(Compiler.FLASH_COMPILER_COMPATABILITY)) &&
- (! options.getBoolean(Compiler.GENERATE_FUNCTION_2))) {
- Object[] onprop = new Instruction[]
- {Instructions.PUSH.make("on"),
- Instructions.PUSH.make(Values.Register(1)),
- Instructions.ADD};
- // Optimize literal property name
- // TODO: [2002-12-03 ptw] Should check for constant expression
- if (args[0] instanceof ASTLiteral) {
- Object v = translateLiteralNode(args[0]);
- if (v instanceof String) {
- onprop = new Instruction[]
- {Instructions.PUSH.make("on" + v)};
+ // actually LzNode.setAttribute.
+ if (
+ // Here this means 'compiling the lfc'
+ options.getBoolean(Compiler.FLASH_COMPILER_COMPATABILITY) &&
+ (! options.getBoolean("passThrough")) &&
+ (fnexpr instanceof ASTPropertyIdentifierReference)) {
+ SimpleNode[] fnchildren = fnexpr.getChildren();
+ String name = ((ASTIdentifier)fnchildren[1]).getName();
+ // We can't expand this if an expression value is expected,
+ // since we don't have 'let'
+ if (name.equals("setAttribute") && (! isReferenced)) {
+ SimpleNode scope = fnchildren[0];
+ SimpleNode property = args[0];
+ SimpleNode value = args[1];
+ List newBody = new ArrayList();
+ String thisvar = "$lzsc$" + UUID().toString();
+ String propvar = "$lzsc$" + UUID().toString();
+ String valvar = "$lzsc$" + UUID().toString();
+ String changedvar = "$lzsc$" + UUID().toString();
+ String svar = "$lzsc$" + UUID().toString();
+ String evtvar = "$lzsc$" + UUID().toString();
+ String decls = "";
+ Compiler.ParseTreePrinter ptp = new Compiler.ParseTreePrinter();
+ if (scope instanceof ASTIdentifier || scope instanceof
ASTThisReference) {
+ thisvar = ptp.visit(scope);
+ } else {
+ decls += "var " + thisvar + " = " + ptp.visit(scope) + ";";
}
+ if (property instanceof ASTLiteral || property instanceof
ASTIdentifier) {
+ propvar = ptp.visit(property);
+ if (property instanceof ASTLiteral) {
+ assert propvar.startsWith("\"") || propvar.startsWith("'");
+ evtvar = propvar.substring(0,1) + "on" + propvar.substring(1);
+ }
+ } else {
+ decls += "var " + propvar + " = " + ptp.visit(property) + ";";
+ }
+ if (value instanceof ASTLiteral || value instanceof ASTIdentifier) {
+ valvar = ptp.visit(value);
+ } else {
+ decls += "var " + valvar + " = " + ptp.visit(value) + ";";
+ }
+ if (arglen > 2) {
+ SimpleNode ifchanged = args[2];
+ if (ifchanged instanceof ASTLiteral || ifchanged instanceof
ASTIdentifier) {
+ changedvar = ptp.visit(ifchanged);
+ } else {
+ decls += "var " + changedvar + " = " + ptp.visit(ifchanged) + ";";
+ }
+ }
+ newBody.add(parseFragment(decls));
+ String fragment = "if (! (" + thisvar + ".__LZdeleted " +
+ ((arglen > 2) ? ("|| (" + changedvar + " && (" + thisvar + "[" +
propvar + "] == " + valvar + "))") : "") +
+ ")) {" +
+ "var " + svar + " = " + thisvar + ".setters;" +
+ "if (" + svar + " && (" + propvar + " in " + svar + ")) {" +
+ " " + thisvar + "[" + svar + "[" + propvar + "]](" + valvar +
");" +
+ "} else {" +
+ " if ($debug) {" +
+ " if (" + svar + " == null) {" +
+ " Debug.warn('null setters on', " + thisvar + ", " +
propvar + ", " + valvar + ");" +
+ " }" +
+ " }" +
+ " " + thisvar + "[ " + propvar + " ] = " + valvar + ";" +
+ ((property instanceof ASTLiteral) ? "" : (" var " + evtvar + " =
(\"on\" + " + propvar + ");")) +
+ " if (" + evtvar + " in " + thisvar + ") {" +
+ " if (" + thisvar + "[" + evtvar + "].ready) {" + thisvar +
"[ " + evtvar + " ].sendEvent( " + valvar + " ); }" +
+ " }" +
+ "}}";
+ newBody.add(parseFragment(fragment));
+ SimpleNode newStmts = new ASTStatementList(0);
+ newStmts.setChildren((SimpleNode[])newBody.toArray(new SimpleNode[0]));
+ visitStatement(newStmts);
+ return true;
}
- // exprs are evaluated first, in proper order, and
- // before any registers are set (as they might be
- // clobbered by expression evaluation).
- List code = new ArrayList(Arrays.asList(new Object[] {fnexpr.get(0), //
: obj
- Instructions.DUP, // : obj, obj
- args[0], // : obj, obj, prop
- args[1], // : obj, obj, prop,
val
-
Instructions.SetRegister.make(3), // r3 = val
- Instructions.POP, // : obj, obj,
prop
-
Instructions.SetRegister.make(1), // r1 = prop
- Instructions.SWAP, // : obj,
prop, obj
-
Instructions.PUSH.make("setters"), // : obj, prop, obj, setters
- Instructions.GetMember, // :
obj, prop, obj.setters
- Instructions.SWAP, // : obj,
obj.setters, prop
- Instructions.GetMember, // :
obj, obj.setters[prop]
-
Instructions.SetRegister.make(2), // r2 = obj.setters[prop]
-
Instructions.PUSH.make(Values.Null), // : obj, obj.setters[prop], null
- Instructions.EQUALS, // : obj,
null == obj.setters[prop]
-
Instructions.BranchIfTrue.make(0), // : obj
-
Instructions.SetRegister.make(0), // r0 = obj
- Instructions.POP, // :
-
Instructions.PUSH.make(Values.Register(3)), // : val
- Instructions.PUSH.make(1), // :
val, 1
-
Instructions.PUSH.make(Values.Register(0)), // : val, 1, obj
-
Instructions.PUSH.make(Values.Register(2)), // : val, 1, obj, setter
- Instructions.BRANCH.make(1),
- new Integer(0), // : obj
-
Instructions.SetRegister.make(0), // r0 = obj
-
Instructions.PUSH.make(Values.Register(1)), // : obj, prop
-
Instructions.PUSH.make(Values.Register(3)), // : obj, prop, val
- Instructions.SetMember, // :
-
Instructions.PUSH.make(Values.Register(3)), // : val
- Instructions.PUSH.make(1), // :
val, 1
-
Instructions.PUSH.make(Values.Register(0))}));
- code.addAll(Arrays.asList(onprop));
- code.addAll(Arrays.asList((new Object[] {Instructions.GetMember, // :
val, 1, obj["on"+prop]
- Instructions.PUSH.make("sendEvent"), // : val,
1, obj["on"+prop], "sendEvent"
- new Integer(1),
- Instructions.CallMethod, // : result
- Instructions.POP}))); // :
- translateControlStructure(node, code.toArray());
- return true; // no return value
}
+
visitCallParameters(node, isReferenced, args);
boolean isref = translateReferenceForCall(fnexpr, true, node);
if (isref) {
Modified:
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
===================================================================
---
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
2007-08-30 20:59:44 UTC (rev 6290)
+++
openlaszlo/branches/wafflecone/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
2007-08-30 21:00:06 UTC (rev 6291)
@@ -124,7 +124,10 @@
AssignOpTable.put(ParserConstants.RUNSIGNEDSHIFTASSIGN, ">>>");
};
- static SimpleNode parseFragment(String code) {
+ private static SimpleNode parseFragment(String code) {
+ if (code.equals("\"\"") || code == null) {
+ code = "";
+ }
code =
"{" +
"\n#pragma 'warnUndefinedReferences=false'\n" +
@@ -132,7 +135,12 @@
code +
"}";
// Extract the statement list from the program
- return (new Compiler.Parser()).parse(code).get(0);
+ try {
+ return (new Compiler.Parser()).parse(code).get(0);
+ } catch (ParseException e) {
+ System.err.println("while compiling " + code);
+ throw e;
+ }
}
// Code to meter a function call. If name is set, uses that,
@@ -1411,11 +1419,99 @@
return node;
}
+ // TODO: [2007-08-20 ptw] Replace with Java 1.5 UUID
+ private Random rand = new Random();
+ private Integer UUID() {
+ return new Integer(rand.nextInt(Integer.MAX_VALUE));
+ }
+
// Could do inline expansions here, like setAttribute
public SimpleNode visitCallExpression(SimpleNode node, boolean isReferenced,
SimpleNode[] children) {
SimpleNode fnexpr = children[0];
SimpleNode[] args = children[1].getChildren();
int arglen = args.length;
+
+ // TODO: [2002-12-03 ptw] There should be a more general
+ // mechanism for matching patterns against AST's and replacing
+ // them.
+ // FIXME: [2002-12-03 ptw] This substitution is not correct
+ // because it does not verify that the method being inlined is
+ // actually LzNode.setAttribute.
+ if (
+ // Here this means 'compiling the lfc'
+ options.getBoolean(Compiler.FLASH_COMPILER_COMPATABILITY) &&
+ (! options.getBoolean("passThrough")) &&
+ (fnexpr instanceof ASTPropertyIdentifierReference)) {
+ SimpleNode[] fnchildren = fnexpr.getChildren();
+ String name = ((ASTIdentifier)fnchildren[1]).getName();
+ // We can't expand this if an expression value is expected,
+ // since we don't have 'let'
+ if (name.equals("setAttribute") && (! isReferenced)) {
+ SimpleNode scope = fnchildren[0];
+ SimpleNode property = args[0];
+ SimpleNode value = args[1];
+ List newBody = new ArrayList();
+ String thisvar = "$lzsc$" + UUID().toString();
+ String propvar = "$lzsc$" + UUID().toString();
+ String valvar = "$lzsc$" + UUID().toString();
+ String changedvar = "$lzsc$" + UUID().toString();
+ String svar = "$lzsc$" + UUID().toString();
+ String evtvar = "$lzsc$" + UUID().toString();
+ String decls = "";
+ Compiler.ParseTreePrinter ptp = new Compiler.ParseTreePrinter();
+ if (scope instanceof ASTIdentifier || scope instanceof
ASTThisReference) {
+ thisvar = ptp.visit(scope);
+ } else {
+ decls += "var " + thisvar + " = " + ptp.visit(scope) + ";";
+ }
+ if (property instanceof ASTLiteral || property instanceof
ASTIdentifier) {
+ propvar = ptp.visit(property);
+ if (property instanceof ASTLiteral) {
+ assert propvar.startsWith("\"") || propvar.startsWith("'");
+ evtvar = propvar.substring(0,1) + "on" + propvar.substring(1);
+ }
+ } else {
+ decls += "var " + propvar + " = " + ptp.visit(property) + ";";
+ }
+ if (value instanceof ASTLiteral || value instanceof ASTIdentifier) {
+ valvar = ptp.visit(value);
+ } else {
+ decls += "var " + valvar + " = " + ptp.visit(value) + ";";
+ }
+ if (arglen > 2) {
+ SimpleNode ifchanged = args[2];
+ if (ifchanged instanceof ASTLiteral || ifchanged instanceof
ASTIdentifier) {
+ changedvar = ptp.visit(ifchanged);
+ } else {
+ decls += "var " + changedvar + " = " + ptp.visit(ifchanged) + ";";
+ }
+ }
+ newBody.add(parseFragment(decls));
+ String fragment = "if (! (" + thisvar + ".__LZdeleted " +
+ ((arglen > 2) ? ("|| (" + changedvar + " && (" + thisvar + "[" +
propvar + "] == " + valvar + "))") : "") +
+ ")) {" +
+ "var " + svar + " = " + thisvar + ".setters;" +
+ "if (" + svar + " && (" + propvar + " in " + svar + ")) {" +
+ " " + thisvar + "[" + svar + "[" + propvar + "]](" + valvar +
");" +
+ "} else {" +
+ " if ($debug) {" +
+ " if (" + svar + " == null) {" +
+ " Debug.warn('null setters on', " + thisvar + ", " +
propvar + ", " + valvar + ");" +
+ " }" +
+ " }" +
+ " " + thisvar + "[ " + propvar + " ] = " + valvar + ";" +
+ ((property instanceof ASTLiteral) ? "" : (" var " + evtvar + " =
(\"on\" + " + propvar + ");")) +
+ " if (" + evtvar + " in " + thisvar + ") {" +
+ " if (" + thisvar + "[" + evtvar + "].ready) {" + thisvar +
"[ " + evtvar + " ].sendEvent( " + valvar + " ); }" +
+ " }" +
+ "}}";
+ newBody.add(parseFragment(fragment));
+ SimpleNode newStmts = new ASTStatementList(0);
+ newStmts.setChildren((SimpleNode[])newBody.toArray(new SimpleNode[0]));
+ return visitStatement(newStmts);
+ }
+ }
+
children[1].setChildren(translateFunctionCallParameters(node,
isReferenced, args));
children[0] = translateReferenceForCall(fnexpr, true, node);
// if (options.getBoolean(Compiler.WARN_UNDEFINED_REFERENCES)) {
Modified: openlaszlo/branches/wafflecone/lps/includes/source/embednew.js
===================================================================
--- openlaszlo/branches/wafflecone/lps/includes/source/embednew.js
2007-08-30 20:59:44 UTC (rev 6290)
+++ openlaszlo/branches/wafflecone/lps/includes/source/embednew.js
2007-08-30 21:00:06 UTC (rev 6291)
@@ -210,8 +210,8 @@
,__dhtmlLoadLibrary: function (url) {
var o = document.createElement('script');
- o.setAttribute('type', 'text/javascript');
- o.setAttribute('src', url);
+ this.__setAttr(o, 'type', 'text/javascript');
+ this.__setAttr(o, 'src', url);
document.getElementsByTagName("head")[0].appendChild(o);
//alert(o);
return o;
@@ -280,6 +280,12 @@
return d;
}
+ ,/** @access private */
+ __setAttr: function(s, n, v) {
+#pragma "passThrough=true"
+ s.setAttribute(n, v);
+ }
+
,/**
* Check that the browser is a supported browser
*
Modified: openlaszlo/branches/wafflecone/lps/includes/source/iframemanager.js
===================================================================
--- openlaszlo/branches/wafflecone/lps/includes/source/iframemanager.js
2007-08-30 20:59:44 UTC (rev 6290)
+++ openlaszlo/branches/wafflecone/lps/includes/source/iframemanager.js
2007-08-30 21:00:06 UTC (rev 6291)
@@ -13,13 +13,13 @@
var id = '__lz' + Lz.iframemanager.__highestz++;
Lz.iframemanager.__frames[id] = i;
- i.setAttribute('id', id);
+ Lz.__setAttr(i, 'id', id);
if (name == null) name = '';
- if (name != "") i.setAttribute('name', name);
+ if (name != "") Lz.__setAttr(i, 'name', name);
i.__gotload = Lz.iframemanager.__gotload;
- i.setAttribute('onload', 'Lz.iframemanager.__gotload("' + id + '")');
+ Lz.__setAttr(i, 'onload', 'Lz.iframemanager.__gotload("' + id + '")');
if (appendto == null || appendto == "undefined") {
appendto = document.body;
}
@@ -29,8 +29,8 @@
if (document.getElementById && !(document.all) ) {
iframe.style.border = '0';
} else if (document.all) {
- iframe.setAttribute('frameborder', '0');
- iframe.setAttribute('allowtransparency', 'true');
+ Lz.__setAttr(iframe, 'frameborder', '0');
+ Lz.__setAttr(iframe, 'allowtransparency', 'true');
}
iframe.style.position = 'absolute';
return id;
@@ -42,7 +42,7 @@
//console.log('setSrc', id, s)
var iframe = Lz.iframemanager.getFrame(id);
if (! iframe) return;
- iframe.setAttribute('src', s);
+ Lz.__setAttr(iframe, 'src', s);
return true;
}
,setPosition: function(id, x, y, width, height, visible) {
_______________________________________________
Laszlo-checkins mailing list
[email protected]
http://www.openlaszlo.org/mailman/listinfo/laszlo-checkins