[Laszlo-checkins] r13797 - in openlaszlo/trunk/WEB-INF/lps: lfc/compiler lfc/events server/src/org/openlaszlo/sc
ptw@openlaszlo.org
ptw at openlaszlo.org
Sat May 2 05:37:44 PDT 2009
Author: ptw
Date: 2009-05-02 05:37:39 -0700 (Sat, 02 May 2009)
New Revision: 13797
Removed:
openlaszlo/trunk/WEB-INF/lps/lfc/compiler/platform/
Modified:
openlaszlo/trunk/WEB-INF/lps/lfc/compiler/Class.lzs
openlaszlo/trunk/WEB-INF/lps/lfc/events/LaszloEvents.lzs
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java
openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
Log:
Change 20090501-ptw-Y by ptw at dueling-banjos.home on 2009-05-01 18:33:57 EDT
in /Users/ptw/OpenLaszlo/trunk-2
for http://svn.openlaszlo.org/openlaszlo/trunk
Summary: Repair profiler for DHTML, tweak Class substrate
Bugs Fixed:
LPP-5637 profiler does not give class method belongs to in DHTML
LPP-8016 Performance differences between OL 4.0.x and 4.3.x (partial)
Technical Reviewer: a.bargull at intensis.de (Message-ID: <49FC2B75.20307 at udo.edu>)
QA Reviewer: max at openlaszlo.org (Message-ID: <49FBC976.8090100 at openlaszlo.org>)
Details:
LaszloEvents: Note class name on event
platform/js2/Instance.js: Remove unused
Class: Hoist the loop around addProperty into addProperties to
reduce function call overhead. Remove static initializers --
these were not supported by JS2 classes, so we no longer use
them. Remove validateClassStructure, no longer needed.
Hand-optimize `is` to `instanceof`, remove unnecessary `call` and
`apply`. Add some profiling names.
JavascriptGenerator, CodeGenerator: optimize profiling annotation
slightly.
JavascriptGenerator: Correct profiling function name annotation.
Tests:
Run the profiler in DHTML, see the class names. Notice slight
improvement in cost of addProperty.
Modified: openlaszlo/trunk/WEB-INF/lps/lfc/compiler/Class.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/compiler/Class.lzs 2009-05-02 05:05:01 UTC (rev 13796)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/compiler/Class.lzs 2009-05-02 12:37:39 UTC (rev 13797)
@@ -29,7 +29,6 @@
this.$lzsc$initialize.apply(this, arguments);
};
Instance.prototype.constructor = Instance;
-Instance.prototype.__initialized = false;
Instance.classname = 'Instance';
Instance.prototype.classname = 'Object';
if ($debug) {
@@ -53,16 +52,17 @@
* @access private
*/
(function () {
- var addProperty = function AddProperty (name, value) {
- if ((value !== void 0) || (! (name in this))) {
- this[name] = value;
-// } else if ($debug) {
-// for (var s = this.constructor; s !== Instance; s = s.prototype.constructor) {
-// if (s.prototype.hasOwnProperty(name)) { break; }
-// }
-// Debug.debug("Attempt to override %w.%s, already defined in %w", this, name, s);
- }
- if (value instanceof Function) {
+ var addProperties = function addProperties (plist) {
+ for (var i = plist.length - 1; i >= 1; i -= 2) {
+ var value = plist[i];
+ var name = plist[i - 1];
+
+ if ((value !== void 0) || (! (name in this))) {
+ this[name] = value;
+ }
+
+ if (! (value instanceof Function)) continue;
+
var xtor = this.constructor;
if (value.hasOwnProperty('superclasses')) {
var os = value.superclasses, found = false;
@@ -94,29 +94,50 @@
}
}
if ($profile) {
- if (! value._profile_name) {
+ if (! value.hasOwnProperty('_profile_name')) {
// `this` is the prototype of the class here, not the class
var o = this['_profile_typename'];
if (o) {
- value._profile_name = value._dbg_name = value.name = (o + '/' + value.name);
+ // Give the initializer an intelligible name for profiling
+ if (name == '$lzsc$initialize') {
+ var pn = o;
+ } else {
+ var pn = (o + '/' + name);
+ }
+ value._profile_name = value._dbg_name = value.name = pn;
}
}
}
}
};
// Bootstrap self
- addProperty.call(Instance.prototype, 'addProperty', addProperty);
+ addProperties.call(Instance.prototype, ['addProperties', addProperties]);
})();
/**
+ * Add a property to an instance
+ *
+ * If the property is a Function (method), annotates the method so
+ * nextMethod can find the next most applicable method
+ *
+ * @param String name: the name of the property
+ * @param value: the value of the property
+ *
+ * @access private
+ */
+Instance.prototype.addProperties(['addProperty', function addProperty(name, value) {
+ this.addProperties([name, value]);
+ }]);
+
+/**
* Find the next most applicable method
*
* Arguments are the current method and the name of the method you
* want. Returns the method. this.nextMethod(arguments.callee,
* 'aMethod').apply(this, arguments);
*
- * @param Function currentMethod: the method from which this is calle,
+ * @param Function currentMethod: the method from which this is callee,
* typically arguments.callee
* @param String nextMethodName: the method that is being looked for
* (can be other than the current method)
@@ -130,8 +151,9 @@
} else {
var superclasses = currentMethod.superclasses;
for (var i = superclasses.length - 1; i >= 0; i--) {
- if (this instanceof superclasses[i]) {
- next = superclasses[i].prototype[nextMethodName];
+ var sc = superclasses[i];
+ if (this instanceof sc) {
+ next = sc.prototype[nextMethodName];
break;
}
}
@@ -167,104 +189,15 @@
}
/**
- * Class initialize method
- *
- * Called by Class.make each time a class or subclass is made.
- * Argument is the prototype of the class. The class initializer
- * allows the class to initialize prototype properties with
- * non-constant values.
- *
- * Class initializers are invoked from least to most specific,
- * automatically by the Class.make method. They cannot be overridden.
- *
- * Default method does nothing
- *
- * @access private
- */
-Instance.initialize = function initialize (prototype) {
- // Scaffolding until the LFC is rewritten
- prototype.__initialized = false;
-};
-if ($debug) {
- Instance.initialize._dbg_typename = 'Instance static function';
-}
-if ($profile) {
- Instance.initialize._dbg_name = Instance.initialize.name = 'Instance.initialize';
-}
-
-if ($debug) {
- Instance.prototype.addProperty('validateClassStructure', function validateClassStructure () {
- // Verifies that superclass links for nextMethod are correct
- var prototype = this.constructor.prototype;
- do {
- var constructor = prototype.constructor;
- if (! prototype.__initialized) {
- // Debug.debug('Validating', constructor);
- for (var k in prototype) {
- if (prototype.hasOwnProperty(k) && k != 'constructor') {
- // Debug.debug(k);
- var value = prototype[k];
- // Cf., Instance.addProperty
- if (value instanceof Function) {
- // Don't whine about _dbg_ annotations
- if (k.indexOf('_dbg_') == 0) { continue; }
- if (value.hasOwnProperty('superclasses')) {
- var os = value.superclasses, found = false;
- for (var i = os.length - 1; i >= 0; i--) {
- if (os[i] === constructor) {
- found = true;
- break;
- }
- }
- if (! found) {
- value.superclasses.push(constructor);
- Debug.error('Invalid class structure [3+]: Use `addProperty` to create %w.%s', this, k);
- }
- } else if (value.hasOwnProperty('superclass')) {
- var o = value.superclass;
- if (o !== constructor) {
- delete value.superclass;
- value.superclasses = [ o, constructor ];
- Debug.error('Invalid class structure [2]: Use `addProperty` to create %w.%s', this, k);
- }
- } else {
- value.superclass = constructor;
- Debug.error('Invalid class structure [1]: Use `addProperty` to create %w.%s', this, k);
- }
- }
- }
- }
- prototype.__initialized = true;
- }
- prototype = constructor.prototype;
- } while (constructor !== Instance);
- });
-};
-
-/**
* Bootstrap Class class
* @todo [2006-05-03 ptw] Rename to Class when LFC has been converted
*/
var Class = {
prototype: new Instance(),
- // Add a method to a class by adding it to the class's prototype
- addProperty: function addProperty (name, value) {
- var proto = this.prototype;
- // TODO: [2006-09-28 ptw] Waiting for compiler support. Enable
- // this when the compiler allows you to declare your intent to
- // override
-// if (false /* not ok to override */) {
-// if ((name in proto) && (proto[name] !== value)) {
-// var over = proto;
-// while (over && (over.constructor !== Instance) && (! (over.constructor.prototype.hasOwnProperty(name)))) {
-// over = over.constructor.prototype;
-// }
-// Debug.debug("%s.prototype.%s (%w) overrides %s.prototype.%s (%w)",
-// this, name, value,
-// over.constructor, name, over.constructor.prototype[name]);
-// }
-// }
- proto.addProperty.apply(proto, arguments);
+ addProperty: Instance.prototype.addProperty,
+ // Add properties to a class by adding them to the class's prototype
+ addProperties: function addProperties (plist) {
+ this.prototype.addProperties(plist);
},
addStaticProperty: function addStaticProperty (name, value) {
// TODO: [2006-09-28 ptw] Waiting for compiler support. Enable
@@ -279,7 +212,7 @@
// }
this[name] = value;
if ($debug) {
- if (value is Function && (! value._dbg_typename)) {
+ if (value instanceof Function && (! value._dbg_typename)) {
value._dbg_owner = this;
value._dbg_typename = function _dbg_typename () {
return Debug.functionName(this._dbg_owner) + ' static function'
@@ -287,7 +220,7 @@
}
}
if ($profile) {
- if (value is Function && (! value._profile_name)) {
+ if (value instanceof Function && (! value._profile_name)) {
// Here `this` is the class
var o = this.prototype['_profile_typename'];
if (o) {
@@ -346,11 +279,6 @@
var nc = function constructor () {
// The constructor notes itself in every instance
this.constructor = arguments.callee;
- if ($debug) {
- // Must come after the constructor is installed
-// Debug.debug("Validate", this, this.validateClassStructure);
- this.validateClassStructure();
- }
// Call the initializer if it is not the default
if (this.$lzsc$initialize !== Instance.prototype.$lzsc$initialize) {
// Debug.debug('Initializing', this);
@@ -441,9 +369,10 @@
}
// Do this after installing the prototype, so profile names are correct
this.addStaticProperty.call(nc, 'addStaticProperty', this.addStaticProperty);
+ nc.addStaticProperty('addProperty', this.addProperty);
// NOTE: [2006-10-10 ptw] This could be inherited from the
// superclass, and hence overridable... not needed yet.
- nc.addStaticProperty('addProperty', this.addProperty);
+ nc.addStaticProperty('addProperties', this.addProperties);
// Install the staticProperties
if (staticProperties) {
for (var i = staticProperties.length - 1; i >= 1; i -= 2) {
@@ -454,30 +383,8 @@
}
// Class.initialize: Install initial values
if (instanceProperties) {
- for (var i = instanceProperties.length - 1; i >= 1; i -= 2) {
- var value = instanceProperties[i];
- var name = instanceProperties[i - 1];
- if ($profile) {
- // Give the initializer an intelligible name for profiling
- if ((name == '$lzsc$initialize') && (value is Function)) {
- value._dbg_name = value.name = prototype._profile_typename;
- }
- }
- nc.addProperty(name, value);
- }
+ nc.addProperties(instanceProperties);
}
- // Run class initializers from least to most specific
- (function classInit (prototype, constructor) {
- if (constructor !== Instance) {
- arguments.callee(prototype, constructor.prototype.constructor);
- }
- if (constructor.hasOwnProperty('initialize')) {
- // Apply the static initializer, so 'this' in the
- // initializer is the class whose prototype is
- // being initialized
- constructor.initialize.call(nc, prototype);
- }
- })(prototype, nc);
if ($debug) {
if (this.allClasses[classname]) {
Debug.error("Redefining %s from %w to %w", classname, this.allClasses[classname], nc);
@@ -492,12 +399,12 @@
};
if ($debug) {
- Class.addProperty._dbg_typename = 'Class static function';
+ Class.addProperties._dbg_typename = 'Class static function';
Class.addStaticProperty._dbg_typename = 'Class static function';
Class.make._dbg_typename = 'Class static function';
}
if ($profile) {
- Class.addProperty._profile_name = Class.addProperty._dbg_name = Class.addProperty.name = 'Class.addProperty';
+ Class.addProperties._profile_name = Class.addProperties._dbg_name = Class.addProperties.name = 'Class.addProperties';
Class.addStaticProperty._profile_name = Class.addStaticProperty._dbg_name = Class.addStaticProperty.name = 'Class.addStaticProperty'
Class.make._profile_name = Class.make._dbg_name = Class.make.name = 'Class.make';
}
@@ -518,7 +425,7 @@
var impls = this.implementations;
for (var mash in impls) {
var t = impls[mash];
- t.addProperty.apply(t, arguments);
+ t.addProperty(name, value);
}
if ($debug) {
if (value instanceof Function && (! value._dbg_typename)) {
@@ -553,28 +460,10 @@
return impls[prototypename];
}
// Add the properties to the prototype (superclassInstance)
- var ip = this.instanceProperties;
- for (var i = ip.length - 1; i >= 1; i -= 2) {
- var value = ip[i];
- var name = ip[i - 1];
-// if ($debug) {
-// if (name in superclassInstance) {
-// Debug.debug("%s.%s overrides %s.%s", this.classname, name,
-// superclassInstance.constructor.classname, name);
-// }
-// }
- superclassInstance.addProperty.call(superclassInstance, name, value);
- }
+ superclassInstance.addProperties(this.instanceProperties);
// Make the interstitial
var xtor = function interstitial () { this.constructor = arguments.callee; };
xtor.prototype = superclassInstance;
- // The mixin's initialize method will run in Class.make (in the
- // proper order).
- // TODO: [2006-05-26 ptw] are there other class properties
- // that need to be copied onto the interstitial?
- if (this.hasOwnProperty('initialize')) {
- xtor.initialize = this.initialize;
- }
// Unique name must identify superclass chain, punctuation is
// added for debugging
xtor.classname = interstitialname;
@@ -636,10 +525,6 @@
nt.addProperty(name, value);
}
}
- // Run the initializer if there is one
- if (nt.hasOwnProperty('initialize')) {
- nt.initialize(nt.prototype);
- }
global[classname] = this.allMixins[classname] = nt;
if ($profile) {
Profiler.event('new Mixin(' + classname + ')', 'returns');
@@ -654,3 +539,9 @@
Mixin.makeInterstitial._dbg_typename = 'Mixin static function';
Mixin.make._dbg_typename = 'Mixin static function';
}
+if ($profile) {
+ Mixin.addProperty._profile_name = Mixin.addProperty._dbg_name = Mixin.addProperty.name = 'Mixin.addProperty';
+ Mixin.addStaticProperty._profile_name = Mixin.addStaticProperty._dbg_name = Mixin.addStaticProperty.name = 'Mixin.addStaticProperty'
+ Mixin.makeInterstitial._profile_name = Mixin.makeInterstitial._dbg_name = Mixin.makeInterstitial.name = 'Mixin.makeInterstitial'
+ Mixin.make._profile_name = Mixin.make._dbg_name = Mixin.make.name = 'Mixin.make';
+}
Modified: openlaszlo/trunk/WEB-INF/lps/lfc/events/LaszloEvents.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/events/LaszloEvents.lzs 2009-05-02 05:05:01 UTC (rev 13796)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/events/LaszloEvents.lzs 2009-05-02 12:37:39 UTC (rev 13797)
@@ -449,7 +449,7 @@
}
if ($profile) {
/** @access private */
- var _dbg_profileName:String;
+ var _profile_name:String;
}
/**
@@ -478,7 +478,7 @@
this._dbg_eventName = eventName;
}
if ($profile) {
- this._dbg_profileName = eventName;
+ this._profile_name = eventSender._profile_typename + '/' + eventName;
}
}
@@ -519,7 +519,7 @@
this.ready = false;
if ($profile) {
- var nm:* = this._dbg_profileName;
+ var nm:* = this._profile_name;
if (nm) {
Profiler.event(nm, 'calls');
}
@@ -556,7 +556,7 @@
}
if ($profile) {
- var nm:* = this._dbg_profileName;
+ var nm:* = this._profile_name;
if (nm) {
Profiler.event(nm, 'returns');
}
Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java 2009-05-02 05:05:01 UTC (rev 13796)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/CodeGenerator.java 2009-05-02 12:37:39 UTC (rev 13797)
@@ -244,14 +244,15 @@
"if ($lzsc$lzp) {" +
// Array keys are strings
" var $lzsc$now = '' + ((new Date).getTime() - $lzsc$lzp.base);" +
+ " var $lzsc$name = " + getname + ";" +
// If the clock has not ticked (or the ms->String conversion
// makes it appear so), we log explicitly to the event buffer,
// otherwise we use the optimization of logging calls and
// returns to separate buffers
" if ($lzsc$lzp.last == $lzsc$now) {" +
- " $lzsc$lzp.events[$lzsc$now] += ('," + event + ":' + " + getname + ");" +
+ " $lzsc$lzp.events[$lzsc$now] += ('," + event + ":' + $lzsc$name);" +
" } else {" +
- " $lzsc$lzp." + event + "[$lzsc$now] = " + getname + ";" +
+ " $lzsc$lzp." + event + "[$lzsc$now] = $lzsc$name;" +
" }" +
" $lzsc$lzp.last = $lzsc$now;" +
"}" +
Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java 2009-05-02 05:05:01 UTC (rev 13796)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/sc/JavascriptGenerator.java 2009-05-02 12:37:39 UTC (rev 13797)
@@ -104,14 +104,15 @@
"if ($lzsc$lzp) {" +
// Array keys are strings
" var $lzsc$now = '' + ((new Date).getTime() - $lzsc$lzp.base);" +
+ " var $lzsc$name = " + getname + ";" +
// If the clock has not ticked (or the ms->String conversion
// makes it appear so), we log explicitly to the event buffer,
// otherwise we use the optimization of logging calls and
// returns to separate buffers
" if ($lzsc$lzp.last == $lzsc$now) {" +
- " $lzsc$lzp.events[$lzsc$now] += ('," + event + ":' + " + getname + ");" +
+ " $lzsc$lzp.events[$lzsc$now] += ('," + event + ":' + $lzsc$name);" +
" } else {" +
- " $lzsc$lzp." + event + "[$lzsc$now] = " + getname + ";" +
+ " $lzsc$lzp." + event + "[$lzsc$now] = $lzsc$name;" +
" }" +
" $lzsc$lzp.last = $lzsc$now;" +
"}");
@@ -1152,7 +1153,7 @@
// Tell metering to look up the name at runtime if it is not a
// global name (this allows us to name closures more
// mnemonically at runtime
- String meterFunctionName = userFunctionName;
+ String meterFunctionName = useName ? functionName : null;
SimpleNode[] paramIds = params.getChildren();
// Pull all the pragmas from the list: process them, and remove
// them
@@ -1529,15 +1530,24 @@
// lfc/debugger/LzBactrace
String fn = (options.getBoolean(Compiler.FLASH_COMPILER_COMPATABILITY) ? "lfc/" : "") + filename;
if (functionName != null &&
- // Either it is a declaration or we are not doing
- // backtraces, so the name will be available from the
- // runtime
- (useName || (! (options.getBoolean(Compiler.DEBUG_BACKTRACE))))) {
- if (options.getBoolean(Compiler.DEBUG_BACKTRACE)) {
+ // Either it is a declaration or we are not doing backtraces
+ // or profiling, so the name will be available for debugging
+ // from the runtime
+ (useName ||
+ (! (options.getBoolean(Compiler.PROFILE) ||
+ options.getBoolean(Compiler.DEBUG_BACKTRACE))))) {
+ if (options.getBoolean(Compiler.PROFILE) ||
+ options.getBoolean(Compiler.DEBUG_BACKTRACE)) {
SimpleNode newNode = new ASTStatementList(0);
- newNode.set(0, new Compiler.PassThroughNode(node));
- newNode.set(1, parseFragment(functionName + "._dbg_filename = " + ScriptCompiler.quote(fn)));
- newNode.set(2, parseFragment(functionName + "._dbg_lineno = " + lineno));
+ int nn = 0;
+ newNode.set(nn++, new Compiler.PassThroughNode(node));
+ if (options.getBoolean(Compiler.PROFILE)) {
+ newNode.set(nn++, parseFragment(functionName + "._dbg_name = " + ScriptCompiler.quote(functionName)));
+ }
+ if (options.getBoolean(Compiler.DEBUG_BACKTRACE)) {
+ newNode.set(nn++, parseFragment(functionName + "._dbg_filename = " + ScriptCompiler.quote(fn)));
+ newNode.set(nn++, parseFragment(functionName + "._dbg_lineno = " + lineno));
+ }
node = visitStatement(newNode);
}
} else {
More information about the Laszlo-checkins
mailing list