[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