[INFER] Clear propagated bit from property type sets on GC, update comments, bug 673469.
authorBrian Hackett <bhackett1024@gmail.com>
Fri, 22 Jul 2011 12:55:52 -0700
changeset 77372 4fbb36c1c9a3ad2aa3cdc7aec0841faf13886a74
parent 77371 d90e0b3a8bb9c83a40954058d035f6665bb1ff75
child 77373 8c7adf094b8e51e7cdc55322bce7897502b50c24
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs673469
milestone8.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
[INFER] Clear propagated bit from property type sets on GC, update comments, bug 673469.
js/src/jit-test/tests/basic/bug673469.js
js/src/jsinfer.cpp
js/src/jsinfer.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug673469.js
@@ -0,0 +1,9 @@
+var a = Boolean();
+false.__proto__;
+var c = ({}).__proto__;
+var d = {};
+gc()
+c[0] = d;
+for (var x in a) {
+  a[x];
+}
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -5199,18 +5199,22 @@ TypeSet::sweep(JSContext *cx, JSCompartm
     } else if (objectCount == 1) {
         TypeObjectKey *object = (TypeObjectKey *) objectSet;
         if (IsAboutToBeFinalized(cx, object)) {
             objectSet = NULL;
             setBaseObjectCount(0);
         }
     }
 
-    /* All constraints are allocated from the pool wiped out on each GC. */
+    /*
+     * All constraints are wiped out on each GC, including those propagating
+     * into this type set from prototype properties.
+     */
     constraintList = NULL;
+    flags &= ~TYPE_FLAG_PROPAGATED_PROPERTY;
 }
 
 inline void
 JSObject::revertLazyType()
 {
     JS_ASSERT(hasSingletonType() && !hasLazyType());
     JS_ASSERT_IF(type_->proto, type_->proto->newType);
     flags |= LAZY_TYPE;
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -164,37 +164,23 @@ class Type
 /* Get the type of a jsval, or zero for an unknown special value. */
 inline Type GetValueType(JSContext *cx, const Value &val);
 
 /*
  * Type inference memory management overview.
  *
  * Inference constructs a global web of constraints relating the contents of
  * type sets particular to various scripts and type objects within a
- * compartment. These constraints can consume a significant amount of memory,
- * and to avoid this building up we clear out (almost, see 1.) all the
- * constraints and most other type inference data on (almost, see 2.) every GC.
- * JIT code which depends on this type information and is sensitive to
- * subsequent changes is cleared at the same time.
- *
- * Type constraints may be either transient --- destroyed along with the type
- * constraints --- or persistent. Persistent constraints describe properties
- * of type objects, locals, args, and observed types in scripts, and may or
- * may not survive GCs.
- *
- * Notes:
- *
- * 1. Some type constraints are persistent, and relate type objects to each
- * other. These survive GCs as long as some target type object is live.
- *
- * 2. If a GC happens while we are in the middle of or working with analysis
- * information (both type information and other transient information stored in
- * ScriptAnalysis), we do not destroy analysis information or collect
- * TypeObjects or JSScripts. This is controlled with AutoEnterAnalysis and
- * AutoEnterTypeInference.
+ * compartment. This data can consume a significant amount of memory, and to
+ * avoid this building up we try to clear it with some regularity. On each GC
+ * which occurs while we are not actively working with inference or other
+ * analysis information, we clear out all generated constraints, all type sets
+ * describing stack types within scripts, and (normally) all data describing
+ * type objects describing particular JS objects (see the lazy type objects
+ * overview below). JIT code depends on this data and is cleared as well.
  */
 
 /*
  * A constraint which listens to additions to a type set and propagates those
  * changes to other type sets.
  */
 class TypeConstraint
 {
@@ -667,25 +653,30 @@ struct TypeNewScript
  *
  * Type objects which represent at most one JS object are constructed lazily.
  * These include types for native functions, standard classes, scripted
  * functions defined at the top level of global/eval scripts, and in some
  * other cases. Typical web workloads often create many windows (and many
  * copies of standard natives) and many scripts, with comparatively few
  * non-singleton types.
  *
- * We can recover the type information for the object from examining it
- * (with exceptions for certain object flags, see OBJECT_FLAG_DETERMINED_MASK),
- * so don't need to track type information when updating the object. The type
- * object is only constructed when we need to put constraints on any of its
- * properties, in which case we fully instantiate the type's properties.
+ * We can recover the type information for the object from examining it,
+ * so don't normally track the possible types of its properties as it is
+ * updated. Property type sets for the object are only constructed when an
+ * analyzed script attaches constraints to it: the script is querying that
+ * property off the object or another which delegates to it, and the analysis
+ * information is sensitive to changes in the property's type. Future changes
+ * to the property (whether those uncovered by analysis or those occurring
+ * in the VM) will treat these properties like those of any other type object.
  *
- * If all outgoing constraints on the type are removed constraints by a GC,
- * the type object and its properties are destroyed and the JS object reverts
- * to having a lazy type.
+ * When a GC occurs, we wipe out all analysis information for all the
+ * compartment's scripts, so can destroy all properties on singleton type
+ * objects at the same time. If there is no reference on the stack to the
+ * type object itself, the type object is also destroyed, and the JS object
+ * reverts to having a lazy type.
  */
 
 /* Type information about an object accessed by a script. */
 struct TypeObject : gc::Cell
 {
 #ifdef DEBUG
     /* Name of this object. */
     jsid name_;
@@ -737,21 +728,21 @@ struct TypeObject : gc::Cell
      * constraints listening to changes to the object's state. Correspondence
      * between the properties of a TypeObject and the properties of
      * script-visible JSObjects (not Call, Block, etc.) which have that type is
      * as follows:
      *
      * - If the type has unknownProperties(), the possible properties and value
      *   types for associated JSObjects are unknown.
      *
-     * - Otherwise, for any JSObject obj with TypeObject type, and any jsid id,
-     *   after obj->getProperty(id) the property in type for id must reflect
-     *   the result of the getProperty. The result is additionally allowed to
-     *   be undefined for ids which are not in obj or its prototypes, and for
-     *   properties of global objects defined with 'var' but not yet written.
+     * - Otherwise, for any JSObject obj with TypeObject type, and any jsid id
+     *   which is a property in obj, after obj->getProperty(id) the property in
+     *   type for id must reflect the result of the getProperty. The result is
+     *   additionally allowed to be undefined for properties of global objects
+     *   defined with 'var' but not yet written.
      *
      * - Additionally, if id is a normal owned native property within obj, then
      *   after the setProperty or defineProperty which wrote its value, the
      *   property in type for id must reflect that type.
      *
      * We establish these by using write barriers on calls to setProperty and
      * defineProperty which are on native properties, and read barriers on
      * getProperty that go through a class hook or special PropertyOp.