[INFER] Move inference methods out of JSContext, bug 657412.
authorBrian Hackett <bhackett1024@gmail.com>
Thu, 02 Jun 2011 10:40:27 -0700
changeset 75132 b9679727505db2d932c2f1815a94a0a73a8723e8
parent 75131 cbd95be079612742815f98591394a58bac656960
child 75133 aa4d3d18621efe9282615ffb959922b121d4e014
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs657412
milestone6.0a1
[INFER] Move inference methods out of JSContext, bug 657412.
js/src/Makefile.in
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsarray.h
js/src/jsarrayinlines.h
js/src/jscntxt.h
js/src/jsdate.cpp
js/src/jsdbgapi.cpp
js/src/jsemit.cpp
js/src/jsfriendapi.cpp
js/src/jsfun.cpp
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/jsinferinlines.h
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsmath.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobjinlines.h
js/src/json.cpp
js/src/jsparse.cpp
js/src/jsproxy.cpp
js/src/jsregexp.cpp
js/src/jsscope.cpp
js/src/jsscript.h
js/src/jsstr.cpp
js/src/jstypedarray.cpp
js/src/jswrapper.cpp
js/src/jsxml.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/PolyIC.cpp
js/src/methodjit/Retcon.cpp
js/src/methodjit/StubCalls.cpp
js/src/shell/js.cpp
js/src/vm/GlobalObject.cpp
modules/libpref/src/init/all.js
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -189,16 +189,17 @@ INSTALLED_HEADERS = \
 		js-config.h \
 		jsautocfg.h \
 		$(CURDIR)/jsautokw.h \
 		js.msg \
 		jsalloc.h \
 		jsanalyze.h \
 		jsapi.h \
 		jsarray.h \
+		jsarrayinlines.h \
 		jsarena.h \
 		jsatom.h \
 		jsbit.h \
 		jsbool.h \
 		jsclist.h \
 		jsclone.h \
 		jscntxt.h \
 		jscompat.h \
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3054,19 +3054,19 @@ JS_NewObject(JSContext *cx, JSClass *jsc
         clasp = &js_ObjectClass;    /* default class is Object */
 
     JS_ASSERT(clasp != &js_FunctionClass);
     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
     JSObject *obj = NewNonFunction<WithProto::Class>(cx, clasp, proto, parent);
     if (obj) {
         if (clasp->ext.equality)
-            cx->markTypeObjectFlags(obj->getType(), OBJECT_FLAG_SPECIAL_EQUALITY);
+            MarkTypeObjectFlags(cx, obj->getType(), OBJECT_FLAG_SPECIAL_EQUALITY);
         obj->syncSpecialEquality();
-        cx->markTypeObjectUnknownProperties(obj->getType());
+        MarkTypeObjectUnknownProperties(cx, obj->getType());
     }
 
     JS_ASSERT_IF(obj, obj->getParent());
     return obj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewObjectWithGivenProto(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
@@ -3080,17 +3080,17 @@ JS_NewObjectWithGivenProto(JSContext *cx
         clasp = &js_ObjectClass;    /* default class is Object */
 
     JS_ASSERT(clasp != &js_FunctionClass);
     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
     JSObject *obj = NewNonFunction<WithProto::Given>(cx, clasp, proto, parent);
     if (obj) {
         obj->syncSpecialEquality();
-        cx->markTypeObjectUnknownProperties(obj->getType());
+        MarkTypeObjectUnknownProperties(cx, obj->getType());
     }
     return obj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewObjectForConstructor(JSContext *cx, const jsval *vp)
 {
     CHECK_REQUEST(cx);
@@ -3544,17 +3544,17 @@ JS_AliasProperty(JSContext *cx, JSObject
                              alias, name, obj2->getClass()->name);
         return JS_FALSE;
     }
     JSAtom *aliasAtom = js_Atomize(cx, alias, strlen(alias));
     if (!aliasAtom) {
         ok = JS_FALSE;
     } else {
         /* Alias the properties within the type information for the object. */
-        cx->aliasTypeProperties(obj->getType(), ATOM_TO_JSID(nameAtom), ATOM_TO_JSID(aliasAtom));
+        AliasTypeProperties(cx, obj->getType(), ATOM_TO_JSID(nameAtom), ATOM_TO_JSID(aliasAtom));
 
         shape = (Shape *)prop;
         ok = (js_AddNativeProperty(cx, obj, ATOM_TO_JSID(aliasAtom),
                                    shape->getter(), shape->setter(), shape->slot,
                                    shape->attributes(), shape->getFlags() | Shape::ALIAS,
                                    shape->shortid)
               != NULL);
     }
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -124,23 +124,23 @@
 #include "jstracer.h"
 #include "jsvector.h"
 #include "jswrapper.h"
 #include "methodjit/StubCalls.h"
 #include "methodjit/StubCalls-inl.h"
 
 #include "vm/ArgumentsObject.h"
 
+#include "jsarrayinlines.h"
 #include "jsatominlines.h"
 #include "jscntxtinlines.h"
 #include "jsinterpinlines.h"
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
 #include "jscntxtinlines.h"
-#include "jsinferinlines.h"
 #include "jsstrinlines.h"
 
 #include "vm/ArgumentsObject-inl.h"
 #include "vm/Stack-inl.h"
 
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
@@ -1054,19 +1054,19 @@ AddLengthProperty(JSContext *cx, JSObjec
 /*
  * Convert an array object from fast-and-dense to slow-and-flexible.
  */
 JSBool
 JSObject::makeDenseArraySlow(JSContext *cx)
 {
     JS_ASSERT(isDenseArray());
 
-    cx->markTypeObjectFlags(getType(),
-                            js::types::OBJECT_FLAG_NON_PACKED_ARRAY |
-                            js::types::OBJECT_FLAG_NON_DENSE_ARRAY);
+    MarkTypeObjectFlags(cx, getType(),
+                            OBJECT_FLAG_NON_PACKED_ARRAY |
+                            OBJECT_FLAG_NON_DENSE_ARRAY);
     markDenseArrayNotPacked(cx);
 
     /*
      * Save old map now, before calling InitScopeForObject. We'll have to undo
      * on error. This is gross, but a better way is not obvious. Note: the
      * exact contents of the array are not preserved on error.
      */
     js::Shape *oldMap = lastProp;
@@ -2176,17 +2176,17 @@ array_push_slowly(JSContext *cx, JSObjec
         return JS_FALSE;
 
     /* Per ECMA-262, return the new array length. */
     jsdouble newlength = length + jsdouble(argc);
     rval->setNumber(newlength);
 
     /* watch for length overflowing to a double. */
     if (!rval->isInt32())
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
 
     return js_SetLengthProperty(cx, obj, newlength);
 }
 
 static JSBool
 array_push1_dense(JSContext* cx, JSObject* obj, const Value &v, Value *rval)
 {
     uint32 length = obj->getArrayLength();
@@ -2289,48 +2289,48 @@ array_pop_slowly(JSContext *cx, JSObject
 {
     jsuint index;
     JSBool hole;
 
     if (!js_GetLengthProperty(cx, obj, &index))
         return JS_FALSE;
     if (index == 0) {
         vp->setUndefined();
-        cx->markTypeCallerUnexpected(TYPE_UNDEFINED);
+        MarkTypeCallerUnexpected(cx, TYPE_UNDEFINED);
     } else {
         index--;
 
         /* Get the to-be-deleted property's value into vp. */
         if (!GetElement(cx, obj, index, &hole, vp))
             return JS_FALSE;
         if (hole)
-            cx->markTypeCallerUnexpected(TYPE_UNDEFINED);
+            MarkTypeCallerUnexpected(cx, TYPE_UNDEFINED);
         if (!hole && DeleteArrayElement(cx, obj, index, true) < 0)
             return JS_FALSE;
     }
     return js_SetLengthProperty(cx, obj, index);
 }
 
 static JSBool
 array_pop_dense(JSContext *cx, JSObject* obj, Value *vp)
 {
     jsuint index;
     JSBool hole;
 
     index = obj->getArrayLength();
     if (index == 0) {
         vp->setUndefined();
-        cx->markTypeCallerUnexpected(TYPE_UNDEFINED);
+        MarkTypeCallerUnexpected(cx, TYPE_UNDEFINED);
         return JS_TRUE;
     }
     index--;
     if (!GetElement(cx, obj, index, &hole, vp))
         return JS_FALSE;
     if (hole)
-        cx->markTypeCallerUnexpected(TYPE_UNDEFINED);
+        MarkTypeCallerUnexpected(cx, TYPE_UNDEFINED);
     if (!hole && DeleteArrayElement(cx, obj, index, true) < 0)
         return JS_FALSE;
 
     if (cx->typeInferenceEnabled() && obj->getDenseArrayInitializedLength() > index)
         obj->setDenseArrayInitializedLength(index);
     obj->setArrayLength(cx, index);
     return JS_TRUE;
 }
@@ -2354,27 +2354,27 @@ array_shift(JSContext *cx, uintN argc, V
         return JS_FALSE;
 
     jsuint length;
     if (!js_GetLengthProperty(cx, obj, &length))
         return JS_FALSE;
 
     if (length == 0) {
         vp->setUndefined();
-        cx->markTypeCallerUnexpected(TYPE_UNDEFINED);
+        MarkTypeCallerUnexpected(cx, TYPE_UNDEFINED);
     } else {
         length--;
 
         if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) &&
             length < obj->getDenseArrayCapacity() &&
             0 < obj->getDenseArrayInitializedLength()) {
             *vp = obj->getDenseArrayElement(0);
             if (vp->isMagic(JS_ARRAY_HOLE)) {
                 vp->setUndefined();
-                cx->markTypeCallerUnexpected(TYPE_UNDEFINED);
+                MarkTypeCallerUnexpected(cx, TYPE_UNDEFINED);
             }
             Value *elems = obj->getDenseArrayElements();
             memmove(elems, elems + 1, length * sizeof(jsval));
             if (cx->typeInferenceEnabled())
                 obj->setDenseArrayInitializedLength(obj->getDenseArrayInitializedLength() - 1);
             else
                 obj->setDenseArrayElement(length, MagicValue(JS_ARRAY_HOLE));
             obj->setArrayLength(cx, length);
@@ -2384,17 +2384,17 @@ array_shift(JSContext *cx, uintN argc, V
         }
 
         /* Get the to-be-deleted property's value into vp ASAP. */
         JSBool hole;
         if (!GetElement(cx, obj, 0, &hole, vp))
             return JS_FALSE;
 
         if (hole)
-            cx->markTypeCallerUnexpected(TYPE_UNDEFINED);
+            MarkTypeCallerUnexpected(cx, TYPE_UNDEFINED);
 
         /* Slide down the array above the first element. */
         AutoValueRooter tvr(cx);
         for (jsuint i = 0; i < length; i++) {
             if (!JS_CHECK_OPERATION_LIMIT(cx) ||
                 !GetElement(cx, obj, i + 1, &hole, tvr.addr()) ||
                 !SetOrDeleteArrayElement(cx, obj, i, hole, tvr.value())) {
                 return JS_FALSE;
@@ -2471,17 +2471,17 @@ array_unshift(JSContext *cx, uintN argc,
     if (!js_SetLengthProperty(cx, obj, newlen))
         return JS_FALSE;
 
     /* Follow Perl by returning the new array length. */
     vp->setNumber(newlen);
 
     /* watch for length overflowing to a double. */
     if (!vp->isInt32())
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
 
     return JS_TRUE;
 }
 
 static JSBool
 array_splice(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj = ToObject(cx, &vp[1]);
@@ -2495,20 +2495,20 @@ array_splice(JSContext *cx, uintN argc, 
     TypeObject *type;
     if (obj->isArray()) {
         type = obj->getType();
     } else {
         /*
          * Make a new type object for the return value.  This is an unexpected
          * result of the call so mark it at the callsite.
          */
-        type = cx->getTypeNewObject(JSProto_Array);
+        type = GetTypeNewObject(cx, JSProto_Array);
         if (!type)
             return false;
-        cx->markTypeCallerUnexpected((jstype) type);
+        MarkTypeCallerUnexpected(cx, (jstype) type);
     }
 
     /* Create a new array value to return. */
     JSObject *obj2 = NewDenseEmptyArray(cx);
     if (!obj2)
         return JS_FALSE;
     obj2->setType(type);
     vp->setObject(*obj2);
@@ -2677,31 +2677,31 @@ array_concat(JSContext *cx, uintN argc, 
         Value *vector = aobj->getDenseArrayElements();
         jsuint initlen = aobj->getDenseArrayInitializedLength();
         nobj = NewDenseCopiedArray(cx, initlen, vector);
         if (!nobj)
             return JS_FALSE;
         if (nobj->getProto() == aobj->getProto())
             nobj->setType(aobj->getType());
         else
-            cx->markTypeCallerUnexpected(TYPE_UNKNOWN);
+            MarkTypeCallerUnexpected(cx, TYPE_UNKNOWN);
         nobj->setType(aobj->getType());
         nobj->setArrayLength(cx, length);
         if (!aobj->isPackedDenseArray())
             nobj->markDenseArrayNotPacked(cx);
         vp->setObject(*nobj);
         if (argc == 0)
             return JS_TRUE;
         argc--;
         p++;
     } else {
         nobj = NewDenseEmptyArray(cx);
         if (!nobj)
             return JS_FALSE;
-        cx->markTypeCallerUnexpected(TYPE_UNKNOWN);
+        MarkTypeCallerUnexpected(cx, TYPE_UNKNOWN);
         vp->setObject(*nobj);
         length = 0;
     }
 
     AutoValueRooter tvr(cx);
 
     /* Loop over [0, argc] to concat args into nobj, expanding all Arrays. */
     for (uintN i = 0; i <= argc; i++) {
@@ -2800,20 +2800,20 @@ array_slice(JSContext *cx, uintN argc, V
     TypeObject *type;
     if (obj->isArray()) {
         type = obj->getType();
     } else {
         /*
          * Make a new type object for the return value.  This is an unexpected
          * result of the call so mark it at the callsite.
          */
-        type = cx->getTypeNewObject(JSProto_Array);
+        type = GetTypeNewObject(cx, JSProto_Array);
         if (!type)
             return false;
-        cx->markTypeCallerUnexpected((jstype) type);
+        MarkTypeCallerUnexpected(cx, (jstype) type);
     }
 
     if (obj->isDenseArray() && end <= obj->getDenseArrayInitializedLength() &&
         !js_PrototypeHasIndexedProperties(cx, obj)) {
         nobj = NewDenseCopiedArray(cx, end - begin, obj->getDenseArrayElements() + begin);
         if (!nobj)
             return JS_FALSE;
         nobj->setType(type);
@@ -2903,17 +2903,17 @@ array_indexOfHelper(JSContext *cx, JSBoo
         }
         if (!hole) {
             JSBool equal;
             if (!StrictlyEqual(cx, *vp, tosearch, &equal))
                 return JS_FALSE;
             if (equal) {
                 vp->setNumber(i);
                 if (!vp->isInt32())
-                    cx->markTypeCallerOverflow();
+                    MarkTypeCallerOverflow(cx);
                 return JS_TRUE;
             }
         }
         if (i == stop)
             goto not_found;
         i += direction;
     }
 
@@ -3012,17 +3012,17 @@ array_extra(JSContext *cx, ArrayExtraMod
         }
         break;
       case MAP:
       case FILTER:
         newlen = (mode == MAP) ? length : 0;
         newarr = NewDenseAllocatedArray(cx, newlen);
         if (!newarr)
             return JS_FALSE;
-        newtype = cx->getTypeCallerInitObject(true);
+        newtype = GetTypeCallerInitObject(cx, true);
         if (!newtype)
             return JS_FALSE;
         newarr->setType(newtype);
         vp->setObject(*newarr);
         break;
       case SOME:
         vp->setBoolean(false);
         break;
@@ -3387,28 +3387,28 @@ static JSFunctionSpec array_static_metho
     JS_FS_END
 };
 
 JSBool
 js_Array(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj;
 
-    TypeObject *type = cx->getTypeCallerInitObject(true);
+    TypeObject *type = GetTypeCallerInitObject(cx, true);
     if (!type)
         return JS_FALSE;
 
     if (argc == 0) {
         obj = NewDenseEmptyArray(cx);
     } else if (argc > 1) {
         if (!InitArrayTypes(cx, type, vp + 2, argc))
             return false;
         obj = NewDenseCopiedArray(cx, argc, vp + 2);
     } else if (!vp[2].isNumber()) {
-        cx->addTypePropertyId(type, JSID_VOID, vp[2]);
+        AddTypePropertyId(cx, type, JSID_VOID, vp[2]);
         obj = NewDenseCopiedArray(cx, 1, vp + 2);
     } else {
         jsuint length;
         if (!ValueToLength(cx, vp + 2, &length))
             return JS_FALSE;
         obj = NewDenseUnallocatedArray(cx, length);
     }
 
@@ -3470,25 +3470,25 @@ js_InitArrayClass(JSContext *cx, JSObjec
     if (!proto)
         return NULL;
 
     /*
      * Add the length property for all arrays with this prototype. Arrays whose
      * length overflows to a uint32 will be caught by setArrayLength.
      */
     jsid lengthId = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
-    cx->addTypePropertyId(proto->getType(), lengthId, TYPE_INT32);
+    AddTypePropertyId(cx, proto->getType(), lengthId, TYPE_INT32);
 
     proto->setArrayLength(cx, 0);
 
     /* The default 'new' object for Array.prototype has unknown properties. */
     TypeObject *newType = proto->getNewType(cx);
     if (!newType)
         return NULL;
-    cx->markTypeObjectUnknownProperties(newType);
+    MarkTypeObjectUnknownProperties(cx, newType);
 
     return proto;
 }
 
 /*
  * Array allocation functions.
  */
 namespace js {
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -69,102 +69,16 @@ JSObject::setDenseArrayInitializedLength
 
 inline bool
 JSObject::isPackedDenseArray()
 {
     JS_ASSERT(isDenseArray());
     return flags & PACKED_ARRAY;
 }
 
-inline void
-JSObject::markDenseArrayNotPacked(JSContext *cx)
-{
-    JS_ASSERT(isDenseArray());
-    if (flags & PACKED_ARRAY) {
-        flags ^= PACKED_ARRAY;
-        cx->markTypeObjectFlags(getType(), js::types::OBJECT_FLAG_NON_PACKED_ARRAY);
-    }
-}
-
-inline void
-JSObject::backfillDenseArrayHoles(JSContext *cx)
-{
-    /* Ensure an array's elements are fully initialized. */
-    ensureDenseArrayInitializedLength(cx, getDenseArrayCapacity(), 0);
-}
-
-inline void
-JSObject::ensureDenseArrayInitializedLength(JSContext *cx, uint32 index, uint32 extra)
-{
-    /*
-     * Ensure that the array's contents have been initialized up to index, and
-     * mark the elements through 'index + extra' as initialized in preparation
-     * for a write.
-     */
-    JS_ASSERT(index + extra <= capacity);
-    if (initializedLength < index) {
-        markDenseArrayNotPacked(cx);
-        ClearValueRange(slots + initializedLength, index - initializedLength, true);
-    }
-    if (initializedLength < index + extra)
-        initializedLength = index + extra;
-}
-
-inline JSObject::EnsureDenseResult
-JSObject::ensureDenseArrayElements(JSContext *cx, uintN index, uintN extra)
-{
-    JS_ASSERT(isDenseArray());
-
-    uintN currentCapacity = numSlots();
-
-    /*
-     * Don't take excessive slow paths when inference is disabled, due to
-     * uninitialized slots between initializedLength and capacity.
-     */
-    JS_ASSERT_IF(!cx->typeInferenceEnabled(), currentCapacity == getDenseArrayInitializedLength());
-
-    uintN requiredCapacity;
-    if (extra == 1) {
-        /* Optimize for the common case. */
-        if (index < currentCapacity) {
-            ensureDenseArrayInitializedLength(cx, index, 1);
-            return ED_OK;
-        }
-        requiredCapacity = index + 1;
-        if (requiredCapacity == 0) {
-            /* Overflow. */
-            return ED_SPARSE;
-        }
-    } else {
-        requiredCapacity = index + extra;
-        if (requiredCapacity < index) {
-            /* Overflow. */
-            return ED_SPARSE;
-        }
-        if (requiredCapacity <= currentCapacity) {
-            ensureDenseArrayInitializedLength(cx, index, extra);
-            return ED_OK;
-        }
-    }
-
-    /*
-     * We use the extra argument also as a hint about number of non-hole
-     * elements to be inserted.
-     */
-    if (requiredCapacity > MIN_SPARSE_INDEX &&
-        willBeSparseDenseArray(requiredCapacity, extra)) {
-        return ED_SPARSE;
-    }
-    if (!growSlots(cx, requiredCapacity))
-        return ED_FAILED;
-
-    ensureDenseArrayInitializedLength(cx, index, extra);
-    return ED_OK;
-}
-
 extern bool
 js_StringIsIndex(JSLinearString *str, jsuint *indexp);
 
 inline JSBool
 js_IdIsIndex(jsid id, jsuint *indexp)
 {
     if (JSID_IS_INT(id)) {
         jsint i;
new file mode 100644
--- /dev/null
+++ b/js/src/jsarrayinlines.h
@@ -0,0 +1,131 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsarrayinlines_h___
+#define jsarrayinlines_h___
+
+#include "jsinferinlines.h"
+
+inline void
+JSObject::markDenseArrayNotPacked(JSContext *cx)
+{
+    JS_ASSERT(isDenseArray());
+    if (flags & PACKED_ARRAY) {
+        flags ^= PACKED_ARRAY;
+        MarkTypeObjectFlags(cx, getType(), js::types::OBJECT_FLAG_NON_PACKED_ARRAY);
+    }
+}
+
+inline void
+JSObject::backfillDenseArrayHoles(JSContext *cx)
+{
+    /* Ensure an array's elements are fully initialized. */
+    ensureDenseArrayInitializedLength(cx, getDenseArrayCapacity(), 0);
+}
+
+inline void
+JSObject::ensureDenseArrayInitializedLength(JSContext *cx, uint32 index, uint32 extra)
+{
+    /*
+     * Ensure that the array's contents have been initialized up to index, and
+     * mark the elements through 'index + extra' as initialized in preparation
+     * for a write.
+     */
+    JS_ASSERT(index + extra <= capacity);
+    if (initializedLength < index) {
+        markDenseArrayNotPacked(cx);
+        ClearValueRange(slots + initializedLength, index - initializedLength, true);
+    }
+    if (initializedLength < index + extra)
+        initializedLength = index + extra;
+}
+
+inline JSObject::EnsureDenseResult
+JSObject::ensureDenseArrayElements(JSContext *cx, uintN index, uintN extra)
+{
+    JS_ASSERT(isDenseArray());
+
+    uintN currentCapacity = numSlots();
+
+    /*
+     * Don't take excessive slow paths when inference is disabled, due to
+     * uninitialized slots between initializedLength and capacity.
+     */
+    JS_ASSERT_IF(!cx->typeInferenceEnabled(), currentCapacity == getDenseArrayInitializedLength());
+
+    uintN requiredCapacity;
+    if (extra == 1) {
+        /* Optimize for the common case. */
+        if (index < currentCapacity) {
+            ensureDenseArrayInitializedLength(cx, index, 1);
+            return ED_OK;
+        }
+        requiredCapacity = index + 1;
+        if (requiredCapacity == 0) {
+            /* Overflow. */
+            return ED_SPARSE;
+        }
+    } else {
+        requiredCapacity = index + extra;
+        if (requiredCapacity < index) {
+            /* Overflow. */
+            return ED_SPARSE;
+        }
+        if (requiredCapacity <= currentCapacity) {
+            ensureDenseArrayInitializedLength(cx, index, extra);
+            return ED_OK;
+        }
+    }
+
+    /*
+     * We use the extra argument also as a hint about number of non-hole
+     * elements to be inserted.
+     */
+    if (requiredCapacity > MIN_SPARSE_INDEX &&
+        willBeSparseDenseArray(requiredCapacity, extra)) {
+        return ED_SPARSE;
+    }
+    if (!growSlots(cx, requiredCapacity))
+        return ED_FAILED;
+
+    ensureDenseArrayInitializedLength(cx, index, extra);
+    return ED_OK;
+}
+
+#endif /* jsarrayinlines_h___ */
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -1271,16 +1271,18 @@ struct JSContext
     bool                 methodJitEnabled;
     bool                 profilingEnabled;
 
     inline js::mjit::JaegerCompartment *jaegerCompartment();
 #endif
 
     bool                 inferenceEnabled;
 
+    bool typeInferenceEnabled() { return inferenceEnabled; }
+
     /* Caller must be holding runtime->gcLock. */
     void updateJITEnabled();
 
 #ifdef MOZ_TRACE_JSCALLS
     /* Function entry/exit debugging callback. */
     JSFunctionCallback    functionCallback;
 
     void doFunctionCallback(const JSFunction *fun,
@@ -1395,74 +1397,16 @@ struct JSContext
   private:
     /*
      * The allocation code calls the function to indicate either OOM failure
      * when p is null or that a memory pressure counter has reached some
      * threshold when p is not null. The function takes the pointer and not
      * a boolean flag to minimize the amount of code in its inlined callers.
      */
     JS_FRIEND_API(void) checkMallocGCPressure(void *p);
-
-  public:
-
-    inline bool typeInferenceEnabled();
-
-    /*
-     * Get the default 'new' object for a given standard class, per the currently
-     * active global.
-     */
-    inline js::types::TypeObject *getTypeNewObject(JSProtoKey key);
-
-    /* Get a type object for the immediate allocation site in this context. */
-    inline js::types::TypeObject *
-    getTypeCallerInitObject(bool isArray);
-
-    /* Mark the immediate allocation site as having produced an unexpected value. */
-    inline void markTypeCallerUnexpected(js::types::jstype type);
-    inline void markTypeCallerUnexpected(const js::Value &value);
-    inline void markTypeCallerOverflow();
-
-    /*
-     * Monitor a javascript call, either on entry to the interpreter or made
-     * from within the interpreter.
-     */
-    inline void typeMonitorCall(const js::CallArgs &args, bool constructing);
-
-    /* Add a possible value for the named property of obj. */
-    inline void addTypeProperty(js::types::TypeObject *obj, const char *name, js::types::jstype type);
-    inline void addTypeProperty(js::types::TypeObject *obj, const char *name, const js::Value &value);
-    inline void addTypePropertyId(js::types::TypeObject *obj, jsid id, js::types::jstype type);
-    inline void addTypePropertyId(js::types::TypeObject *obj, jsid id, const js::Value &value);
-    inline void addTypePropertyId(js::types::TypeObject *obj, jsid id, js::types::ClonedTypeSet *types);
-
-    /* Get the type to use for objects with no prototype. */
-    inline js::types::TypeObject *getTypeEmpty();
-
-    /* Alias two properties in the type information for obj. */
-    inline void aliasTypeProperties(js::types::TypeObject *obj, jsid first, jsid second);
-
-    /* Set one or more dynamic flags on a type object. */
-    inline void markTypeObjectFlags(js::types::TypeObject *obj, js::types::TypeObjectFlags flags);
-
-    /* Mark all properties of a type object as unknown. */
-    inline void markTypeObjectUnknownProperties(js::types::TypeObject *obj);
-
-    /* Mark any property which has been deleted or reconfigured. */
-    inline void markTypePropertyConfigured(js::types::TypeObject *obj, jsid id);
-
-    /* Mark a global object as having had its slots reallocated. */
-    inline void markGlobalReallocation(JSObject *obj);
-
-    /*
-     * For an array or object which has not yet escaped and been referenced elsewhere,
-     * pick a new type based on the object's current contents.
-     */
-    inline void fixArrayType(JSObject *obj);
-    inline void fixObjectType(JSObject *obj);
-
 }; /* struct JSContext */
 
 namespace js {
 
 #ifdef JS_THREADSAFE
 # define JS_THREAD_ID(cx)       ((cx)->thread() ? (cx)->thread()->id : 0)
 #endif
 
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -1450,17 +1450,17 @@ date_getYear(JSContext *cx, uintN argc, 
     Value yearVal = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_YEAR);
     if (yearVal.isInt32()) {
         /* Follow ECMA-262 to the letter, contrary to IE JScript. */
         jsint year = yearVal.toInt32() - 1900;
         vp->setInt32(year);
     } else {
         *vp = yearVal;
         if (!vp->isInt32())
-            cx->markTypeCallerOverflow();
+            MarkTypeCallerOverflow(cx);
     }
 
     return true;
 }
 
 static JSBool
 date_getFullYear(JSContext *cx, uintN argc, Value *vp)
 {
@@ -1468,31 +1468,31 @@ date_getFullYear(JSContext *cx, uintN ar
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return JS_FALSE;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_YEAR);
     if (!vp->isInt32())
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
     return JS_TRUE;
 }
 
 static JSBool
 date_getUTCFullYear(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble result;
     if (!GetThisUTCTime(cx, vp, &result))
         return false;
 
     if (JSDOUBLE_IS_FINITE(result))
         result = YearFromTime(result);
     else
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return true;
 }
 
 static JSBool
 date_getMonth(JSContext *cx, uintN argc, Value *vp)
 {
@@ -1500,31 +1500,31 @@ date_getMonth(JSContext *cx, uintN argc,
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return false;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MONTH);
     if (!vp->isInt32())
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
     return true;
 }
 
 static JSBool
 date_getUTCMonth(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble result;
     if (!GetThisUTCTime(cx, vp, &result))
         return false;
 
     if (JSDOUBLE_IS_FINITE(result))
         result = MonthFromTime(result);
     else
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return true;
 }
 
 static JSBool
 date_getDate(JSContext *cx, uintN argc, Value *vp)
 {
@@ -1532,31 +1532,31 @@ date_getDate(JSContext *cx, uintN argc, 
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return false;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DATE);
     if (!vp->isInt32())
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
     return true;
 }
 
 static JSBool
 date_getUTCDate(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble result;
     if (!GetThisUTCTime(cx, vp, &result))
         return false;
 
     if (JSDOUBLE_IS_FINITE(result))
         result = DateFromTime(result);
     else
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return true;
 }
 
 static JSBool
 date_getDay(JSContext *cx, uintN argc, Value *vp)
 {
@@ -1564,31 +1564,31 @@ date_getDay(JSContext *cx, uintN argc, V
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return false;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DAY);
     if (!vp->isInt32())
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
     return true;
 }
 
 static JSBool
 date_getUTCDay(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble result;
     if (!GetThisUTCTime(cx, vp, &result))
         return false;
 
     if (JSDOUBLE_IS_FINITE(result))
         result = WeekDay(result);
     else
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return true;
 }
 
 static JSBool
 date_getHours(JSContext *cx, uintN argc, Value *vp)
 {
@@ -1596,31 +1596,31 @@ date_getHours(JSContext *cx, uintN argc,
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return false;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_HOURS);
     if (!vp->isInt32())
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
     return true;
 }
 
 static JSBool
 date_getUTCHours(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble result;
     if (!GetThisUTCTime(cx, vp, &result))
         return false;
 
     if (JSDOUBLE_IS_FINITE(result))
         result = HourFromTime(result);
     else
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return JS_TRUE;
 }
 
 static JSBool
 date_getMinutes(JSContext *cx, uintN argc, Value *vp)
 {
@@ -1628,31 +1628,31 @@ date_getMinutes(JSContext *cx, uintN arg
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return false;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MINUTES);
     if (!vp->isInt32())
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
     return true;
 }
 
 static JSBool
 date_getUTCMinutes(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble result;
     if (!GetThisUTCTime(cx, vp, &result))
         return false;
 
     if (JSDOUBLE_IS_FINITE(result))
         result = MinFromTime(result);
     else
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return true;
 }
 
 /* Date.getSeconds is mapped to getUTCSeconds */
 
 static JSBool
@@ -1662,33 +1662,33 @@ date_getUTCSeconds(JSContext *cx, uintN 
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return false;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_SECONDS);
     if (!vp->isInt32())
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
     return true;
 }
 
 /* Date.getMilliseconds is mapped to getUTCMilliseconds */
 
 static JSBool
 date_getUTCMilliseconds(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble result;
     if (!GetThisUTCTime(cx, vp, &result))
         return false;
 
     if (JSDOUBLE_IS_FINITE(result))
         result = msFromTime(result);
     else
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return true;
 }
 
 static JSBool
 date_getTimezoneOffset(JSContext *cx, uintN argc, Value *vp)
 {
@@ -1706,17 +1706,17 @@ date_getTimezoneOffset(JSContext *cx, ui
 
     /*
      * Return the time zone offset in minutes for the current locale that is
      * appropriate for this time. This value would be a constant except for
      * daylight savings time.
      */
     jsdouble result = (utctime - localtime) / msPerMinute;
     if (!JSDOUBLE_IS_FINITE(result))
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return true;
 }
 
 static JSBool
 date_setTime(JSContext *cx, uintN argc, Value *vp)
 {
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -220,18 +220,20 @@ JS_SetDebugModeForCompartment(JSContext 
             return JS_FALSE;
         }
 
         mjit::ReleaseScriptCode(cx, script, true);
         mjit::ReleaseScriptCode(cx, script, false);
         script->debugMode = !!debug;
 
         /* Mark arguments objects as escaping in all scripts if debug mode is on. */
-        if (script->usesArguments && debug)
-            cx->markTypeObjectFlags(script->fun->getType(), types::OBJECT_FLAG_CREATED_ARGUMENTS);
+        if (script->usesArguments && debug) {
+            types::MarkTypeObjectFlags(cx, script->fun->getType(),
+                                       types::OBJECT_FLAG_CREATED_ARGUMENTS);
+        }
     }
 #endif
 
     return JS_TRUE;
 }
 
 JS_FRIEND_API(JSBool)
 js_SetSingleStepMode(JSContext *cx, JSScript *script, JSBool singleStep)
@@ -771,17 +773,17 @@ FindWatchPoint(JSRuntime *rt, JSObject *
     DBG_UNLOCK(rt);
     return wp;
 }
 
 JSBool
 js_watch_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
 {
     /* Capture possible effects of the calls to nativeSetSlot below. */
-    cx->addTypePropertyId(obj->getType(), id, types::TYPE_UNKNOWN);
+    types::AddTypePropertyId(cx, obj->getType(), id, types::TYPE_UNKNOWN);
 
     assertSameCompartment(cx, obj);
     JSRuntime *rt = cx->runtime;
     DBG_LOCK(rt);
     for (JSWatchPoint *wp = (JSWatchPoint *)rt->watchPointList.next;
          &wp->links != &rt->watchPointList;
          wp = (JSWatchPoint *)wp->links.next) {
         const Shape *shape = wp->shape;
@@ -1096,17 +1098,17 @@ JS_SetWatchPoint(JSContext *cx, JSObject
         return false;
 
     if (!obj->isNative()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH,
                              obj->getClass()->name);
         return false;
     }
 
-    cx->markTypePropertyConfigured(obj->getType(), propid);
+    types::MarkTypePropertyConfigured(cx, obj->getType(), propid);
 
     JSObject *pobj;
     JSProperty *prop;
     if (!js_LookupProperty(cx, obj, propid, &pobj, &prop))
         return false;
     const Shape *shape = (Shape *) prop;
     JSRuntime *rt = cx->runtime;
     if (!shape) {
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -4450,17 +4450,17 @@ JSParseNode::getConstantValue(JSContext 
             Value value;
             if (!pn->getConstantValue(cx, strictChecks, &value))
                 return false;
             if (!obj->defineProperty(cx, INT_TO_JSID(idx), value, NULL, NULL, JSPROP_ENUMERATE))
                 return false;
         }
         JS_ASSERT(idx == pn_count);
 
-        cx->fixArrayType(obj);
+        types::FixArrayType(cx, obj);
         vp->setObject(*obj);
         return true;
       }
       case TOK_RC: {
         JS_ASSERT((pn_op == JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
 
         gc::FinalizeKind kind = GuessObjectGCKind(pn_count, false);
         JSObject *obj = NewBuiltinClassInstance(cx, &js_ObjectClass, kind);
@@ -4490,17 +4490,17 @@ JSParseNode::getConstantValue(JSContext 
                     ? !js_SetPropertyHelper(cx, obj, id, 0, &value, strictChecks)
                     : !DefineNativeProperty(cx, obj, id, value, NULL, NULL,
                                             JSPROP_ENUMERATE, 0, 0)) {
                     return false;
                 }
             }
         }
 
-        cx->fixObjectType(obj);
+        types::FixObjectType(cx, obj);
         vp->setObject(*obj);
         return true;
       }
       default:
         JS_NOT_REACHED("Unexpected node");
     }
     return false;
 }
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -102,15 +102,15 @@ JS_NewObjectWithUniqueType(JSContext *cx
     if (!obj)
         return NULL;
 
     types::TypeObject *type = cx->compartment->types.newTypeObject(cx, NULL, "Unique", "",
                                                                    false, false, proto);
     if (!type)
         return NULL;
     if (obj->hasSpecialEquality())
-        cx->markTypeObjectFlags(type, types::OBJECT_FLAG_SPECIAL_EQUALITY);
+        types::MarkTypeObjectFlags(cx, type, types::OBJECT_FLAG_SPECIAL_EQUALITY);
     if (!obj->setTypeAndUniqueShape(cx, type))
         return NULL;
     type->singleton = obj;
 
     return obj;
 }
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -104,18 +104,18 @@ JSObject::getThrowTypeError() const
     return getGlobal()->getThrowTypeError();
 }
 
 JSBool
 js_GetArgsValue(JSContext *cx, StackFrame *fp, Value *vp)
 {
     JSObject *argsobj;
 
-    cx->markTypeObjectFlags(fp->fun()->getType(),
-                            OBJECT_FLAG_CREATED_ARGUMENTS | OBJECT_FLAG_UNINLINEABLE);
+    MarkTypeObjectFlags(cx, fp->fun()->getType(),
+                        OBJECT_FLAG_CREATED_ARGUMENTS | OBJECT_FLAG_UNINLINEABLE);
 
     if (fp->hasOverriddenArgs()) {
         JS_ASSERT(fp->hasCallObj());
         jsid id = ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom);
         return fp->callObj().getProperty(cx, id, vp);
     }
     argsobj = js_GetArgsObject(cx, fp);
     if (!argsobj)
@@ -1017,17 +1017,17 @@ NewDeclEnvObject(JSContext *cx, StackFra
 {
     JSObject *envobj = js_NewGCObject(cx, FINALIZE_OBJECT2);
     if (!envobj)
         return NULL;
 
     EmptyShape *emptyDeclEnvShape = EmptyShape::getEmptyDeclEnvShape(cx);
     if (!emptyDeclEnvShape)
         return NULL;
-    envobj->init(cx, &js_DeclEnvClass, cx->getTypeEmpty(), &fp->scopeChain(), fp, false);
+    envobj->init(cx, &js_DeclEnvClass, GetTypeEmpty(cx), &fp->scopeChain(), fp, false);
     envobj->setMap(emptyDeclEnvShape);
 
     return envobj;
 }
 
 namespace js {
 
 JSObject *
@@ -1607,17 +1607,17 @@ fun_getProperty(JSContext *cx, JSObject 
     JSFunction *fun = obj->getFunctionPrivate();
 
     if (slot == FUN_ARGUMENTS || slot == FUN_CALLER) {
         /*
          * Mark the function's script as uninlineable, to expand any of its
          * frames on the stack before we go looking for them.
          */
         if (fun->isInterpreted())
-            cx->markTypeObjectFlags(fun->getType(), OBJECT_FLAG_UNINLINEABLE);
+            MarkTypeObjectFlags(cx, fun->getType(), OBJECT_FLAG_UNINLINEABLE);
     }
 
     /* Find fun's top-most activation record. */
     StackFrame *fp;
     for (fp = js_GetTopStackFrame(cx, FRAME_EXPAND_NONE);
          fp && (fp->maybeFun() != fun || fp->isDirectEvalOrDebuggerFrame());
          fp = fp->prev()) {
         continue;
@@ -1625,17 +1625,17 @@ fun_getProperty(JSContext *cx, JSObject 
 
 #ifdef JS_METHODJIT
     if (slot == FUN_CALLER && fp && fp->prev()) {
         /* Also make sure the caller is uninlineable. */
         JSInlinedSite *inlined;
         fp->prev()->pc(cx, fp, &inlined);
         if (inlined) {
             JSFunction *fun = fp->prev()->jit()->inlineFrames()[inlined->inlineIndex].fun;
-            cx->markTypeObjectFlags(fun->getType(), OBJECT_FLAG_UNINLINEABLE);
+            MarkTypeObjectFlags(cx, fun->getType(), OBJECT_FLAG_UNINLINEABLE);
         }
     }
 #endif
 
     switch (slot) {
       case FUN_ARGUMENTS:
         /* Warn if strict about f.arguments or equivalent unqualified uses. */
         if (!JS_ReportErrorFlagsAndNumber(cx,
@@ -2732,17 +2732,17 @@ js_InitFunctionClass(JSContext *cx, JSOb
 
     /*
      * The default 'new' object for Function.prototype has unknown properties.
      * This will be used for generic scripted functions, e.g. from non-compileAndGo code.
      */
     TypeObject *newType = proto->getNewType(cx);
     if (!newType)
         return NULL;
-    cx->markTypeObjectUnknownProperties(newType);
+    MarkTypeObjectUnknownProperties(cx, newType);
 
     JSFunction *fun = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, obj, NULL, NULL, NULL);
     if (!fun)
         return NULL;
     fun->flags |= JSFUN_PROTOTYPE;
 
     JSScript *script = JSScript::NewScript(cx, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, JSVERSION_DEFAULT);
     if (!script)
@@ -2903,17 +2903,17 @@ js_CloneFunctionObject(JSContext *cx, JS
             js_CallNewScriptHook(cx, cfun->script(), cfun);
         } else {
             TypeObject *type = cx->compartment->types.newTypeObject(cx, NULL, "ClonedFunction", "",
                                                                     true, false,
                                                                     clone->getProto());
             if (!type || !clone->setTypeAndUniqueShape(cx, type))
                 return NULL;
             if (fun->getType()->unknownProperties())
-                cx->markTypeObjectUnknownProperties(type);
+                MarkTypeObjectUnknownProperties(cx, type);
             else
                 type->asFunction()->handler = fun->getType()->asFunction()->handler;
         }
     }
     return clone;
 }
 
 #ifdef JS_TRACER
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -1364,30 +1364,27 @@ TypeConstraintTransformThis::newType(JSC
 /////////////////////////////////////////////////////////////////////
 // Freeze constraints
 /////////////////////////////////////////////////////////////////////
 
 /* Constraint which marks all types as pushed by some bytecode. */
 class TypeConstraintPushAll : public TypeConstraint
 {
 public:
-    const jsbytecode *pc;
-
-    TypeConstraintPushAll(JSScript *script, const jsbytecode *pc)
+    jsbytecode *pc;
+
+    TypeConstraintPushAll(JSScript *script, jsbytecode *pc)
         : TypeConstraint("pushAll", script), pc(pc)
     {}
 
-    void newType(JSContext *cx, TypeSet *source, jstype type)
-    {
-        cx->compartment->types.dynamicPush(cx, script, pc - script->code, type);
-    }
+    void newType(JSContext *cx, TypeSet *source, jstype type);
 };
 
 void
-TypeSet::pushAllTypes(JSContext *cx, JSScript *script, const jsbytecode *pc)
+TypeSet::pushAllTypes(JSContext *cx, JSScript *script, jsbytecode *pc)
 {
     add(cx, ArenaNew<TypeConstraintPushAll>(cx->compartment->pool, script, pc));
 }
 
 /* Constraint which triggers recompilation of a script if any type is added to a type set. */
 class TypeConstraintFreeze : public TypeConstraint
 {
 public:
@@ -2015,214 +2012,16 @@ TypeCompartment::growPendingArray(JSCont
     memcpy(newArray, pendingArray, pendingCount * sizeof(PendingWork));
     cx->free_(pendingArray);
 
     pendingArray = newArray;
     pendingCapacity = newCapacity;
 }
 
 void
-TypeCompartment::dynamicCall(JSContext *cx, JSObject *callee,
-                             const js::CallArgs &args, bool constructing)
-{
-    unsigned nargs = callee->getFunctionPrivate()->nargs;
-    JSScript *script = callee->getFunctionPrivate()->script();
-
-    if (!script->ensureTypeArray(cx))
-        return;
-
-    if (constructing) {
-        script->typeSetNewCalled(cx);
-    } else {
-        jstype type = GetValueType(cx, args.thisv());
-        script->typeSetThis(cx, type);
-    }
-
-    /*
-     * Add constraints going up to the minimum of the actual and formal count.
-     * If there are more actuals than formals the later values can only be
-     * accessed through the arguments object, which is monitored.
-     */
-    unsigned arg = 0;
-    for (; arg < args.argc() && arg < nargs; arg++)
-        script->typeSetArgument(cx, arg, args[arg]);
-
-    /* Watch for fewer actuals than formals to the call. */
-    for (; arg < nargs; arg++)
-        script->typeSetArgument(cx, arg, UndefinedValue());
-}
-
-/* Intermediate type information for a dynamic type pushed in a script. */
-class TypeIntermediatePushed : public TypeIntermediate
-{
-    uint32 offset;
-    jstype type;
-
-  public:
-    TypeIntermediatePushed(uint32 offset, jstype type)
-        : offset(offset), type(type)
-    {}
-
-    void replay(JSContext *cx, JSScript *script)
-    {
-        TypeSet *pushed = script->analysis(cx)->pushedTypes(offset);
-        pushed->addType(cx, type);
-    }
-
-    bool hasDynamicResult(uint32 offset, jstype type) {
-        return this->offset == offset && this->type == type;
-    }
-
-    bool sweep(JSContext *cx, JSCompartment *compartment)
-    {
-        if (!TypeIsObject(type))
-            return true;
-
-        TypeObject *object = (TypeObject *) type;
-        if (object->marked)
-            return true;
-
-        if (object->unknownProperties()) {
-            type = (jstype) &compartment->types.typeEmpty;
-            return true;
-        }
-
-        return false;
-    }
-};
-
-void
-TypeCompartment::dynamicPush(JSContext *cx, JSScript *script, uint32 offset, jstype type)
-{
-    JS_ASSERT(cx->typeInferenceEnabled());
-    AutoEnterTypeInference enter(cx);
-
-    jsbytecode *pc = script->code + offset;
-    UntrapOpcode untrap(cx, script, pc);
-
-    /* Directly update associated type sets for applicable bytecodes. */
-    if (CanHaveReadBarrier(pc)) {
-        TypeSet *types = script->bytecodeTypes(pc);
-        if (!types->hasType(type)) {
-            InferSpew(ISpewOps, "externalType: monitorResult #%u:%05u: %s",
-                      script->id(), offset, TypeString(type));
-            types->addType(cx, type);
-        }
-        return;
-    }
-
-    /*
-     * For inc/dec ops, we need to go back and reanalyze the affected opcode
-     * taking the overflow into account. We won't see an explicit adjustment
-     * of the type of the thing being inc/dec'ed, nor will adding TYPE_DOUBLE to
-     * the pushed value affect that type. We only handle inc/dec operations
-     * that do not have an object lvalue; INCNAME/INCPROP/INCELEM and friends
-     * should call addTypeProperty to reflect the property change.
-     */
-    JSOp op = JSOp(*pc);
-    const JSCodeSpec *cs = &js_CodeSpec[op];
-    if (cs->format & (JOF_INC | JOF_DEC)) {
-        switch (op) {
-          case JSOP_INCGNAME:
-          case JSOP_DECGNAME:
-          case JSOP_GNAMEINC:
-          case JSOP_GNAMEDEC: {
-            jsid id = GetAtomId(cx, script, pc, 0);
-            TypeObject *global = script->getGlobalType();
-            if (!global->unknownProperties()) {
-                TypeSet *types = global->getProperty(cx, id, true);
-                if (!types)
-                    break;
-                types->addType(cx, type);
-            }
-            break;
-          }
-
-          case JSOP_INCLOCAL:
-          case JSOP_DECLOCAL:
-          case JSOP_LOCALINC:
-          case JSOP_LOCALDEC:
-          case JSOP_INCARG:
-          case JSOP_DECARG:
-          case JSOP_ARGINC:
-          case JSOP_ARGDEC: {
-            /*
-             * Just mark the slot's type as holding the new type. This captures
-             * the effect if the slot is not being tracked, and if the slot
-             * doesn't escape we will update the pushed types below to capture
-             * the slot's value after this write.
-             */
-            uint32 slot = GetBytecodeSlot(script, pc);
-            if (slot < TotalSlots(script)) {
-                TypeSet *types = script->slotTypes(slot);
-                types->addType(cx, type);
-            }
-            break;
-          }
-
-          default:;
-        }
-    }
-
-    if (script->hasAnalysis() && script->analysis(cx)->ranInference()) {
-        /*
-         * If the pushed set already has this type, we don't need to ensure
-         * there is a TypeIntermediate. Either there already is one, or the
-         * type could be determined from the script's other input type sets.
-         */
-        TypeSet *pushed = script->analysis(cx)->pushedTypes(offset, 0);
-        if (pushed->hasType(type))
-            return;
-    } else {
-        /* Scan all intermediate types on the script to check for a dupe. */
-        TypeIntermediate *result, **presult = &script->intermediateTypes;
-        while (*presult) {
-            result = *presult;
-            if (result->hasDynamicResult(offset, type)) {
-                if (presult != &script->intermediateTypes) {
-                    /* Move to the head of the list, maintain LRU order. */
-                    *presult = result->next;
-                    result->next = script->intermediateTypes;
-                    script->intermediateTypes = result;
-                }
-                return;
-            }
-            presult = &result->next;
-        }
-    }
-
-    InferSpew(ISpewOps, "externalType: monitorResult #%u:%05u: %s",
-               script->id(), offset, TypeString(type));
-
-    TypeIntermediatePushed *result = cx->new_<TypeIntermediatePushed>(offset, type);
-    if (!result) {
-        setPendingNukeTypes(cx);
-        return;
-    }
-    script->addIntermediateType(result);
-
-    if (script->hasAnalysis() && script->analysis(cx)->ranInference()) {
-        TypeSet *pushed = script->analysis(cx)->pushedTypes(offset, 0);
-        pushed->addType(cx, type);
-    } else if (script->ranInference) {
-        /* Any new dynamic result triggers reanalysis and recompilation. */
-        ScriptAnalysis *analysis = script->analysis(cx);
-        if (!analysis) {
-            setPendingNukeTypes(cx);
-            return;
-        }
-        analysis->analyzeTypes(cx);
-    }
-
-    /* Trigger recompilation of any inline callers. */
-    if (script->fun)
-        ObjectStateChange(cx, script->fun->getType(), false, true);
-}
-
-void
 TypeCompartment::processPendingRecompiles(JSContext *cx)
 {
     /* Steal the list of scripts to recompile, else we will try to recursively recompile them. */
     Vector<JSScript*> *pending = pendingRecompiles;
     pendingRecompiles = NULL;
 
     JS_ASSERT(!pending->empty());
 
@@ -2576,17 +2375,17 @@ TypeCompartment::fixArrayType(JSContext 
 
         TypeObject *objType = newTypeObject(cx, NULL, name, "", false, true, obj->getProto());
         if (!objType) {
             cx->compartment->types.setPendingNukeTypes(cx);
             return;
         }
         obj->setType(objType);
 
-        cx->addTypePropertyId(objType, JSID_VOID, type);
+        AddTypePropertyId(cx, objType, JSID_VOID, type);
 
         if (!arrayTypeTable->relookupOrAdd(p, key, objType)) {
             cx->compartment->types.setPendingNukeTypes(cx);
             return;
         }
     }
 }
 
@@ -2669,17 +2468,17 @@ TypeCompartment::fixObjectType(JSContext
             jstype ntype = GetValueType(cx, obj->getSlot(i));
             if (ntype != types[i]) {
                 if (NumberTypes(ntype, types[i])) {
                     if (types[i] == TYPE_INT32) {
                         types[i] = TYPE_DOUBLE;
                         const Shape *shape = baseShape;
                         while (!JSID_IS_EMPTY(shape->propid)) {
                             if (shape->slot == i) {
-                                cx->addTypePropertyId(p->value.object, shape->propid, TYPE_DOUBLE);
+                                AddTypePropertyId(cx, p->value.object, shape->propid, TYPE_DOUBLE);
                                 break;
                             }
                             shape = shape->previous();
                         }
                     }
                 } else {
                     return;
                 }
@@ -2726,17 +2525,17 @@ TypeCompartment::fixObjectType(JSContext
             cx->compartment->types.setPendingNukeTypes(cx);
             return;
         }
 
         const Shape *shape = baseShape;
         while (!JSID_IS_EMPTY(shape->propid)) {
             ids[shape->slot] = shape->propid;
             types[shape->slot] = GetValueType(cx, obj->getSlot(shape->slot));
-            cx->addTypePropertyId(objType, shape->propid, types[shape->slot]);
+            AddTypePropertyId(cx, objType, shape->propid, types[shape->slot]);
             shape = shape->previous();
         }
 
         /* Construct the new shape. */
         for (unsigned i = 0; i < obj->slotSpan(); i++) {
             if (!DefineNativeProperty(cx, xobj, ids[i], UndefinedValue(), NULL, NULL,
                                       JSPROP_ENUMERATE, 0, 0, DNP_SKIP_TYPE)) {
                 cx->compartment->types.setPendingNukeTypes(cx);
@@ -2902,19 +2701,139 @@ TypeObject::addDefiniteProperties(JSCont
             types->setDefinite(shape->slot);
         }
         shape = shape->previous();
     }
 
     return true;
 }
 
+inline void
+InlineAddTypeProperty(JSContext *cx, TypeObject *obj, jsid id, jstype type)
+{
+    /* Convert string index properties into the common index property. */
+    id = MakeTypeId(cx, id);
+
+    AutoEnterTypeInference enter(cx);
+
+    TypeSet *types = obj->getProperty(cx, id, true);
+    if (!types || types->hasType(type))
+        return;
+
+    InferSpew(ISpewOps, "externalType: property %s %s: %s",
+              obj->name(), TypeIdString(id), TypeString(type));
+    types->addType(cx, type);
+}
+
+void
+TypeObject::addPropertyType(JSContext *cx, jsid id, jstype type)
+{
+    InlineAddTypeProperty(cx, this, id, type);
+}
+
+void
+TypeObject::addPropertyType(JSContext *cx, jsid id, const Value &value)
+{
+    InlineAddTypeProperty(cx, this, id, GetValueType(cx, value));
+}
+
+void
+TypeObject::addPropertyType(JSContext *cx, const char *name, jstype type)
+{
+    jsid id = JSID_VOID;
+    if (name) {
+        JSAtom *atom = js_Atomize(cx, name, strlen(name));
+        if (!atom) {
+            AutoEnterTypeInference enter(cx);
+            cx->compartment->types.setPendingNukeTypes(cx);
+            return;
+        }
+        id = ATOM_TO_JSID(atom);
+    }
+    InlineAddTypeProperty(cx, this, id, type);
+}
+
+void
+TypeObject::addPropertyType(JSContext *cx, const char *name, const Value &value)
+{
+    addPropertyType(cx, name, GetValueType(cx, value));
+}
+
+void
+TypeObject::addPropertyTypeSet(JSContext *cx, jsid id, ClonedTypeSet *set)
+{
+    AutoEnterTypeInference enter(cx);
+
+    TypeSet *types = getProperty(cx, id, true);
+    if (!types)
+        return;
+
+    InferSpew(ISpewOps, "externalType: property %s %s", name(), TypeIdString(id));
+    types->addTypeSet(cx, set);
+}
+
+void
+TypeObject::aliasProperties(JSContext *cx, jsid first, jsid second)
+{
+    AutoEnterTypeInference enter(cx);
+
+    first = MakeTypeId(cx, first);
+    second = MakeTypeId(cx, second);
+
+    TypeSet *firstTypes = getProperty(cx, first, true);
+    TypeSet *secondTypes = getProperty(cx, second, true);
+    if (!firstTypes || !secondTypes)
+        return;
+
+    firstTypes->addBaseSubset(cx, this, secondTypes);
+    secondTypes->addBaseSubset(cx, this, firstTypes);
+}
+
+void
+TypeObject::markPropertyConfigured(JSContext *cx, jsid id)
+{
+    AutoEnterTypeInference enter(cx);
+
+    id = MakeTypeId(cx, id);
+
+    TypeSet *types = getProperty(cx, id, true);
+    if (types)
+        types->setOwnProperty(cx, true);
+}
+
+void
+TypeObject::markSlotReallocation(JSContext *cx)
+{
+    /*
+     * Constraints listening for reallocation will trigger recompilation if
+     * newObjectState is invoked with 'force' set to true.
+     */
+    AutoEnterTypeInference enter(cx);
+    TypeSet *types = getProperty(cx, JSID_VOID, false);
+    if (types) {
+        TypeConstraint *constraint = types->constraintList;
+        while (constraint) {
+            constraint->newObjectState(cx, this, true);
+            constraint = constraint->next;
+        }
+    }
+}
+
+
+
+
+
+
+
+
 void
 TypeObject::setFlags(JSContext *cx, TypeObjectFlags flags)
 {
+    AutoEnterTypeInference enter(cx);
+
     JS_ASSERT(cx->compartment->activeInference);
     JS_ASSERT((this->flags & flags) != flags);
 
     JSScript *fixArgsScript = NULL;
     if ((flags & ~this->flags & OBJECT_FLAG_CREATED_ARGUMENTS) && isFunction) {
         TypeFunction *fun = asFunction();
         if (fun->script && fun->script->usedLazyArgs)
             fixArgsScript = fun->script;
@@ -2928,16 +2847,18 @@ TypeObject::setFlags(JSContext *cx, Type
     InferSpew(ISpewOps, "%s: setFlags %u", name(), flags);
 
     ObjectStateChange(cx, this, false, false);
 }
 
 void
 TypeObject::markUnknown(JSContext *cx)
 {
+    AutoEnterTypeInference enter(cx);
+
     JS_ASSERT(cx->compartment->activeInference);
     JS_ASSERT(!unknownProperties());
 
     InferSpew(ISpewOps, "UnknownProperties: %s", name());
 
     ObjectStateChange(cx, this, true, true);
 
     /* Mark existing instances as unknown. */
@@ -3805,17 +3726,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
                  * be caught with dynamic monitoring.
                  */
                 TypeSet *types = initializer->getProperty(cx, JSID_VOID, true);
                 if (!types)
                     return false;
                 if (state.hasGetSet)
                     types->addType(cx, TYPE_UNKNOWN);
                 else if (state.hasHole)
-                    cx->markTypeObjectFlags(initializer, js::types::OBJECT_FLAG_NON_PACKED_ARRAY);
+                    MarkTypeObjectFlags(cx, initializer, OBJECT_FLAG_NON_PACKED_ARRAY);
                 else
                     poppedTypes(pc, 0)->addSubset(cx, script, types);
             }
         } else {
             pushed[0].addType(cx, TYPE_UNKNOWN);
         }
         state.hasGetSet = false;
         state.hasHole = false;
@@ -4126,42 +4047,41 @@ ScriptAnalysis::analyzeTypes(JSContext *
     if (!script->usesArguments)
         return;
 
     /*
      * Do additional analysis to determine whether the arguments object in the
      * script can escape.
      */
 
-    if (script->fun->getType()->hasAnyFlags(types::OBJECT_FLAG_CREATED_ARGUMENTS))
+    if (script->fun->getType()->hasAnyFlags(OBJECT_FLAG_CREATED_ARGUMENTS))
         return;
 
     /*
      * Note: don't check for strict mode code here, even though arguments
      * accesses in such scripts will always be deoptimized. These scripts can
      * have a JSOP_ARGUMENTS in their prologue which the usesArguments check
      * above does not account for. We filter in the interpreter and JITs
      * themselves.
      */
     if (script->fun->isHeavyweight() || cx->compartment->debugMode) {
-        cx->markTypeObjectFlags(script->fun->getType(),
-                                types::OBJECT_FLAG_CREATED_ARGUMENTS);
+        MarkTypeObjectFlags(cx, script->fun->getType(), OBJECT_FLAG_CREATED_ARGUMENTS);
         return;
     }
 
     offset = 0;
     while (offset < script->length) {
         Bytecode *code = maybeCode(offset);
         jsbytecode *pc = script->code + offset;
 
         if (code && JSOp(*pc) == JSOP_ARGUMENTS) {
             Vector<SSAValue> seen(cx);
             if (!followEscapingArguments(cx, SSAValue::PushedValue(offset, 0), &seen)) {
-                cx->markTypeObjectFlags(script->fun->getType(),
-                                        types::OBJECT_FLAG_CREATED_ARGUMENTS);
+                MarkTypeObjectFlags(cx, script->fun->getType(),
+                                    OBJECT_FLAG_CREATED_ARGUMENTS);
                 return;
             }
         }
 
         offset += GetBytecodeLength(pc);
     }
 
     /*
@@ -4729,16 +4649,299 @@ ScriptAnalysis::printTypes(JSContext *cx
 
     printf("\n");
 
 #endif /* DEBUG */
 
 }
 
 /////////////////////////////////////////////////////////////////////
+// Interface functions
+/////////////////////////////////////////////////////////////////////
+
+namespace js { namespace types {
+
+void
+MarkTypeCallerUnexpectedSlow(JSContext *cx, jstype type)
+{
+    /*
+     * Check that we are actually at a scripted callsite. This function is
+     * called from JS natives which can be called anywhere a script can be
+     * called, such as on property getters or setters. This filtering is not
+     * perfect, but we only need to make sure the type result is added wherever
+     * the native's type handler was used, i.e. at scripted callsites directly
+     * calling the native.
+     */
+
+    StackFrame *caller = js_GetScriptedCaller(cx, NULL);
+    if (!caller)
+        return;
+
+    /*
+     * Watch out if the caller is in a different compartment from this one.
+     * This must have gone through a cross-compartment wrapper.
+     */
+    if (caller->script()->compartment != cx->compartment)
+        return;
+
+    JSScript *script;
+    jsbytecode *pc = caller->inlinepc(cx, &script);
+
+    js::analyze::UntrapOpcode untrap(cx, script, pc);
+
+    switch ((JSOp)*pc) {
+      case JSOP_CALL:
+      case JSOP_EVAL:
+      case JSOP_FUNCALL:
+      case JSOP_FUNAPPLY:
+      case JSOP_NEW:
+        break;
+      case JSOP_ITER:
+        /* This is also used for handling custom iterators. */
+        break;
+      default:
+        return;
+    }
+
+    TypeDynamicResult(cx, script, pc, type);
+}
+
+void
+MarkTypeCallerUnexpectedSlow(JSContext *cx, const Value &value)
+{
+    MarkTypeCallerUnexpectedSlow(cx, GetValueType(cx, value));
+}
+
+void
+TypeMonitorCallSlow(JSContext *cx, JSObject *callee,
+                    const CallArgs &args, bool constructing)
+{
+    unsigned nargs = callee->getFunctionPrivate()->nargs;
+    JSScript *script = callee->getFunctionPrivate()->script();
+
+    if (!script->ensureTypeArray(cx))
+        return;
+
+    if (constructing) {
+        script->typeSetNewCalled(cx);
+    } else {
+        jstype type = GetValueType(cx, args.thisv());
+        script->typeSetThis(cx, type);
+    }
+
+    /*
+     * Add constraints going up to the minimum of the actual and formal count.
+     * If there are more actuals than formals the later values can only be
+     * accessed through the arguments object, which is monitored.
+     */
+    unsigned arg = 0;
+    for (; arg < args.argc() && arg < nargs; arg++)
+        script->typeSetArgument(cx, arg, args[arg]);
+
+    /* Watch for fewer actuals than formals to the call. */
+    for (; arg < nargs; arg++)
+        script->typeSetArgument(cx, arg, UndefinedValue());
+}
+
+/* Intermediate type information for a dynamic type pushed in a script. */
+class TypeIntermediatePushed : public TypeIntermediate
+{
+    uint32 offset;
+    jstype type;
+
+  public:
+    TypeIntermediatePushed(uint32 offset, jstype type)
+        : offset(offset), type(type)
+    {}
+
+    void replay(JSContext *cx, JSScript *script)
+    {
+        TypeSet *pushed = script->analysis(cx)->pushedTypes(offset);
+        pushed->addType(cx, type);
+    }
+
+    bool hasDynamicResult(uint32 offset, jstype type) {
+        return this->offset == offset && this->type == type;
+    }
+
+    bool sweep(JSContext *cx, JSCompartment *compartment)
+    {
+        if (!TypeIsObject(type))
+            return true;
+
+        TypeObject *object = (TypeObject *) type;
+        if (object->marked)
+            return true;
+
+        if (object->unknownProperties()) {
+            type = (jstype) &compartment->types.typeEmpty;
+            return true;
+        }
+
+        return false;
+    }
+};
+
+void
+TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, jstype type)
+{
+    JS_ASSERT(cx->typeInferenceEnabled());
+    AutoEnterTypeInference enter(cx);
+
+    UntrapOpcode untrap(cx, script, pc);
+
+    /* Directly update associated type sets for applicable bytecodes. */
+    if (CanHaveReadBarrier(pc)) {
+        TypeSet *types = script->bytecodeTypes(pc);
+        if (!types->hasType(type)) {
+            InferSpew(ISpewOps, "externalType: monitorResult #%u:%05u: %s",
+                      script->id(), pc - script->code, TypeString(type));
+            types->addType(cx, type);
+        }
+        return;
+    }
+
+    /*
+     * For inc/dec ops, we need to go back and reanalyze the affected opcode
+     * taking the overflow into account. We won't see an explicit adjustment
+     * of the type of the thing being inc/dec'ed, nor will adding TYPE_DOUBLE to
+     * the pushed value affect that type. We only handle inc/dec operations
+     * that do not have an object lvalue; INCNAME/INCPROP/INCELEM and friends
+     * should call addTypeProperty to reflect the property change.
+     */
+    JSOp op = JSOp(*pc);
+    const JSCodeSpec *cs = &js_CodeSpec[op];
+    if (cs->format & (JOF_INC | JOF_DEC)) {
+        switch (op) {
+          case JSOP_INCGNAME:
+          case JSOP_DECGNAME:
+          case JSOP_GNAMEINC:
+          case JSOP_GNAMEDEC: {
+            jsid id = GetAtomId(cx, script, pc, 0);
+            TypeObject *global = script->getGlobalType();
+            if (!global->unknownProperties()) {
+                TypeSet *types = global->getProperty(cx, id, true);
+                if (!types)
+                    break;
+                types->addType(cx, type);
+            }
+            break;
+          }
+
+          case JSOP_INCLOCAL:
+          case JSOP_DECLOCAL:
+          case JSOP_LOCALINC:
+          case JSOP_LOCALDEC:
+          case JSOP_INCARG:
+          case JSOP_DECARG:
+          case JSOP_ARGINC:
+          case JSOP_ARGDEC: {
+            /*
+             * Just mark the slot's type as holding the new type. This captures
+             * the effect if the slot is not being tracked, and if the slot
+             * doesn't escape we will update the pushed types below to capture
+             * the slot's value after this write.
+             */
+            uint32 slot = GetBytecodeSlot(script, pc);
+            if (slot < TotalSlots(script)) {
+                TypeSet *types = script->slotTypes(slot);
+                types->addType(cx, type);
+            }
+            break;
+          }
+
+          default:;
+        }
+    }
+
+    if (script->hasAnalysis() && script->analysis(cx)->ranInference()) {
+        /*
+         * If the pushed set already has this type, we don't need to ensure
+         * there is a TypeIntermediate. Either there already is one, or the
+         * type could be determined from the script's other input type sets.
+         */
+        TypeSet *pushed = script->analysis(cx)->pushedTypes(pc, 0);
+        if (pushed->hasType(type))
+            return;
+    } else {
+        /* Scan all intermediate types on the script to check for a dupe. */
+        TypeIntermediate *result, **presult = &script->intermediateTypes;
+        while (*presult) {
+            result = *presult;
+            if (result->hasDynamicResult(pc - script->code, type)) {
+                if (presult != &script->intermediateTypes) {
+                    /* Move to the head of the list, maintain LRU order. */
+                    *presult = result->next;
+                    result->next = script->intermediateTypes;
+                    script->intermediateTypes = result;
+                }
+                return;
+            }
+            presult = &result->next;
+        }
+    }
+
+    InferSpew(ISpewOps, "externalType: monitorResult #%u:%05u: %s",
+              script->id(), pc - script->code, TypeString(type));
+
+    TypeIntermediatePushed *result = cx->new_<TypeIntermediatePushed>(pc - script->code, type);
+    if (!result) {
+        cx->compartment->types.setPendingNukeTypes(cx);
+        return;
+    }
+    script->addIntermediateType(result);
+
+    if (script->hasAnalysis() && script->analysis(cx)->ranInference()) {
+        TypeSet *pushed = script->analysis(cx)->pushedTypes(pc, 0);
+        pushed->addType(cx, type);
+    } else if (script->ranInference) {
+        /* Any new dynamic result triggers reanalysis and recompilation. */
+        ScriptAnalysis *analysis = script->analysis(cx);
+        if (!analysis) {
+            cx->compartment->types.setPendingNukeTypes(cx);
+            return;
+        }
+        analysis->analyzeTypes(cx);
+    }
+
+    /* Trigger recompilation of any inline callers. */
+    if (script->fun)
+        ObjectStateChange(cx, script->fun->getType(), false, true);
+}
+
+void
+TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval)
+{
+    UntrapOpcode untrap(cx, script, pc);
+
+    /* Allow the non-TYPESET scenario to simplify stubs invoked by INC* ops. Yuck. */
+    if (!(js_CodeSpec[*pc].format & JOF_TYPESET))
+        return;
+
+    jstype type = GetValueType(cx, rval);
+    TypeSet *types = script->bytecodeTypes(pc);
+    if (types->hasType(type))
+        return;
+
+    AutoEnterTypeInference enter(cx);
+
+    InferSpew(ISpewOps, "bytecodeType: #%u:%05u: %s",
+              script->id(), pc - script->code, TypeString(type));
+    types->addType(cx, type);
+}
+
+} } /* namespace js::types */
+
+void
+TypeConstraintPushAll::newType(JSContext *cx, TypeSet *source, jstype type)
+{
+    TypeDynamicResult(cx, script, pc, type);
+}
+
+/////////////////////////////////////////////////////////////////////
 // JSScript
 /////////////////////////////////////////////////////////////////////
 
 /*
  * Returns true if we don't expect to compute the correct types for some value
  * pushed by the specified bytecode.
  */
 static inline bool
@@ -4889,17 +5092,17 @@ JSScript::typeCheckBytecode(JSContext *c
     for (int i = 0; i < defCount; i++) {
         const js::Value &val = sp[-defCount + i];
         TypeSet *types = analysis_->pushedTypes(pc, i);
         if (IgnorePushed(pc, i))
             continue;
 
         jstype type = GetValueType(cx, val);
 
-        if (!types::TypeMatches(cx, types, type)) {
+        if (!TypeMatches(cx, types, type)) {
             TypeFailure(cx, "Missing type at #%u:%05u pushed %u: %s",
                                    id(), pc - code, i, TypeString(type));
         }
 
         if (TypeIsObject(type)) {
             JS_ASSERT(val.isObject());
             JSObject *obj = &val.toObject();
             TypeObject *object = (TypeObject *) type;
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -423,17 +423,17 @@ class TypeSet
 
     /* Get whether this type set is non-empty. */
     bool knownNonEmpty(JSContext *cx);
 
     /* Get the single value which can appear in this type set, otherwise NULL. */
     JSObject *getSingleton(JSContext *cx);
 
     /* Mark all current and future types in this set as pushed by script/pc. */
-    void pushAllTypes(JSContext *cx, JSScript *script, const jsbytecode *pc);
+    void pushAllTypes(JSContext *cx, JSScript *script, jsbytecode *pc);
 
     /*
      * Clone (possibly NULL) source onto target; if any new types are added to
      * source in the future, the script will be recompiled.
      */
     static void Clone(JSContext *cx, TypeSet *source, ClonedTypeSet *target);
 
     /* Set of scripts which condensed constraints have been generated for. */
@@ -700,16 +700,24 @@ struct TypeObject
     inline unsigned getPropertyCount();
     inline Property *getProperty(unsigned i);
 
     /* Helpers */
 
     bool addProperty(JSContext *cx, jsid id, Property **pprop);
     bool addDefiniteProperties(JSContext *cx, JSObject *obj);
     void addPrototype(JSContext *cx, TypeObject *proto);
+    void addPropertyType(JSContext *cx, jsid id, jstype type);
+    void addPropertyType(JSContext *cx, jsid id, const Value &value);
+    void addPropertyType(JSContext *cx, const char *name, jstype type);
+    void addPropertyType(JSContext *cx, const char *name, const Value &value);
+    void addPropertyTypeSet(JSContext *cx, jsid id, ClonedTypeSet *set);
+    void markPropertyConfigured(JSContext *cx, jsid id);
+    void aliasProperties(JSContext *cx, jsid first, jsid second);
+    void markSlotReallocation(JSContext *cx);
     void setFlags(JSContext *cx, TypeObjectFlags flags);
     void markUnknown(JSContext *cx);
     void clearNewScript(JSContext *cx);
     void storeToInstances(JSContext *cx, Property *base);
     void getFromPrototypes(JSContext *cx, Property *base);
 
     void print(JSContext *cx);
     void trace(JSTracer *trc);
@@ -880,23 +888,16 @@ struct TypeCompartment
     TypeObject *newTypeObject(JSContext *cx, JSScript *script,
                               const char *base, const char *postfix,
                               bool isFunction, bool isArray, JSObject *proto);
 
     /* Make an initializer object. */
     TypeObject *newInitializerTypeObject(JSContext *cx, JSScript *script,
                                          uint32 offset, bool isArray);
 
-    /*
-     * Add the specified type to the specified set, do any necessary reanalysis
-     * stemming from the change and recompile any affected scripts.
-     */
-    void dynamicPush(JSContext *cx, JSScript *script, uint32 offset, jstype type);
-    void dynamicCall(JSContext *cx, JSObject *callee, const CallArgs &args, bool constructing);
-
     void nukeTypes(JSContext *cx);
     void processPendingRecompiles(JSContext *cx);
 
     /* Mark all types as needing destruction once inference has 'finished'. */
     void setPendingNukeTypes(JSContext *cx);
 
     /* Mark a script as needing recompilation once inference has finished. */
     void addPendingRecompile(JSContext *cx, JSScript *script);
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -234,294 +234,212 @@ CanHaveReadBarrier(const jsbytecode *pc)
       case JSOP_GETGLOBAL:
       case JSOP_CALLGLOBAL:
         return true;
       default:
         return false;
     }
 }
 
-} } /* namespace js::types */
-
 /////////////////////////////////////////////////////////////////////
-// JSContext
+// Interface functions
 /////////////////////////////////////////////////////////////////////
 
-inline bool
-JSContext::typeInferenceEnabled()
-{
-    return inferenceEnabled;
-}
+/*
+ * These functions check whether inference is enabled before performing some
+ * action on the type state. To avoid checking cx->typeInferenceEnabled()
+ * everywhere, it is generally preferred to use one of these functions or
+ * a type function on JSScript to perform inference operations.
+ */
 
-inline js::types::TypeObject *
-JSContext::getTypeNewObject(JSProtoKey key)
+/*
+ * Get the default 'new' object for a given standard class, per the currently
+ * active global.
+ */
+inline TypeObject *
+GetTypeNewObject(JSContext *cx, JSProtoKey key)
 {
     JSObject *proto;
-    if (!js_GetClassPrototype(this, NULL, key, &proto, NULL))
+    if (!js_GetClassPrototype(cx, NULL, key, &proto, NULL))
         return NULL;
-    return proto->getNewType(this);
+    return proto->getNewType(cx);
 }
 
-inline js::types::TypeObject *
-JSContext::getTypeCallerInitObject(bool isArray)
+/* Get a type object for the immediate allocation site within a native. */
+inline TypeObject *
+GetTypeCallerInitObject(JSContext *cx, bool isArray)
 {
-    if (typeInferenceEnabled()) {
-        js::StackFrame *caller = js_GetScriptedCaller(this, NULL);
-        if (caller && caller->script()->compartment == compartment) {
+    if (cx->typeInferenceEnabled()) {
+        StackFrame *caller = js_GetScriptedCaller(cx, NULL);
+        if (caller && caller->script()->compartment == cx->compartment) {
             JSScript *script;
-            jsbytecode *pc = caller->inlinepc(this, &script);
-            return script->getTypeInitObject(this, pc, isArray);
+            jsbytecode *pc = caller->inlinepc(cx, &script);
+            return script->getTypeInitObject(cx, pc, isArray);
         }
     }
-    return getTypeNewObject(isArray ? JSProto_Array : JSProto_Object);
+    return GetTypeNewObject(cx, isArray ? JSProto_Array : JSProto_Object);
+}
+
+/* Mark the immediate scripted caller of a native as having produced an unexpected value. */
+inline void
+MarkTypeCallerUnexpected(JSContext *cx, jstype type)
+{
+    extern void MarkTypeCallerUnexpectedSlow(JSContext *cx, jstype type);
+
+    if (cx->typeInferenceEnabled())
+        MarkTypeCallerUnexpectedSlow(cx, type);
 }
 
 inline void
-JSContext::markTypeCallerUnexpected(js::types::jstype type)
+MarkTypeCallerUnexpected(JSContext *cx, const Value &value)
 {
-    if (!typeInferenceEnabled())
-        return;
-
-    /*
-     * Check that we are actually at a scripted callsite. This function is
-     * called from JS natives which can be called anywhere a script can be
-     * called, such as on property getters or setters. This filtering is not
-     * perfect, but we only need to make sure the type result is added wherever
-     * the native's type handler was used, i.e. at scripted callsites directly
-     * calling the native.
-     */
-
-    js::StackFrame *caller = js_GetScriptedCaller(this, NULL);
-    if (!caller)
-        return;
+    extern void MarkTypeCallerUnexpectedSlow(JSContext *cx, const Value &value);
 
-    /*
-     * Watch out if the caller is in a different compartment from this one.
-     * This must have gone through a cross-compartment wrapper.
-     */
-    if (caller->script()->compartment != compartment)
-        return;
-
-    JSScript *script;
-    jsbytecode *pc = caller->inlinepc(this, &script);
-
-    js::analyze::UntrapOpcode untrap(this, script, pc);
-
-    switch ((JSOp)*pc) {
-      case JSOP_CALL:
-      case JSOP_EVAL:
-      case JSOP_FUNCALL:
-      case JSOP_FUNAPPLY:
-      case JSOP_NEW:
-        break;
-      case JSOP_ITER:
-        /* This is also used for handling custom iterators. */
-        break;
-      default:
-        return;
-    }
-
-    compartment->types.dynamicPush(this, script, pc - script->code, type);
+    if (cx->typeInferenceEnabled())
+        MarkTypeCallerUnexpectedSlow(cx, value);
 }
 
 inline void
-JSContext::markTypeCallerUnexpected(const js::Value &value)
+MarkTypeCallerOverflow(JSContext *cx)
 {
-    if (typeInferenceEnabled())
-        markTypeCallerUnexpected(js::types::GetValueType(this, value));
+    MarkTypeCallerUnexpected(cx, TYPE_DOUBLE);
 }
 
+/*
+ * Monitor a javascript call, either on entry to the interpreter or made
+ * from within the interpreter.
+ */
 inline void
-JSContext::markTypeCallerOverflow()
+TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing)
 {
-    markTypeCallerUnexpected(js::types::TYPE_DOUBLE);
+    extern void TypeMonitorCallSlow(JSContext *cx, JSObject *callee,
+                                    const CallArgs &args, bool constructing);
+
+    if (cx->typeInferenceEnabled()) {
+        JSObject *callee = &args.callee();
+        if (callee->isFunction() && callee->getFunctionPrivate()->isInterpreted())
+            TypeMonitorCallSlow(cx, callee, args, constructing);
+    }
+}
+
+/* Add a possible type for a property of obj. */
+inline void
+AddTypePropertyId(JSContext *cx, TypeObject *obj, jsid id, jstype type)
+{
+    if (cx->typeInferenceEnabled() && !obj->unknownProperties())
+        obj->addPropertyType(cx, id, type);
 }
 
 inline void
-JSContext::addTypeProperty(js::types::TypeObject *obj, const char *name, js::types::jstype type)
+AddTypePropertyId(JSContext *cx, TypeObject *obj, jsid id, const Value &value)
 {
-    if (typeInferenceEnabled() && !obj->unknownProperties()) {
-        jsid id = JSID_VOID;
-        if (name) {
-            JSAtom *atom = js_Atomize(this, name, strlen(name));
-            if (!atom) {
-                js::types::AutoEnterTypeInference enter(this);
-                compartment->types.setPendingNukeTypes(this);
-                return;
-            }
-            id = ATOM_TO_JSID(atom);
-        }
-        addTypePropertyId(obj, id, type);
-    }
-}
-
-inline void
-JSContext::addTypeProperty(js::types::TypeObject *obj, const char *name, const js::Value &value)
-{
-    if (typeInferenceEnabled() && !obj->unknownProperties())
-        addTypeProperty(obj, name, js::types::GetValueType(this, value));
+    if (cx->typeInferenceEnabled() && !obj->unknownProperties())
+        obj->addPropertyType(cx, id, value);
 }
 
 inline void
-JSContext::addTypePropertyId(js::types::TypeObject *obj, jsid id, js::types::jstype type)
-{
-    if (!typeInferenceEnabled() || obj->unknownProperties())
-        return;
-
-    /* Convert string index properties into the common index property. */
-    id = js::types::MakeTypeId(this, id);
-
-    js::types::AutoEnterTypeInference enter(this);
-
-    js::types::TypeSet *types = obj->getProperty(this, id, true);
-    if (!types || types->hasType(type))
-        return;
-
-    js::types::InferSpew(js::types::ISpewOps, "externalType: property %s %s: %s",
-                         obj->name(), js::types::TypeIdString(id),
-                         js::types::TypeString(type));
-    types->addType(this, type);
-}
-
-inline void
-JSContext::addTypePropertyId(js::types::TypeObject *obj, jsid id, const js::Value &value)
-{
-    if (typeInferenceEnabled() && !obj->unknownProperties())
-        addTypePropertyId(obj, id, js::types::GetValueType(this, value));
-}
-
-inline void
-JSContext::addTypePropertyId(js::types::TypeObject *obj, jsid id, js::types::ClonedTypeSet *set)
+AddTypeProperty(JSContext *cx, TypeObject *obj, const char *name, jstype type)
 {
-    if (obj->unknownProperties())
-        return;
-    id = js::types::MakeTypeId(this, id);
-
-    js::types::AutoEnterTypeInference enter(this);
-
-    js::types::TypeSet *types = obj->getProperty(this, id, true);
-    if (!types)
-        return;
-
-    js::types::InferSpew(js::types::ISpewOps, "externalType: property %s %s",
-                         obj->name(), js::types::TypeIdString(id));
-    types->addTypeSet(this, set);
-}
-
-inline js::types::TypeObject *
-JSContext::getTypeEmpty()
-{
-    return &compartment->types.typeEmpty;
-}
-
-inline void
-JSContext::aliasTypeProperties(js::types::TypeObject *obj, jsid first, jsid second)
-{
-    if (!typeInferenceEnabled() || obj->unknownProperties())
-        return;
-
-    js::types::AutoEnterTypeInference enter(this);
-
-    first = js::types::MakeTypeId(this, first);
-    second = js::types::MakeTypeId(this, second);
-
-    js::types::TypeSet *firstTypes = obj->getProperty(this, first, true);
-    js::types::TypeSet *secondTypes = obj->getProperty(this, second, true);
-    if (!firstTypes || !secondTypes)
-        return;
-
-    firstTypes->addBaseSubset(this, obj, secondTypes);
-    secondTypes->addBaseSubset(this, obj, firstTypes);
+    if (cx->typeInferenceEnabled() && !obj->unknownProperties())
+        obj->addPropertyType(cx, name, type);
 }
 
 inline void
-JSContext::markTypeObjectFlags(js::types::TypeObject *obj, js::types::TypeObjectFlags flags)
+AddTypeProperty(JSContext *cx, TypeObject *obj, const char *name, const Value &value)
+{
+    if (cx->typeInferenceEnabled() && !obj->unknownProperties())
+        obj->addPropertyType(cx, name, value);
+}
+
+/* Add an entire type set to a property of obj. */
+inline void
+AddTypePropertySet(JSContext *cx, TypeObject *obj, jsid id, ClonedTypeSet *set)
+{
+    if (cx->typeInferenceEnabled() && !obj->unknownProperties())
+        obj->addPropertyTypeSet(cx, id, set);
+}
+
+/* Get the default type object to use for objects with no prototype. */
+inline TypeObject *
+GetTypeEmpty(JSContext *cx)
+{
+    return &cx->compartment->types.typeEmpty;
+}
+
+/* Alias two properties in the type information for obj. */
+inline void
+AliasTypeProperties(JSContext *cx, TypeObject *obj, jsid first, jsid second)
+{
+    if (cx->typeInferenceEnabled() && !obj->unknownProperties())
+        obj->aliasProperties(cx, first, second);
+}
+
+/* Set one or more dynamic flags on a type object. */
+inline void
+MarkTypeObjectFlags(JSContext *cx, TypeObject *obj, TypeObjectFlags flags)
 {
-    if (!typeInferenceEnabled() || obj->hasAllFlags(flags))
-        return;
+    if (cx->typeInferenceEnabled() && !obj->hasAllFlags(flags))
+        obj->setFlags(cx, flags);
+}
+
+/* Mark all properties of a type object as unknown. */
+inline void
+MarkTypeObjectUnknownProperties(JSContext *cx, TypeObject *obj)
+{
+    if (cx->typeInferenceEnabled() && !obj->unknownProperties())
+        obj->markUnknown(cx);
+}
 
-    js::types::AutoEnterTypeInference enter(this);
-    obj->setFlags(this, flags);
+/*
+ * Mark any property which has been deleted or configured to be non-writable or
+ * have a getter/setter.
+ */
+inline void
+MarkTypePropertyConfigured(JSContext *cx, TypeObject *obj, jsid id)
+{
+    if (cx->typeInferenceEnabled() && !obj->unknownProperties())
+        obj->markPropertyConfigured(cx, id);
 }
 
+/* Mark a global object as having had its slots reallocated. */
+inline void
+MarkGlobalReallocation(JSContext *cx, JSObject *obj)
+{
+    JS_ASSERT(obj->isGlobal());
+    if (cx->typeInferenceEnabled() && !obj->getType()->unknownProperties())
+        obj->getType()->markSlotReallocation(cx);
+}
+
+/*
+ * For an array or object which has not yet escaped and been referenced elsewhere,
+ * pick a new type based on the object's current contents.
+ */
+
 inline void
-JSContext::markTypePropertyConfigured(js::types::TypeObject *obj, jsid id)
+FixArrayType(JSContext *cx, JSObject *obj)
 {
-    if (!typeInferenceEnabled() || obj->unknownProperties())
-        return;
-    id = js::types::MakeTypeId(this, id);
-
-    js::types::AutoEnterTypeInference enter(this);
-    js::types::TypeSet *types = obj->getProperty(this, id, true);
-    if (types)
-        types->setOwnProperty(this, true);
+    if (cx->typeInferenceEnabled())
+        cx->compartment->types.fixArrayType(cx, obj);
 }
 
 inline void
-JSContext::markGlobalReallocation(JSObject *obj)
+FixObjectType(JSContext *cx, JSObject *obj)
 {
-    JS_ASSERT(obj->isGlobal());
-
-    if (!typeInferenceEnabled() || obj->getType()->unknownProperties())
-        return;
-
-    /*
-     * Constraints listening for reallocation will trigger recompilation if
-     * newObjectState is invoked with 'force' set to true.
-     */
-    js::types::AutoEnterTypeInference enter(this);
-    js::types::TypeSet *types = obj->getType()->getProperty(this, JSID_VOID, false);
-    if (types) {
-        js::types::TypeConstraint *constraint = types->constraintList;
-        while (constraint) {
-            constraint->newObjectState(this, obj->getType(), true);
-            constraint = constraint->next;
-        }
-    }
+    if (cx->typeInferenceEnabled())
+        cx->compartment->types.fixObjectType(cx, obj);
 }
 
-inline void
-JSContext::markTypeObjectUnknownProperties(js::types::TypeObject *obj)
-{
-    if (!typeInferenceEnabled() || obj->unknownProperties())
-        return;
-
-    js::types::AutoEnterTypeInference enter(this);
-    obj->markUnknown(this);
-}
-
-inline void
-JSContext::typeMonitorCall(const js::CallArgs &args, bool constructing)
-{
-    if (!typeInferenceEnabled())
-        return;
+/* Interface helpers for JSScript */
+extern void TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval);
+extern void TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, js::types::jstype type);
 
-    JSObject *callee = &args.callee();
-    if (!callee->isFunction() || !callee->getFunctionPrivate()->isInterpreted())
-        return;
-
-    compartment->types.dynamicCall(this, callee, args, constructing);
-}
-
-inline void
-JSContext::fixArrayType(JSObject *obj)
-{
-    if (typeInferenceEnabled())
-        compartment->types.fixArrayType(this, obj);
-}
-
-inline void
-JSContext::fixObjectType(JSObject *obj)
-{
-    if (typeInferenceEnabled())
-        compartment->types.fixObjectType(this, obj);
-}
+} } /* namespace js::types */
 
 /////////////////////////////////////////////////////////////////////
-// JSScript
+// Script interface functions
 /////////////////////////////////////////////////////////////////////
 
 inline bool
 JSScript::ensureTypeArray(JSContext *cx)
 {
     if (typeArray)
         return true;
     return makeTypeArray(cx);
@@ -612,17 +530,17 @@ JSScript::getTypeNewObject(JSContext *cx
         return NULL;
     return proto->getNewType(cx);
 }
 
 inline js::types::TypeObject *
 JSScript::getTypeInitObject(JSContext *cx, const jsbytecode *pc, bool isArray)
 {
     if (!cx->typeInferenceEnabled() || !global)
-        return cx->getTypeNewObject(isArray ? JSProto_Array : JSProto_Object);
+        return js::types::GetTypeNewObject(cx, isArray ? JSProto_Array : JSProto_Object);
 
     uint32 offset = pc - code;
     js::types::TypeObject *prev = NULL, *obj = typeObjects;
     while (obj) {
         if (isArray ? obj->initializerArray : obj->initializerObject) {
             if (obj->initializerOffset == offset) {
                 /* Move this to the head of the objects list, maintain LRU order. */
                 if (prev) {
@@ -638,70 +556,56 @@ JSScript::getTypeInitObject(JSContext *c
     }
 
     return cx->compartment->types.newInitializerTypeObject(cx, this, offset, isArray);
 }
 
 inline void
 JSScript::typeMonitor(JSContext *cx, jsbytecode *pc, const js::Value &rval)
 {
-    js::analyze::UntrapOpcode untrap(cx, this, pc);
-
-    if (cx->typeInferenceEnabled() && (js_CodeSpec[*pc].format & JOF_TYPESET)) {
-        /* Allow the non-TYPESET scenario to simplify stubs invonked by INC* ops. Yuck. */
+    if (cx->typeInferenceEnabled())
+        js::types::TypeMonitorResult(cx, this, pc, rval);
+}
 
-        js::types::jstype type = js::types::GetValueType(cx, rval);
-        js::types::TypeSet *types = bytecodeTypes(pc);
-        if (types->hasType(type))
-            return;
-
-        js::types::AutoEnterTypeInference enter(cx);
-
-        js::types::InferSpew(js::types::ISpewOps, "bytecodeType: #%u:%05u: %s",
-                             id(), pc - code, js::types::TypeString(type));
-        types->addType(cx, type);
-    }
+inline void
+JSScript::typeMonitorOverflow(JSContext *cx, jsbytecode *pc)
+{
+    if (cx->typeInferenceEnabled())
+        js::types::TypeDynamicResult(cx, this, pc, js::types::TYPE_DOUBLE);
 }
 
 inline void
-JSScript::typeMonitorOverflow(JSContext *cx, const jsbytecode *pc)
+JSScript::typeMonitorString(JSContext *cx, jsbytecode *pc)
 {
     if (cx->typeInferenceEnabled())
-        cx->compartment->types.dynamicPush(cx, this, pc - code, js::types::TYPE_DOUBLE);
+        js::types::TypeDynamicResult(cx, this, pc, js::types::TYPE_STRING);
 }
 
 inline void
-JSScript::typeMonitorString(JSContext *cx, const jsbytecode *pc)
+JSScript::typeMonitorUnknown(JSContext *cx, jsbytecode *pc)
 {
     if (cx->typeInferenceEnabled())
-        cx->compartment->types.dynamicPush(cx, this, pc - code, js::types::TYPE_STRING);
+        js::types::TypeDynamicResult(cx, this, pc, js::types::TYPE_UNKNOWN);
 }
 
 inline void
-JSScript::typeMonitorUnknown(JSContext *cx, const jsbytecode *pc)
-{
-    if (cx->typeInferenceEnabled())
-        cx->compartment->types.dynamicPush(cx, this, pc - code, js::types::TYPE_UNKNOWN);
-}
-
-inline void
-JSScript::typeMonitorAssign(JSContext *cx, const jsbytecode *pc,
+JSScript::typeMonitorAssign(JSContext *cx, jsbytecode *pc,
                             JSObject *obj, jsid id, const js::Value &rval)
 {
     if (cx->typeInferenceEnabled()) {
         /*
          * Mark as unknown any object which has had dynamic assignments to
          * non-integer properties at SETELEM opcodes. This avoids making large
          * numbers of type properties for hashmap-style objects. :FIXME: this
          * is too aggressive for things like prototype library initialization.
          */
         uint32 i;
         if (js_IdIsIndex(id, &i))
             return;
-        cx->markTypeObjectUnknownProperties(obj->getType());
+        js::types::MarkTypeObjectUnknownProperties(cx, obj->getType());
     }
 }
 
 inline void
 JSScript::typeSetThis(JSContext *cx, js::types::jstype type)
 {
     JS_ASSERT(cx->typeInferenceEnabled());
     if (!ensureTypeArray(cx))
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -544,17 +544,17 @@ js_OnUnknownMethod(JSContext *cx, Value 
             if (!JSID_IS_VOID(id))
                 vp[0] = IdToValue(id);
         }
 #endif
         obj = js_NewGCObject(cx, FINALIZE_OBJECT2);
         if (!obj)
             return false;
 
-        obj->init(cx, &js_NoSuchMethodClass, cx->getTypeEmpty(), NULL, NULL, false);
+        obj->init(cx, &js_NoSuchMethodClass, GetTypeEmpty(cx), NULL, NULL, false);
         obj->setSharedNonNativeMap();
         obj->setSlot(JSSLOT_FOUND_FUNCTION, tvr.value());
         obj->setSlot(JSSLOT_SAVED_ID, vp[0]);
         vp[0].setObject(*obj);
     }
     return true;
 }
 
@@ -647,17 +647,17 @@ Invoke(JSContext *cx, const CallArgs &ar
         if (JS_UNLIKELY(clasp == &js_NoSuchMethodClass))
             return NoSuchMethod(cx, args.argc(), args.base());
 #endif
         JS_ASSERT_IF(option == INVOKE_CONSTRUCTOR, !clasp->construct);
         if (!clasp->call) {
             js_ReportIsNotFunction(cx, &args.calleev(), ToReportFlags(option));
             return false;
         }
-        cx->markTypeCallerUnexpected(types::TYPE_UNKNOWN);
+        MarkTypeCallerUnexpected(cx, types::TYPE_UNKNOWN);
         return CallJSNative(cx, clasp->call, args.argc(), args.base());
     }
 
     /* Invoke native functions. */
     JSFunction *fun = callee.getFunctionPrivate();
     JS_ASSERT_IF(option == INVOKE_CONSTRUCTOR, !fun->isConstructor());
     if (fun->isNative())
         return CallJSNative(cx, fun->u.n.native, args.argc(), args.base());
@@ -673,17 +673,17 @@ Invoke(JSContext *cx, const CallArgs &ar
                 return false;
             args.rval().setObject(*obj);
         } else {
             args.rval().setUndefined();
         }
         return true;
     }
 
-    cx->typeMonitorCall(args, option == INVOKE_CONSTRUCTOR);
+    TypeMonitorCall(cx, args, option == INVOKE_CONSTRUCTOR);
 
     /* Get pointer to new frame/slots, prepare arguments. */
     uint32 flags = ToFrameFlags(option);
     InvokeFrameGuard frame;
     StackFrame *fp = cx->stack.getInvokeFrame(cx, args, fun, script, &flags, &frame);
     if (!fp)
         return false;
 
@@ -1275,17 +1275,17 @@ InvokeConstructor(JSContext *cx, const C
             if (!Invoke(cx, args, INVOKE_CONSTRUCTOR))
                 return false;
 
             JS_ASSERT(args.rval().isObject());
             JS_RUNTIME_METER(cx->runtime, constructs);
             return true;
         }
         if (clasp->construct) {
-            cx->markTypeCallerUnexpected(types::TYPE_UNKNOWN);
+            MarkTypeCallerUnexpected(cx, types::TYPE_UNKNOWN);
             args.thisv().setMagicWithObjectOrNullPayload(NULL);
             return CallJSNativeConstructor(cx, clasp->construct, args.argc(), args.base());
         }
     }
 
 error:
     js_ReportIsNotFunction(cx, &args.calleev(), JSV2F_CONSTRUCT);
     return false;
@@ -3960,17 +3960,17 @@ do_incop:
         goto error;
 
     /*
      * Add undefined to the object itself when read out during an incop.
      * The getProperty can produce undefined without being accounted for by
      * type information, and typeMonitor will not be update the object itself.
      */
     if (regs.sp[-1].isUndefined())
-        cx->addTypePropertyId(obj->getType(), id, types::TYPE_UNDEFINED);
+        AddTypePropertyId(cx, obj->getType(), id, types::TYPE_UNDEFINED);
 
     const JSCodeSpec *cs = &js_CodeSpec[op];
     JS_ASSERT(cs->ndefs == 1);
     JS_ASSERT((cs->format & JOF_TMPSLOT_MASK) >= JOF_TMPSLOT2);
 
     uint32 format = cs->format;
     uint32 setPropFlags = (JOF_MODE(format) == JOF_NAME)
                           ? JSRESOLVE_ASSIGNING
@@ -4466,18 +4466,18 @@ BEGIN_CASE(JSOP_GETELEM)
     if (lref.isMagic(JS_LAZY_ARGUMENTS)) {
         if (rref.isInt32() && size_t(rref.toInt32()) < regs.fp()->numActualArgs()) {
             regs.sp--;
             regs.sp[-1] = regs.fp()->canonicalActualArg(rref.toInt32());
             script->typeMonitor(cx, regs.pc, regs.sp[-1]);
             len = JSOP_GETELEM_LENGTH;
             DO_NEXT_OP(len);
         }
-        cx->markTypeObjectFlags(script->fun->getType(),
-                                types::OBJECT_FLAG_CREATED_ARGUMENTS);
+        MarkTypeObjectFlags(cx, script->fun->getType(),
+                            types::OBJECT_FLAG_CREATED_ARGUMENTS);
         JS_ASSERT(!lref.isMagic(JS_LAZY_ARGUMENTS));
     }
 
     JSObject *obj;
     VALUE_TO_OBJECT(cx, &lref, obj);
 
     const Value *copyFrom;
     Value rval;
@@ -4702,17 +4702,17 @@ BEGIN_CASE(JSOP_FUNCALL)
 
             /* Restrict recursion of lightweight functions. */
             if (JS_UNLIKELY(inlineCallCount >= StackSpace::MAX_INLINE_CALLS)) {
                 js_ReportOverRecursed(cx);
                 goto error;
             }
 
             /* This will construct the type sets for the callee, if necessary. */
-            cx->typeMonitorCall(CallArgsFromVp(argc, vp), flags & StackFrame::CONSTRUCTING);
+            TypeMonitorCall(cx, CallArgsFromVp(argc, vp), flags & StackFrame::CONSTRUCTING);
 
             bool newType = (flags & StackFrame::CONSTRUCTING) &&
                 cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
 
             /* Get pointer to new frame/slots, prepare arguments. */
             ContextStack &stack = cx->stack;
             StackFrame *newfp = stack.getInlineFrame(cx, regs.sp, argc, newfun,
                                                      newscript, &flags);
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -377,17 +377,17 @@ GetCustomIterator(JSContext *cx, JSObjec
 
     /*
      * Notify type inference of the custom iterator.  This only needs to be done
      * if this is coming from a 'for in' loop, not a call to Iterator itself.
      * If an Iterator object is used in a for loop then the values fetched in
      * that loop are unknown, whether there is a custom __iterator__ or not.
      */
     if (!(flags & JSITER_OWNONLY))
-        cx->markTypeCallerUnexpected(types::TYPE_UNKNOWN);
+        types::MarkTypeCallerUnexpected(cx, types::TYPE_UNKNOWN);
 
     /* Otherwise call it and return that object. */
     LeaveTrace(cx);
     Value arg = BooleanValue((flags & JSITER_FOREACH) == 0);
     if (!ExternalInvoke(cx, ObjectValue(*obj), *vp, 1, &arg, vp))
         return false;
     if (vp->isPrimitive()) {
         /*
@@ -437,17 +437,17 @@ NewIteratorObject(JSContext *cx, uintN f
          */
         JSObject *obj = js_NewGCObject(cx, FINALIZE_OBJECT0);
         if (!obj)
             return NULL;
 
         EmptyShape *emptyEnumeratorShape = EmptyShape::getEmptyEnumeratorShape(cx);
         if (!emptyEnumeratorShape)
             return NULL;
-        obj->init(cx, &js_IteratorClass, cx->getTypeEmpty(), NULL, NULL, false);
+        obj->init(cx, &js_IteratorClass, types::GetTypeEmpty(cx), NULL, NULL, false);
         obj->setMap(emptyEnumeratorShape);
         return obj;
     }
 
     return NewBuiltinClassInstance(cx, &js_IteratorClass);
 }
 
 NativeIterator *
@@ -490,17 +490,17 @@ RegisterEnumerator(JSContext *cx, JSObje
 
 static inline bool
 VectorToKeyIterator(JSContext *cx, JSObject *obj, uintN flags, AutoIdVector &keys,
                     uint32 slength, uint32 key, Value *vp)
 {
     JS_ASSERT(!(flags & JSITER_FOREACH));
 
     if (obj)
-        cx->markTypeObjectFlags(obj->getType(), types::OBJECT_FLAG_ITERATED);
+        types::MarkTypeObjectFlags(cx, obj->getType(), types::OBJECT_FLAG_ITERATED);
 
     JSObject *iterobj = NewIteratorObject(cx, flags);
     if (!iterobj)
         return false;
 
     NativeIterator *ni = NativeIterator::allocateIterator(cx, slength, keys);
     if (!ni)
         return false;
@@ -540,17 +540,17 @@ VectorToKeyIterator(JSContext *cx, JSObj
 
 bool
 VectorToValueIterator(JSContext *cx, JSObject *obj, uintN flags, AutoIdVector &keys,
                       Value *vp)
 {
     JS_ASSERT(flags & JSITER_FOREACH);
 
     if (obj)
-        cx->markTypeObjectFlags(obj->getType(), types::OBJECT_FLAG_ITERATED);
+        types::MarkTypeObjectFlags(cx, obj->getType(), types::OBJECT_FLAG_ITERATED);
 
     JSObject *iterobj = NewIteratorObject(cx, flags);
     if (!iterobj)
         return false;
 
     NativeIterator *ni = NativeIterator::allocateIterator(cx, 0, keys);
     if (!ni)
         return false;
@@ -1493,11 +1493,11 @@ js_InitIteratorClasses(JSContext *cx, JS
     }
 #endif
 
     MarkStandardClassInitializedNoProto(obj, &js_StopIterationClass);
 
     proto = js_InitClass(cx, obj, NULL, &js_StopIterationClass, NULL, 0, NULL,
                          NULL, NULL, NULL, NULL);
     if (proto)
-        cx->addTypeProperty(obj->getType(), js_StopIteration_str, ObjectValue(*proto));
+        types::AddTypeProperty(cx, obj->getType(), js_StopIteration_str, ObjectValue(*proto));
     return proto;
 }
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -121,25 +121,25 @@ Class js_MathClass = {
 
 JSBool
 js_math_abs(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
         return JS_TRUE;
     }
     if (!ValueToNumber(cx, vp[2], &x))
         return JS_FALSE;
     z = fabs(x);
     vp->setNumber(z);
     if (!vp[2].isDouble() && vp->isDouble())
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
     return JS_TRUE;
 }
 
 static JSBool
 math_acos(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z;
 
@@ -267,25 +267,25 @@ js_math_ceil_impl(jsdouble x)
 
 JSBool
 js_math_ceil(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
         return JS_TRUE;
     }
     if (!ValueToNumber(cx, vp[2], &x))
         return JS_FALSE;
     z = js_math_ceil_impl(x);
     vp->setNumber(z);
     if (!vp->isInt32())
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
     return JS_TRUE;
 }
 
 static JSBool
 math_cos(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z;
 
@@ -344,25 +344,25 @@ js_math_floor_impl(jsdouble x)
 
 JSBool
 js_math_floor(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
         return JS_TRUE;
     }
     if (!ValueToNumber(cx, vp[2], &x))
         return JS_FALSE;
     z = js_math_floor_impl(x);
     vp->setNumber(z);
     if (!vp->isInt32())
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
     return JS_TRUE;
 }
 
 static JSBool
 math_log(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z;
 
@@ -390,74 +390,74 @@ JSBool
 js_math_max(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z = js_NegativeInfinity;
     Value *argv;
     uintN i;
 
     if (argc == 0) {
         vp->setDouble(js_NegativeInfinity);
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
         return JS_TRUE;
     }
     argv = vp + 2;
     bool expectDouble = false;
     for (i = 0; i < argc; i++) {
         expectDouble |= argv[i].isDouble();
         if (!ValueToNumber(cx, argv[i], &x))
             return JS_FALSE;
         if (JSDOUBLE_IS_NaN(x)) {
             vp->setDouble(js_NaN);
-            cx->markTypeCallerOverflow();
+            types::MarkTypeCallerOverflow(cx);
             return JS_TRUE;
         }
         if (x == 0 && x == z) {
             if (js_copysign(1.0, z) == -1)
                 z = x;
         } else {
             z = (x > z) ? x : z;
         }
     }
     if (!vp->setNumber(z) && !expectDouble)
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
     return JS_TRUE;
 }
 
 JSBool
 js_math_min(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z = js_PositiveInfinity;
     Value *argv;
     uintN i;
 
     if (argc == 0) {
         vp->setDouble(js_PositiveInfinity);
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
         return JS_TRUE;
     }
     argv = vp + 2;
     bool expectDouble = false;
     for (i = 0; i < argc; i++) {
         expectDouble |= argv[i].isDouble();
         if (!ValueToNumber(cx, argv[i], &x))
             return JS_FALSE;
         if (JSDOUBLE_IS_NaN(x)) {
             vp->setDouble(js_NaN);
-            cx->markTypeCallerOverflow();
+            types::MarkTypeCallerOverflow(cx);
             return JS_TRUE;
         }
         if (x == 0 && x == z) {
             if (js_copysign(1.0, x) == -1)
                 z = x;
         } else {
             z = (x < z) ? x : z;
         }
     }
     if (!vp->setNumber(z) && !expectDouble)
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
     return JS_TRUE;
 }
 
 static jsdouble
 powi(jsdouble x, jsint y)
 {
     jsuint n = (y < 0) ? -y : y;
     jsdouble m = x;
@@ -486,65 +486,65 @@ powi(jsdouble x, jsint y)
 
 JSBool
 js_math_pow(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, y, z;
 
     if (argc <= 1) {
         vp->setDouble(js_NaN);
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
         return JS_TRUE;
     }
     bool expectDouble = vp[2].isDouble() || vp[3].isDouble();
     if (!ValueToNumber(cx, vp[2], &x))
         return JS_FALSE;
     if (!ValueToNumber(cx, vp[3], &y))
         return JS_FALSE;
     /*
      * Special case for square roots. Note that pow(x, 0.5) != sqrt(x)
      * when x = -0.0, so we have to guard for this.
      */
     if (JSDOUBLE_IS_FINITE(x) && x != 0.0) {
         if (y == 0.5) {
             vp->setNumber(sqrt(x));
             if (!expectDouble)
-                cx->markTypeCallerOverflow();
+                types::MarkTypeCallerOverflow(cx);
             return JS_TRUE;
         }
         if (y == -0.5) {
             vp->setNumber(1.0/sqrt(x));
             if (!expectDouble)
-                cx->markTypeCallerOverflow();
+                types::MarkTypeCallerOverflow(cx);
             return JS_TRUE;
         }
     }
     /*
      * Because C99 and ECMA specify different behavior for pow(),
      * we need to wrap the libm call to make it ECMA compliant.
      */
     if (!JSDOUBLE_IS_FINITE(y) && (x == 1.0 || x == -1.0)) {
         vp->setDouble(js_NaN);
         if (!expectDouble)
-            cx->markTypeCallerOverflow();
+            types::MarkTypeCallerOverflow(cx);
         return JS_TRUE;
     }
     /* pow(x, +-0) is always 1, even for x = NaN. */
     if (y == 0) {
         vp->setInt32(1);
         return JS_TRUE;
     }
 
     if (vp[3].isInt32())
         z = powi(x, vp[3].toInt32());
     else
         z = pow(x, y);
 
     if (!vp->setNumber(z) && !expectDouble)
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
     return JS_TRUE;
 }
 
 static const int64 RNG_MULTIPLIER = 0x5DEECE66DLL;
 static const int64 RNG_ADDEND = 0xBLL;
 static const int64 RNG_MASK = (1LL << 48) - 1;
 static const jsdouble RNG_DSCALE = jsdouble(1LL << 53);
 
@@ -619,25 +619,25 @@ js_math_round_impl(jsdouble x)
 
 JSBool
 js_math_round(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
         return JS_TRUE;
     }
     if (!ValueToNumber(cx, vp[2], &x))
         return JS_FALSE;
     z = js_copysign(floor(x + 0.5), x);
     vp->setNumber(z);
     if (!vp->isInt32())
-        cx->markTypeCallerOverflow();
+        types::MarkTypeCallerOverflow(cx);
     return JS_TRUE;
 }
 
 static JSBool
 math_sin(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z;
 
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -418,17 +418,17 @@ ParseIntDoubleHelper(jsdouble d)
 
 /* See ECMA 15.1.2.2. */
 static JSBool
 num_parseInt(JSContext *cx, uintN argc, Value *vp)
 {
     /* Fast paths and exceptional cases. */
     if (argc == 0) {
         vp->setDouble(js_NaN);
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
         return true;
     }
 
     if (argc == 1 || (vp[3].isInt32() && (vp[3].toInt32() == 0 || vp[3].toInt32() == 10))) {
         if (vp[2].isInt32()) {
             *vp = vp[2];
             return true;
         }
@@ -439,17 +439,17 @@ num_parseInt(JSContext *cx, uintN argc, 
          *
          * To preserve this behaviour, we can't use the fast-path when string >
          * 1e21, or else the result would be |NeM|.
          */
         if (vp[2].isDouble() &&
             vp[2].toDouble() > -1.0e21 &&
             vp[2].toDouble() < 1.0e21) {
             vp->setDouble(ParseIntDoubleHelper(vp[2].toDouble()));
-            cx->markTypeCallerOverflow();
+            MarkTypeCallerOverflow(cx);
             return true;
         }
     }
 
     /* Step 1. */
     JSString *inputString = js_ValueToString(cx, vp[2]);
     if (!inputString)
         return false;
@@ -459,17 +459,17 @@ num_parseInt(JSContext *cx, uintN argc, 
     bool stripPrefix = true;
     int32_t radix = 0;
     if (argc > 1) {
         if (!ValueToECMAInt32(cx, vp[3], &radix))
             return false;
         if (radix != 0) {
             if (radix < 2 || radix > 36) {
                 vp->setDouble(js_NaN);
-                cx->markTypeCallerOverflow();
+                MarkTypeCallerOverflow(cx);
                 return true;
             }
             if (radix != 16)
                 stripPrefix = false;
         }
     }
 
     /* Steps 2-5, 9-14. */
@@ -480,17 +480,17 @@ num_parseInt(JSContext *cx, uintN argc, 
 
     jsdouble number;
     if (!ParseIntStringHelper(cx, ws, end, radix, stripPrefix, &number))
         return false;
 
     /* Step 15. */
     vp->setNumber(number);
     if (!vp->isInt32())
-        cx->markTypeCallerOverflow();
+        MarkTypeCallerOverflow(cx);
     return true;
 }
 
 #ifdef JS_TRACER
 static jsdouble FASTCALL
 ParseInt(JSContext* cx, JSString* str)
 {
     TraceMonitor *tm = JS_TRACE_MONITOR_ON_TRACE(cx);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -76,17 +76,17 @@
 #include "jsstaticcheck.h"
 #include "jsstdint.h"
 #include "jsstr.h"
 #include "jstracer.h"
 #include "jsdbgapi.h"
 #include "json.h"
 #include "jswrapper.h"
 
-#include "jsinferinlines.h"
+#include "jsarrayinlines.h"
 #include "jsinterpinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
 #include "jsobjinlines.h"
 
 #include "vm/StringObject-inl.h"
 
 #if JS_HAS_GENERATORS
@@ -2597,17 +2597,17 @@ obj_create(JSContext *cx, uintN argc, Va
      */
     JSObject *obj = NewNonFunction<WithProto::Given>(cx, &js_ObjectClass, v.toObjectOrNull(),
                                                         vp->toObject().getGlobal());
     if (!obj)
         return JS_FALSE;
     vp->setObject(*obj); /* Root and prepare for eventual return. */
 
     /* Don't track types or array-ness for objects created here. */
-    cx->markTypeObjectUnknownProperties(obj->getType());
+    MarkTypeObjectUnknownProperties(cx, obj->getType());
 
     /* 15.2.3.5 step 4. */
     if (argc > 1 && !vp[3].isUndefined()) {
         if (vp[3].isPrimitive()) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_NONNULL_OBJECT);
             return JS_FALSE;
         }
 
@@ -2879,17 +2879,17 @@ js_Object(JSContext *cx, uintN argc, Val
     }
     if (!obj) {
         /* Make an object whether this was called with 'new' or not. */
         JS_ASSERT(!argc || vp[2].isNull() || vp[2].isUndefined());
         gc::FinalizeKind kind = NewObjectGCKind(cx, &js_ObjectClass);
         obj = NewBuiltinClassInstance(cx, &js_ObjectClass, kind);
         if (!obj)
             return JS_FALSE;
-        TypeObject *type = cx->getTypeCallerInitObject(false);
+        TypeObject *type = GetTypeCallerInitObject(cx, false);
         if (!type || !obj->setTypeAndEmptyShape(cx, type))
             return JS_FALSE;
     }
     vp->setObject(*obj);
     return JS_TRUE;
 }
 
 JSObject *
@@ -3351,31 +3351,31 @@ js_NewBlockObject(JSContext *cx)
      */
     JSObject *blockObj = js_NewGCObject(cx, FINALIZE_OBJECT2);
     if (!blockObj)
         return NULL;
 
     EmptyShape *emptyBlockShape = EmptyShape::getEmptyBlockShape(cx);
     if (!emptyBlockShape)
         return NULL;
-    blockObj->init(cx, &js_BlockClass, cx->getTypeEmpty(), NULL, NULL, false);
+    blockObj->init(cx, &js_BlockClass, GetTypeEmpty(cx), NULL, NULL, false);
     blockObj->setMap(emptyBlockShape);
 
     return blockObj;
 }
 
 JSObject *
 js_CloneBlockObject(JSContext *cx, JSObject *proto, StackFrame *fp)
 {
     JS_ASSERT(proto->isStaticBlock());
 
     size_t count = OBJ_BLOCK_COUNT(cx, proto);
     gc::FinalizeKind kind = gc::GetGCObjectKind(count + 1);
 
-    js::types::TypeObject *type = proto->getNewType(cx);
+    TypeObject *type = proto->getNewType(cx);
     if (!type)
         return false;
 
     JSObject *clone = js_NewGCObject(cx, kind);
     if (!clone)
         return NULL;
 
     StackFrame *priv = js_FloatingFrameIfGenerator(cx, fp);
@@ -3913,17 +3913,17 @@ js_InitObjectClass(JSContext *cx, JSObje
                                    object_props, object_methods, NULL, object_static_methods);
     if (!proto)
         return NULL;
 
     /* The default 'new' object for Object.prototype has unknown properties. */
     TypeObject *newType = proto->getNewType(cx);
     if (!newType)
         return NULL;
-    cx->markTypeObjectUnknownProperties(newType);
+    MarkTypeObjectUnknownProperties(cx, newType);
 
     /* ECMA (15.1.2.1) says 'eval' is a property of the global object. */
     jsid id = ATOM_TO_JSID(cx->runtime->atomState.evalAtom);
 
     JSObject *evalobj = js_DefineFunction(cx, obj, id, eval, 1, JSFUN_STUB_GSOPS,
                                           JS_TypeHandlerDynamic, js_eval_str);
     if (!evalobj)
         return NULL;
@@ -3953,17 +3953,17 @@ DefineStandardSlot(JSContext *cx, JSObje
 
         const Shape *shape = obj->nativeLookup(id);
         if (!shape) {
             uint32 slot = 2 * JSProto_LIMIT + key;
             if (!js_SetReservedSlot(cx, obj, slot, v))
                 return false;
             if (!obj->addProperty(cx, id, PropertyStub, StrictPropertyStub, slot, attrs, 0, 0))
                 return false;
-            cx->addTypePropertyId(obj->getType(), id, v);
+            AddTypePropertyId(cx, obj->getType(), id, v);
 
             named = true;
             return true;
         }
     }
 
     named = obj->defineProperty(cx, id, v, PropertyStub, StrictPropertyStub, attrs);
     return named;
@@ -4038,18 +4038,18 @@ DefineConstructorAndPrototype(JSContext 
         return NULL;
 
     TypeObject *type = proto->getNewType(cx);
     if (!type)
         return NULL;
 
     /* Mark types with a special equality hook as having unknown properties. */
     if (clasp->ext.equality) {
-        cx->markTypeObjectUnknownProperties(type);
-        cx->markTypeObjectUnknownProperties(proto->getType());
+        MarkTypeObjectUnknownProperties(cx, type);
+        MarkTypeObjectUnknownProperties(cx, proto->getType());
     }
 
     proto->syncSpecialEquality();
 
     /* After this point, control must exit via label bad or out. */
     AutoObjectRooter tvr(cx, proto);
 
     JSObject *ctor;
@@ -4418,17 +4418,17 @@ JSObject::growSlots(JSContext *cx, size_
         if (!cx->typeInferenceEnabled())
             backfillDenseArrayHoles(cx);
     } else {
         /* Clear the new slots we added. */
         ClearValueRange(slots + oldAllocCount, allocCount - oldAllocCount, false);
     }
 
     if (changed && isGlobal())
-        cx->markGlobalReallocation(this);
+        MarkGlobalReallocation(cx, this);
 
     return true;
 }
 
 void
 JSObject::shrinkSlots(JSContext *cx, size_t newcap)
 {
     uint32 oldcap = numSlots();
@@ -4463,17 +4463,17 @@ JSObject::shrinkSlots(JSContext *cx, siz
 
     if (fill < newcap) {
         /* Clear any excess holes if we tried to shrink below SLOT_CAPACITY_MIN. */
         if (!isDenseArray())
             clearSlotRange(fill, newcap - fill);
     }
 
     if (changed && isGlobal())
-        cx->markGlobalReallocation(this);
+        MarkGlobalReallocation(cx, this);
 }
 
 bool
 JSObject::ensureInstanceReservedSlots(JSContext *cx, size_t nreserved)
 {
     JS_ASSERT_IF(isNative(),
                  isBlock() || isCall() || (isFunction() && isBoundFunction()));
 
@@ -4517,29 +4517,29 @@ SetProto(JSContext *cx, JSObject *obj, J
      * case any entries were filled by looking up through obj.
      */
     JSObject *oldproto = obj;
     while (oldproto && oldproto->isNative()) {
         oldproto->protoShapeChange(cx);
         oldproto = oldproto->getProto();
     }
 
-    TypeObject *type = proto ? proto->getNewType(cx) : cx->getTypeEmpty();
+    TypeObject *type = proto ? proto->getNewType(cx) : GetTypeEmpty(cx);
     if (!type)
         return false;
 
     /*
      * Setting __proto__ on an object that has escaped and may be referenced by
      * other heap objects can only be done if the properties of both objects are unknown.
      * Type sets containing this object will contain the original type but not the
      * new type of the object, which is OK since we treat objects in type sets with
      * unknown properties as interchangeable.
      */
-    cx->markTypeObjectUnknownProperties(obj->getType());
-    cx->markTypeObjectUnknownProperties(type);
+    MarkTypeObjectUnknownProperties(cx, obj->getType());
+    MarkTypeObjectUnknownProperties(cx, type);
 
     if (checkForCycles) {
         for (JSObject *obj2 = proto; obj2; obj2 = obj2->getProto()) {
             if (obj2 == obj) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CYCLIC_VALUE,
                                      js_proto_str);
                 return false;
             }
@@ -4694,17 +4694,17 @@ js_ConstructObject(JSContext *cx, Class 
             proto = rval.toObjectOrNull();
     }
 
     JSObject *obj = NewObject<WithProto::Class>(cx, clasp, proto, parent);
     if (!obj)
         return NULL;
 
     obj->syncSpecialEquality();
-    cx->markTypeObjectUnknownProperties(obj->getType());
+    MarkTypeObjectUnknownProperties(cx, obj->getType());
 
     Value rval;
     if (!InvokeConstructorWithGivenThis(cx, obj, cval, argc, argv, &rval))
         return NULL;
 
     if (rval.isPrimitive())
         return obj;
 
@@ -5016,18 +5016,18 @@ DefineNativeProperty(JSContext *cx, JSOb
      * only half of a property.
      */
     const Shape *shape = NULL;
     if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
         JSObject *pobj;
         JSProperty *prop;
 
         /* Type information for getter/setter properties is unknown. */
-        cx->addTypePropertyId(obj->getType(), id, TYPE_UNKNOWN);
-        cx->markTypePropertyConfigured(obj->getType(), id);
+        AddTypePropertyId(cx, obj->getType(), id, TYPE_UNKNOWN);
+        MarkTypePropertyConfigured(cx, obj->getType(), id);
 
         /*
          * If we are defining a getter whose setter was already defined, or
          * vice versa, finish the job via obj->changeProperty, and refresh the
          * property cache line for (obj, id) to map shape.
          */
         if (!js_LookupProperty(cx, obj, id, &pobj, &prop))
             return NULL;
@@ -5076,19 +5076,19 @@ DefineNativeProperty(JSContext *cx, JSOb
     }
 
     if (((defineHow & DNP_SET_METHOD) || getter == PropertyStub) &&
         !(defineHow & DNP_SKIP_TYPE)) {
         /*
          * Type information for normal native properties should reflect the
          * initial value of the property.
          */
-        cx->addTypePropertyId(obj->getType(), id, value);
+        AddTypePropertyId(cx, obj->getType(), id, value);
         if (attrs & JSPROP_READONLY)
-            cx->markTypePropertyConfigured(obj->getType(), id);
+            MarkTypePropertyConfigured(cx, obj->getType(), id);
     }
 
     /* Get obj's own scope if it has one, or create a new one for obj. */
     if (!obj->ensureClassReservedSlots(cx))
         return NULL;
 
     /*
      * Make a local copy of value, in case a method barrier needs to update the
@@ -5580,34 +5580,34 @@ js_NativeGetInline(JSContext *cx, JSObje
         (JS_LIKELY(cx->runtime->propertyRemovals == sample) ||
          pobj->nativeContains(*shape))) {
         if (!pobj->methodWriteBarrier(cx, *shape, *vp))
             return false;
         pobj->nativeSetSlot(slot, *vp);
     }
 
     /* Record values produced by shapes without a default getter. */
-    cx->addTypePropertyId(obj->getType(), shape->propid, *vp);
+    AddTypePropertyId(cx, obj->getType(), shape->propid, *vp);
 
     return true;
 }
 
 JSBool
 js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj, const Shape *shape, uintN getHow,
              Value *vp)
 {
     return js_NativeGetInline(cx, obj, obj, pobj, shape, getHow, vp);
 }
 
 JSBool
 js_NativeSet(JSContext *cx, JSObject *obj, const Shape *shape, bool added, bool strict, Value *vp)
 {
     LeaveTraceIfGlobalObject(cx, obj);
 
-    cx->addTypePropertyId(obj->getType(), shape->propid, *vp);
+    AddTypePropertyId(cx, obj->getType(), shape->propid, *vp);
 
     uint32 slot;
     int32 sample;
 
     JS_ASSERT(obj->isNative());
 
     slot = shape->slot;
     if (slot != SHAPE_INVALID_SLOT) {
@@ -5688,17 +5688,17 @@ js_GetPropertyHelperWithShapeInline(JSCo
 
         if (!CallJSPropertyOp(cx, obj->getClass()->getProperty, obj, id, vp))
             return JS_FALSE;
 
         PCMETER(getHow & JSGET_CACHE_RESULT && JS_PROPERTY_CACHE(cx).nofills++);
 
         /* Record non-undefined values produced by the class getter hook. */
         if (!vp->isUndefined())
-            cx->addTypePropertyId(obj->getType(), id, *vp);
+            AddTypePropertyId(cx, obj->getType(), id, *vp);
 
         /*
          * Give a strict warning if foo.bar is evaluated by a script for an
          * object foo with no property named 'bar'.
          */
         jsbytecode *pc;
         if (vp->isUndefined() && ((pc = js_GetCurrentBytecodePC(cx)) != NULL)) {
             JSOp op;
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -123,29 +123,29 @@ JSObject::unbrand(JSContext *cx)
     }
     setGeneric();
     return true;
 }
 
 inline JSBool
 JSObject::setAttributes(JSContext *cx, jsid id, uintN *attrsp)
 {
-    cx->markTypePropertyConfigured(getType(), id);
+    js::types::MarkTypePropertyConfigured(cx, getType(), id);
     js::AttributesOp op = getOps()->setAttributes;
     return (op ? op : js_SetAttributes)(cx, this, id, attrsp);
 }
 
 inline JSBool
 JSObject::getProperty(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp)
 {
     js::PropertyIdOp op = getOps()->getProperty;
     if (op) {
         if (!op(cx, this, receiver, id, vp))
             return false;
-        cx->addTypePropertyId(getType(), id, *vp);
+        js::types::AddTypePropertyId(cx, getType(), id, *vp);
     } else {
         if (!js_GetProperty(cx, this, receiver, id, vp))
             return false;
         JS_ASSERT(js::types::TypeHasProperty(cx, getType(), id, *vp));
     }
     return true;
 }
 
@@ -153,18 +153,18 @@ inline JSBool
 JSObject::getProperty(JSContext *cx, jsid id, js::Value *vp)
 {
     return getProperty(cx, this, id, vp);
 }
 
 inline JSBool
 JSObject::deleteProperty(JSContext *cx, jsid id, js::Value *rval, JSBool strict)
 {
-    cx->addTypePropertyId(getType(), id, js::types::TYPE_UNDEFINED);
-    cx->markTypePropertyConfigured(getType(), id);
+    js::types::AddTypePropertyId(cx, getType(), id, js::types::TYPE_UNDEFINED);
+    js::types::MarkTypePropertyConfigured(cx, getType(), id);
     js::DeleteIdOp op = getOps()->deleteProperty;
     return (op ? op : js_DeleteProperty)(cx, this, id, rval, strict);
 }
 
 inline void
 JSObject::syncSpecialEquality()
 {
     if (clasp->ext.equality) {
@@ -192,17 +192,17 @@ JSObject::finalize(JSContext *cx)
 
 /* 
  * Initializer for Call objects for functions and eval frames. Set class,
  * parent, map, and shape, and allocate slots.
  */
 inline void
 JSObject::initCall(JSContext *cx, const js::Bindings &bindings, JSObject *parent)
 {
-    init(cx, &js_CallClass, cx->getTypeEmpty(), parent, NULL, false);
+    init(cx, &js_CallClass, js::types::GetTypeEmpty(cx), parent, NULL, false);
     lastProp = bindings.lastShape();
 
     /*
      * If |bindings| is for a function that has extensible parents, that means
      * its Call should have its own shape; see js::Bindings::extensibleParents.
      */
     if (bindings.extensibleParents())
         setOwnShape(js_GenerateShape(cx));
@@ -450,21 +450,21 @@ JSObject::setArrayLength(JSContext *cx, 
 {
     JS_ASSERT(isArray());
 
     if (length > INT32_MAX) {
         /*
          * Mark the type of this object as possibly not a dense array, per the
          * requirements of OBJECT_FLAG_NON_DENSE_ARRAY.
          */
-        cx->markTypeObjectFlags(getType(),
-                                js::types::OBJECT_FLAG_NON_PACKED_ARRAY |
-                                js::types::OBJECT_FLAG_NON_DENSE_ARRAY);
+        js::types::MarkTypeObjectFlags(cx, getType(),
+                                       js::types::OBJECT_FLAG_NON_PACKED_ARRAY |
+                                       js::types::OBJECT_FLAG_NON_DENSE_ARRAY);
         jsid lengthId = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
-        cx->addTypePropertyId(getType(), lengthId, js::types::TYPE_DOUBLE);
+        js::types::AddTypePropertyId(cx, getType(), lengthId, js::types::TYPE_DOUBLE);
     }
 
     setPrivate((void*) length);
 }
 
 inline void
 JSObject::setDenseArrayLength(uint32 length)
 {
@@ -507,17 +507,17 @@ JSObject::setDenseArrayElement(uintN idx
 {
     JS_ASSERT(isDenseArray() && idx < getDenseArrayInitializedLength());
     slots[idx] = val;
 }
 
 inline void
 JSObject::setDenseArrayElementWithType(JSContext *cx, uintN idx, const js::Value &val)
 {
-    cx->addTypePropertyId(getType(), JSID_VOID, val);
+    js::types::AddTypePropertyId(cx, getType(), JSID_VOID, val);
     setDenseArrayElement(idx, val);
 }
 
 inline void
 JSObject::shrinkDenseArrayElements(JSContext *cx, uintN cap)
 {
     JS_ASSERT(isDenseArray());
     shrinkSlots(cx, cap);
@@ -803,17 +803,17 @@ JSObject::getNewType(JSContext *cx, JSSc
         makeNewType(cx, script);
     }
     return newType;
 }
 
 inline bool
 JSObject::clearType(JSContext *cx)
 {
-    js::types::TypeObject *newType = cx->getTypeEmpty();
+    js::types::TypeObject *newType = js::types::GetTypeEmpty(cx);
     if (!newType)
         return false;
     type = newType;
     return true;
 }
 
 inline void
 JSObject::setType(js::types::TypeObject *newType)
@@ -1002,17 +1002,17 @@ JSObject::nativeSetSlot(uintN slot, cons
     JS_ASSERT(containsSlot(slot));
     return setSlot(slot, value);
 }
 
 inline void
 JSObject::nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value)
 {
     nativeSetSlot(shape->slot, value);
-    cx->addTypePropertyId(getType(), shape->propid, value);
+    js::types::AddTypePropertyId(cx, getType(), shape->propid, value);
 }
 
 inline bool
 JSObject::isNative() const
 {
     return lastProp->isNative();
 }
 
@@ -1414,17 +1414,17 @@ NewObject(JSContext *cx, js::Class *clas
           gc::FinalizeKind kind)
 {
     /* Bootstrap the ur-object, and make it the default prototype object. */
     if (withProto == WithProto::Class && !proto) {
         if (!FindProto(cx, clasp, parent, &proto))
           return NULL;
     }
 
-    types::TypeObject *type = proto ? proto->getNewType(cx) : cx->getTypeEmpty();
+    types::TypeObject *type = proto ? proto->getNewType(cx) : js::types::GetTypeEmpty(cx);
     if (!type)
         return NULL;
 
     /*
      * Allocate an object from the GC heap and initialize all its fields before
      * doing any operation that can potentially trigger GC. Functions have a
      * larger non-standard allocation size.
      *
@@ -1648,21 +1648,21 @@ DefineConstructorAndPrototype(JSContext 
     JS_ASSERT(global->isGlobal());
     JS_ASSERT(!global->nativeEmpty()); /* reserved slots already allocated */
     JS_ASSERT(ctor);
     JS_ASSERT(proto);
 
     jsid id = ATOM_TO_JSID(cx->runtime->atomState.classAtoms[key]);
     JS_ASSERT(!global->nativeLookup(id));
 
-    /* Set these first in case addTypePropertyId looks for this class. */
+    /* Set these first in case AddTypePropertyId looks for this class. */
     global->setSlot(key, ObjectValue(*ctor));
     global->setSlot(key + JSProto_LIMIT, ObjectValue(*proto));
 
-    cx->addTypePropertyId(global->getType(), id, ObjectValue(*ctor));
+    types::AddTypePropertyId(cx, global->getType(), id, ObjectValue(*ctor));
     if (!global->addDataProperty(cx, id, key + JSProto_LIMIT * 2, 0)) {
         global->setSlot(key, UndefinedValue());
         global->setSlot(key + JSProto_LIMIT, UndefinedValue());
         return false;
     }
 
     global->setSlot(key + JSProto_LIMIT * 2, ObjectValue(*ctor));
     return true;
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -128,17 +128,17 @@ js_json_stringify(JSContext *cx, uintN a
     // needs to support returning undefined. So this is a little awkward
     // for the API, because we want to support streaming writers.
     if (!sb.empty()) {
         JSString *str = sb.finishString();
         if (!str)
             return false;
         vp->setString(str);
     } else {
-        cx->markTypeCallerUnexpected(types::TYPE_UNDEFINED);
+        MarkTypeCallerUnexpected(cx, types::TYPE_UNDEFINED);
         vp->setUndefined();
     }
 
     return true;
 }
 
 JSBool
 js_TryJSON(JSContext *cx, Value *vp)
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -1179,17 +1179,17 @@ Compiler::defineGlobals(JSContext *cx, G
         if (def.funbox) {
             JSFunction *fun = def.funbox->function();
 
             /*
              * No need to check for redeclarations or anything, global
              * optimizations only take place if the property is not defined.
              */
             rval.setObject(*fun);
-            cx->addTypePropertyId(globalObj->getType(), id, rval);
+            types::AddTypePropertyId(cx, globalObj->getType(), id, rval);
         } else {
             rval.setUndefined();
         }
 
         /*
          * Don't update the type information when defining the property for the
          * global object, per the consistency rules for type properties. If the
          * property is only undefined before it is ever written, we can check
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -1170,17 +1170,17 @@ NewProxyObject(JSContext *cx, JSProxyHan
     if (fun) {
         obj->setSlot(JSSLOT_PROXY_CALL, call ? ObjectValue(*call) : UndefinedValue());
         if (construct) {
             obj->setSlot(JSSLOT_PROXY_CONSTRUCT, ObjectValue(*construct));
         }
     }
 
     /* Don't track types of properties of proxies. */
-    cx->markTypeObjectUnknownProperties(obj->getType());
+    MarkTypeObjectUnknownProperties(cx, obj->getType());
 
     return obj;
 }
 
 static JSBool
 proxy_create(JSContext *cx, uintN argc, Value *vp)
 {
     if (argc < 1) {
--- a/js/src/jsregexp.cpp
+++ b/js/src/jsregexp.cpp
@@ -789,17 +789,17 @@ regexp_construct(JSContext *cx, uintN ar
         if (argc >= 1 && argv[0].isObject() && argv[0].toObject().isRegExp() &&
             (argc == 1 || argv[1].isUndefined())) {
             *vp = argv[0];
             /*
              * Note: the type handler for RegExp only accounts for a new
              * regexps for any associated compileAndGo RegExp global, not new
              * regexps with different prototypes or RegExp.prototype itself.
              */
-            cx->markTypeCallerUnexpected(*vp);
+            MarkTypeCallerUnexpected(cx, *vp);
             return true;
         }
     }
 
     JSObject *obj = NewBuiltinClassInstance(cx, &js_RegExpClass);
     if (!obj)
         return false;
 
@@ -902,22 +902,22 @@ js_InitRegExpClass(JSContext *cx, JSObje
      * Object.prototype.)
      *
      * All callers of JSObject::initSharingEmptyShape depend on this.
      */
     if (!type->getEmptyShape(cx, &js_RegExpClass, FINALIZE_OBJECT0))
         return NULL;
 
     /* Capture properties added individually to each RegExp object. */
-    cx->addTypeProperty(protoType, "source", TYPE_STRING);
-    cx->addTypeProperty(protoType, "global", TYPE_BOOLEAN);
-    cx->addTypeProperty(protoType, "ignoreCase", TYPE_BOOLEAN);
-    cx->addTypeProperty(protoType, "multiline", TYPE_BOOLEAN);
-    cx->addTypeProperty(protoType, "sticky", TYPE_BOOLEAN);
-    cx->addTypeProperty(protoType, "lastIndex", TYPE_INT32);
+    AddTypeProperty(cx, protoType, "source", TYPE_STRING);
+    AddTypeProperty(cx, protoType, "global", TYPE_BOOLEAN);
+    AddTypeProperty(cx, protoType, "ignoreCase", TYPE_BOOLEAN);
+    AddTypeProperty(cx, protoType, "multiline", TYPE_BOOLEAN);
+    AddTypeProperty(cx, protoType, "sticky", TYPE_BOOLEAN);
+    AddTypeProperty(cx, protoType, "lastIndex", TYPE_INT32);
 
     /* Install the fully-constructed RegExp and RegExp.prototype in global. */
     if (!DefineConstructorAndPrototype(cx, global, JSProto_RegExp, ctor, proto))
         return NULL;
 
     return proto;
 }
 
--- a/js/src/jsscope.cpp
+++ b/js/src/jsscope.cpp
@@ -990,19 +990,19 @@ JSObject::changeProperty(JSContext *cx, 
 
     /* Allow only shared (slotless) => unshared (slotful) transition. */
     JS_ASSERT(!((attrs ^ shape->attrs) & JSPROP_SHARED) ||
               !(attrs & JSPROP_SHARED));
 
     /* Don't allow method properties to be changed to have a getter. */
     JS_ASSERT_IF(getter != shape->rawGetter, !shape->isMethod());
 
-    cx->markTypePropertyConfigured(getType(), shape->propid);
+    types::MarkTypePropertyConfigured(cx, getType(), shape->propid);
     if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
-        cx->addTypePropertyId(getType(), shape->propid, types::TYPE_UNKNOWN);
+        types::AddTypePropertyId(cx, getType(), shape->propid, types::TYPE_UNKNOWN);
 
     if (getter == PropertyStub)
         getter = NULL;
     if (setter == StrictPropertyStub)
         setter = NULL;
 
     if (!CheckCanChangeAttrs(cx, this, shape, &attrs))
         return NULL;
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -586,25 +586,25 @@ struct JSScript {
     bool condenseTypes(JSContext *cx);
     void sweepAnalysis(JSContext *cx);
 
     /* Get a type object for an allocation site in this script. */
     inline js::types::TypeObject *
     getTypeInitObject(JSContext *cx, const jsbytecode *pc, bool isArray);
 
     /* Monitor a bytecode pushing an unexpected value. */
-    inline void typeMonitorOverflow(JSContext *cx, const jsbytecode *pc);
-    inline void typeMonitorString(JSContext *cx, const jsbytecode *pc);
-    inline void typeMonitorUnknown(JSContext *cx, const jsbytecode *pc);
+    inline void typeMonitorOverflow(JSContext *cx, jsbytecode *pc);
+    inline void typeMonitorString(JSContext *cx, jsbytecode *pc);
+    inline void typeMonitorUnknown(JSContext *cx, jsbytecode *pc);
 
     /* Monitor a JOF_TYPESET bytecode pushing any value into its pushed type set. */
     inline void typeMonitor(JSContext *cx, jsbytecode *pc, const js::Value &val);
 
     /* Monitor an assignment at a SETELEM on a non-integer identifier. */
-    inline void typeMonitorAssign(JSContext *cx, const jsbytecode *pc,
+    inline void typeMonitorAssign(JSContext *cx, jsbytecode *pc,
                                   JSObject *obj, jsid id, const js::Value &val);
 
     /* Add a type for a variable in this script. */
     inline void typeSetThis(JSContext *cx, js::types::jstype type);
     inline void typeSetThis(JSContext *cx, const js::Value &value);
     inline void typeSetThis(JSContext *cx, js::types::ClonedTypeSet *types);
     inline void typeSetNewCalled(JSContext *cx);
     inline void typeSetLocal(JSContext *cx, unsigned local, js::types::jstype type);
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -1054,17 +1054,17 @@ js_str_charCodeAt(JSContext *cx, uintN a
     if (!chars)
         return false;
 
     vp->setInt32(chars[i]);
     return true;
 
 out_of_range:
     vp->setDouble(js_NaN);
-    cx->markTypeCallerOverflow();
+    MarkTypeCallerOverflow(cx);
     return true;
 }
 
 /*
  * Boyer-Moore-Horspool superlinear search for pat:patlen in text:textlen.
  * The patlen argument must be positive and no greater than sBMHPatLenMax.
  *
  * Return the index of pat in text, or -1 if not found.
@@ -2627,17 +2627,17 @@ SplitHelper(JSContext *cx, JSLinearStrin
                 if (res->pairIsPresent(i + 1)) {
                     JSSubString parsub;
                     res->getParen(i + 1, &parsub);
                     sub = js_NewStringCopyN(cx, parsub.chars, parsub.length);
                     if (!sub || !splits.append(StringValue(sub)))
                         return NULL;
                 } else {
                     /* Only string entries have been accounted for so far. */
-                    cx->addTypePropertyId(type, JSID_VOID, UndefinedValue());
+                    AddTypePropertyId(cx, type, JSID_VOID, UndefinedValue());
                     if (!splits.append(UndefinedValue()))
                         return NULL;
                 }
 
                 /* Step 13(c)(iii)(7)(d). */
                 if (splits.length() == limit)
                     return NewDenseCopiedArray(cx, splits.length(), splits.begin());
             }
@@ -2721,20 +2721,20 @@ class SplitStringMatcher {
 static JSBool
 str_split(JSContext *cx, uintN argc, Value *vp)
 {
     /* Steps 1-2. */
     JSString *str = ThisToStringForStringProto(cx, vp);
     if (!str)
         return false;
 
-    TypeObject *type = cx->getTypeCallerInitObject(true);
+    TypeObject *type = GetTypeCallerInitObject(cx, true);
     if (!type)
         return false;
-    cx->addTypePropertyId(type, JSID_VOID, types::TYPE_STRING);
+    AddTypePropertyId(cx, type, JSID_VOID, types::TYPE_STRING);
 
     /* Step 5: Use the second argument as the split limit, if given. */
     uint32 limit;
     if (argc > 1 && !vp[3].isUndefined()) {
         jsdouble d;
         if (!ValueToNumber(cx, vp[3], &d))
             return false;
         limit = js_DoubleToECMAUint32(d);
@@ -3539,22 +3539,22 @@ js_InitStringClass(JSContext *cx, JSObje
 
     /* Pre-brand String and String.prototype for trace-jitted code. */
     if (!cx->typeInferenceEnabled()) {
         proto->brand(cx);
         ctor->brand(cx);
     }
 
     jsid lengthId = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
-    cx->addTypePropertyId(proto->getType(), lengthId, TYPE_INT32);
+    AddTypePropertyId(cx, proto->getType(), lengthId, TYPE_INT32);
 
     TypeObject *type = proto->getNewType(cx);
     if (!type)
         return NULL;
-    cx->addTypePropertyId(type, JSID_VOID, TYPE_STRING);
+    AddTypePropertyId(cx, type, JSID_VOID, TYPE_STRING);
 
     /*
      * Make sure proto's emptyShape is available to be shared by String
      * objects. JSObject::emptyShape is a one-slot cache. If we omit this, some
      * other class could snap it up. (The risk is particularly great for
      * Object.prototype.)
      *
      * All callers of JSObject::initSharingEmptyShape depend on this.
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -1530,19 +1530,19 @@ do {                                    
                          &TypedArray::slowClasses[TypedArray::_type],          \
                          _typedArray::class_constructor, 3,                    \
                          JS_TypeHandlerNew,                                    \
                          _typedArray::jsprops,                                 \
                          _typedArray::jsfuncs,                                 \
                          NULL, NULL);                                          \
     if (!proto)                                                                \
         return NULL;                                                           \
-    cx->addTypePropertyId(proto->getType(), JSID_VOID, types::TYPE_INT32);     \
+    AddTypePropertyId(cx, proto->getType(), JSID_VOID, types::TYPE_INT32);     \
     if (_typedArray::ArrayElementTypeMayBeDouble())                            \
-        cx->addTypePropertyId(proto->getType(), JSID_VOID, types::TYPE_DOUBLE); \
+        AddTypePropertyId(cx, proto->getType(), JSID_VOID, types::TYPE_DOUBLE); \
     JSObject *ctor = JS_GetConstructor(cx, proto);                             \
     if (!ctor ||                                                               \
         !JS_DefineProperty(cx, ctor, "BYTES_PER_ELEMENT",                      \
                            INT_TO_JSVAL(sizeof(_typedArray::ThisType)),        \
                            JS_PropertyStub, JS_StrictPropertyStub,             \
                            JSPROP_PERMANENT | JSPROP_READONLY) ||              \
         !JS_DefineProperty(cx, proto, "BYTES_PER_ELEMENT",                     \
                            INT_TO_JSVAL(sizeof(_typedArray::ThisType)),        \
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -632,17 +632,17 @@ Reify(JSContext *cx, JSCompartment *orig
         return VectorToKeyIterator(cx, obj, ni->flags, keys, vp);
     return VectorToValueIterator(cx, obj, ni->flags, keys, vp); 
 }
 
 bool
 JSCrossCompartmentWrapper::iterate(JSContext *cx, JSObject *wrapper, uintN flags, Value *vp)
 {
     if (!(flags & JSITER_OWNONLY))
-        cx->markTypeCallerUnexpected(types::TYPE_UNKNOWN);
+        types::MarkTypeCallerUnexpected(cx, types::TYPE_UNKNOWN);
 
     PIERCE(cx, wrapper, GET,
            NOTHING,
            JSWrapper::iterate(cx, wrapper, flags, vp),
            CanReify(vp) ? Reify(cx, call.origin, vp) : call.origin->wrap(cx, vp));
 }
 
 bool
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -7130,18 +7130,18 @@ js_InitQNameClass(JSContext *cx, JSObjec
                                    qname_props, qname_methods, NULL, NULL);
     if (!proto)
         return NULL;
 
     /* Properties of QName objects are not modeled by type inference. */
     TypeObject *type = proto->getNewType(cx);
     if (!type)
         return NULL;
-    cx->markTypeObjectUnknownProperties(type);
-    cx->markTypeObjectUnknownProperties(proto->getType());
+    MarkTypeObjectUnknownProperties(cx, type);
+    MarkTypeObjectUnknownProperties(cx, proto->getType());
 
     return proto;
 }
 
 JSObject *
 js_InitXMLClass(JSContext *cx, JSObject *obj)
 {
     JSObject *proto, *pobj;
@@ -7161,18 +7161,18 @@ js_InitXMLClass(JSContext *cx, JSObject 
     /* Define the isXMLName function. */
     if (!JS_DefineFunction(cx, obj, js_isXMLName_str, xml_isXMLName, 1, 0))
         return NULL;
 
     /* Properties of XML objects are not modeled by type inference. */
     TypeObject *type = proto->getNewType(cx);
     if (!type)
         return NULL;
-    cx->markTypeObjectUnknownProperties(type);
-    cx->markTypeObjectUnknownProperties(proto->getType());
+    MarkTypeObjectUnknownProperties(cx, type);
+    MarkTypeObjectUnknownProperties(cx, proto->getType());
 
     xml = js_NewXML(cx, JSXML_CLASS_TEXT);
     if (!xml)
         return NULL;
     proto->setPrivate(xml);
     xml->object = proto;
     METER(xml_stats.xmlobj);
 
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -166,18 +166,20 @@ mjit::Compiler::compile()
         // just need a pointer so the VM can quickly decide whether this
         // method can be JIT'd or not. Global scripts cannot be IC'd, since
         // they have no functions, so there is no danger.
         *checkAddr = (*jit)->arityCheckEntry
                      ? (*jit)->arityCheckEntry
                      : (*jit)->invokeEntry;
     } else if (status != Compile_Retry) {
         *checkAddr = JS_UNJITTABLE_SCRIPT;
-        if (outerScript->fun)
-            cx->markTypeObjectFlags(outerScript->fun->getType(), types::OBJECT_FLAG_UNINLINEABLE);
+        if (outerScript->fun) {
+            types::MarkTypeObjectFlags(cx, outerScript->fun->getType(),
+                                       types::OBJECT_FLAG_UNINLINEABLE);
+        }
     }
 
     return status;
 }
 
 CompileStatus
 mjit::Compiler::checkAnalysis(JSScript *script)
 {
@@ -3904,17 +3906,18 @@ mjit::Compiler::inlineScriptedFunction(u
          */
         ensureDoubleArguments();
 
         status = generateMethod();
         if (status != Compile_Okay) {
             popActiveFrame();
             if (status == Compile_Abort) {
                 /* The callee is uncompileable, mark it as uninlineable and retry. */
-                cx->markTypeObjectFlags(script->fun->getType(), types::OBJECT_FLAG_UNINLINEABLE);
+                types::MarkTypeObjectFlags(cx, script->fun->getType(),
+                                           types::OBJECT_FLAG_UNINLINEABLE);
                 return Compile_Retry;
             }
             return status;
         }
 
         if (needReturnValue && !returnSet) {
             if (a->returnSet) {
                 returnSet = true;
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -311,17 +311,17 @@ UncachedInlineCall(VMFrame &f, uint32 fl
     JSObject &callee = vp->toObject();
     JSFunction *newfun = callee.getFunctionPrivate();
     JSScript *newscript = newfun->script();
 
     bool newType = (flags & StackFrame::CONSTRUCTING) && cx->typeInferenceEnabled() &&
         types::UseNewType(cx, f.script(), f.pc());
 
     CallArgs args = CallArgsFromVp(argc, vp);
-    cx->typeMonitorCall(args, flags & StackFrame::CONSTRUCTING);
+    types::TypeMonitorCall(cx, args, flags & StackFrame::CONSTRUCTING);
 
     /* Get pointer to new frame/slots, prepare arguments. */
     StackFrame *newfp = cx->stack.getInlineFrameWithinLimit(cx, f.regs.sp, argc,
                                                             newfun, newscript, &flags,
                                                             f.entryfp, &f.stackLimit, NULL);
     if (JS_UNLIKELY(!newfp))
         return false;
 
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -603,17 +603,17 @@ class SetPropCompiler : public PICStubCo
              * usually be a slowdown even if there *are* other shapes that
              * don't realloc.
              */
             if (obj->numSlots() != slots)
                 return disable("insufficient slot capacity");
 
             if (pic.typeMonitored) {
                 RecompilationMonitor monitor(cx);
-                cx->addTypePropertyId(obj->getType(), shape->propid, pic.rhsTypes);
+                types::AddTypePropertySet(cx, obj->getType(), shape->propid, pic.rhsTypes);
                 if (monitor.recompiled())
                     return Lookup_Uncacheable;
             }
 
             return generateStub(initialShape, shape, true);
         }
 
         const Shape *shape = (const Shape *) prop;
@@ -622,17 +622,17 @@ class SetPropCompiler : public PICStubCo
         if (!shape->writable())
             return disable("readonly");
 
         if (shape->hasDefaultSetter()) {
             if (!shape->hasSlot())
                 return disable("invalid slot");
             if (pic.typeMonitored) {
                 RecompilationMonitor monitor(cx);
-                cx->addTypePropertyId(obj->getType(), shape->propid, pic.rhsTypes);
+                types::AddTypePropertySet(cx, obj->getType(), shape->propid, pic.rhsTypes);
                 if (monitor.recompiled())
                     return Lookup_Uncacheable;
             }
         } else {
             if (shape->hasSetterValue())
                 return disable("scripted setter");
             if (shape->setterOp() != SetCallArg &&
                 shape->setterOp() != SetCallVar) {
--- a/js/src/methodjit/Retcon.cpp
+++ b/js/src/methodjit/Retcon.cpp
@@ -249,18 +249,19 @@ Recompiler::expandInlineFrames(JSContext
     uint8* codeStart = (uint8 *)fp->jit()->code.m_code.executableAddress();
 
     InlineFrame *inner = &fp->jit()->inlineFrames()[inlined->inlineIndex];
     jsbytecode *innerpc = inner->fun->script()->code + inlined->pcOffset;
 
     StackFrame *innerfp = expandInlineFrameChain(cx, fp, inner);
 
     /* Check if the VMFrame returns into the inlined frame. */
-    if (f->stubRejoin && (f->stubRejoin & 0x1) && f->fp() == fp) {
+    if (f->stubRejoin && f->fp() == fp) {
         /* The VMFrame is calling CompileFunction. */
+        JS_ASSERT(f->stubRejoin != REJOIN_NATIVE && f->stubRejoin != REJOIN_NATIVE_LOWERED);
         innerfp->setRejoin(StubRejoin((RejoinState) f->stubRejoin));
         *frameAddr = JS_FUNC_TO_DATA_PTR(void *, JaegerInterpoline);
     }
     if (*frameAddr == codeStart + inlined->codeOffset) {
         /* The VMFrame returns directly into the expanded frame. */
         SetRejoinState(innerfp, *inlined, frameAddr);
     }
 
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -389,17 +389,17 @@ NameOp(VMFrame &f, JSObject *obj, bool c
             NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval, return NULL);
         }
 
         /*
          * If this is an incop, update the property's types themselves,
          * to capture the type effect on the intermediate value.
          */
         if (rval.isUndefined() && (js_CodeSpec[*f.pc()].format & (JOF_INC|JOF_DEC)))
-            cx->addTypePropertyId(obj->getType(), id, types::TYPE_UNDEFINED);
+            AddTypePropertyId(cx, obj->getType(), id, TYPE_UNDEFINED);
     }
 
     f.script()->typeMonitor(cx, f.pc(), rval);
 
     *f.regs.sp++ = rval;
 
     if (callname)
         PushImplicitThis(f, obj, rval);
@@ -444,18 +444,18 @@ stubs::GetElem(VMFrame &f)
     }
 
     if (lref.isMagic(JS_LAZY_ARGUMENTS)) {
         if (rref.isInt32() && size_t(rref.toInt32()) < regs.fp()->numActualArgs()) {
             regs.sp[-2] = regs.fp()->canonicalActualArg(rref.toInt32());
             f.script()->typeMonitor(cx, f.pc(), regs.sp[-2]);
             return;
         }
-        cx->markTypeObjectFlags(f.script()->fun->getType(),
-                                types::OBJECT_FLAG_CREATED_ARGUMENTS);
+        MarkTypeObjectFlags(cx, f.script()->fun->getType(),
+                            OBJECT_FLAG_CREATED_ARGUMENTS);
         JS_ASSERT(!lref.isMagic(JS_LAZY_ARGUMENTS));
     }
 
     JSObject *obj = ValueToObject(cx, &lref);
     if (!obj)
         THROW();
 
     const Value *copyFrom;
@@ -1080,17 +1080,17 @@ MonitorArithmeticOverflow(VMFrame &f, co
     }
 
     JSObject *obj = ValueToObject(cx, &ov);
     if (!obj)
         return;
     JSAtom *atom;
     GET_ATOM_FROM_BYTECODE(f.script(), f.pc(), 0, atom);
 
-    cx->addTypePropertyId(obj->getType(), ATOM_TO_JSID(atom), TYPE_DOUBLE);
+    AddTypePropertyId(cx, obj->getType(), ATOM_TO_JSID(atom), TYPE_DOUBLE);
 }
 
 void JS_FASTCALL
 stubs::Add(VMFrame &f)
 {
     JSContext *cx = f.cx;
     FrameRegs &regs = f.regs;
     Value rval = regs.sp[-1];
@@ -1352,17 +1352,17 @@ void JS_FASTCALL
 stubs::This(VMFrame &f)
 {
     /*
      * We can't yet inline scripts which need to compute their 'this' object
      * from a primitive; the frame we are computing 'this' for does not exist yet.
      */
     if (f.regs.inlined()) {
         JSFunction *fun = f.jit()->inlineFrames()[f.regs.inlined()->inlineIndex].fun;
-        f.cx->markTypeObjectFlags(fun->getType(), OBJECT_FLAG_UNINLINEABLE);
+        MarkTypeObjectFlags(f.cx, fun->getType(), OBJECT_FLAG_UNINLINEABLE);
     }
 
     if (!ComputeThis(f.cx, f.fp()))
         THROW();
     f.regs.sp[-1] = f.fp()->thisValue();
 }
 
 void JS_FASTCALL
@@ -2839,27 +2839,25 @@ stubs::CheckArgumentTypes(VMFrame &f)
 #ifdef DEBUG
 void JS_FASTCALL
 stubs::AssertArgumentTypes(VMFrame &f)
 {
     StackFrame *fp = f.fp();
     JSFunction *fun = fp->fun();
     JSScript *script = fun->script();
 
-    types::jstype type = types::GetValueType(f.cx, fp->thisValue());
-    if (!types::TypeMatches(f.cx, script->thisTypes(), type)) {
-        types::TypeFailure(f.cx, "Missing type for #%u this: %s", script->id(),
-                           types::TypeString(type));
-    }
+    jstype type = GetValueType(f.cx, fp->thisValue());
+    if (!TypeMatches(f.cx, script->thisTypes(), type))
+        TypeFailure(f.cx, "Missing type for #%u this: %s", script->id(), TypeString(type));
 
     for (unsigned i = 0; i < fun->nargs; i++) {
-        type = types::GetValueType(f.cx, fp->formalArg(i));
-        if (!types::TypeMatches(f.cx, script->argTypes(i), type)) {
-            types::TypeFailure(f.cx, "Missing type for #%u arg %d: %s", script->id(), i,
-                               types::TypeString(type));
+        type = GetValueType(f.cx, fp->formalArg(i));
+        if (!TypeMatches(f.cx, script->argTypes(i), type)) {
+            TypeFailure(f.cx, "Missing type for #%u arg %d: %s", script->id(), i,
+                        TypeString(type));
         }
     }
 }
 #endif
 
 /*
  * These two are never actually called, they just give us a place to rejoin if
  * there is an invariant failure when initially entering a loop.
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3275,17 +3275,17 @@ ResolveClass(JSContext *cx, JSObject *ob
 static JSBool
 split_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp)
 {
     /*
      * This can resolve properties which are not on the original object's
      * prototype chain, breaking assumptions type inference makes about the
      * possible properties on an object.
      */
-    cx->addTypePropertyId(obj->getType(), id, types::TYPE_UNKNOWN);
+    types::AddTypePropertyId(cx, obj->getType(), id, types::TYPE_UNKNOWN);
 
     ComplexObject *cpx;
 
     if (JSID_IS_ATOM(id) && JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(id), "isInner")) {
         *objp = obj;
         return JS_DefinePropertyById(cx, obj, id, JSVAL_VOID, NULL, NULL, JSPROP_SHARED);
     }
 
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -90,19 +90,19 @@ js_InitFunctionAndObjectClasses(JSContex
     if (!obj_proto)
         return NULL;
 
     /*
      * Function.prototype and the global object delegate to Object.prototype.
      * Don't update the prototype if the __proto__ of either object was cleared
      * after the objects started getting used.
      */
-    if (!fun_proto->getProto() && fun_proto->getType() != cx->getTypeEmpty())
+    if (!fun_proto->getProto() && fun_proto->getType() != types::GetTypeEmpty(cx))
         fun_proto->getType()->splicePrototype(cx, obj_proto);
-    if (!obj->getProto() && obj->getType() != cx->getTypeEmpty())
+    if (!obj->getProto() && obj->getType() != types::GetTypeEmpty(cx))
         obj->getType()->splicePrototype(cx, obj_proto);
 
     return fun_proto;
 }
 
 namespace js {
 
 GlobalObject *
@@ -114,17 +114,17 @@ GlobalObject::create(JSContext *cx, Clas
     if (!obj)
         return NULL;
 
     types::TypeObject *type = cx->compartment->types.newTypeObject(cx, NULL, "Global", "",
                                                                    false, false, NULL);
     if (!type || !obj->setTypeAndUniqueShape(cx, type))
         return NULL;
     if (clasp->ext.equality)
-        cx->markTypeObjectFlags(type, types::OBJECT_FLAG_SPECIAL_EQUALITY);
+        MarkTypeObjectFlags(cx, type, types::OBJECT_FLAG_SPECIAL_EQUALITY);
     type->singleton = obj;
 
     GlobalObject *globalObj = obj->asGlobal();
 
     globalObj->syncSpecialEquality();
 
     /* Construct a regexp statics object for this global object. */
     JSObject *res = regexp_statics_construct(cx, globalObj);
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -611,17 +611,17 @@ pref("javascript.options.strict.debug", 
 #endif
 pref("javascript.options.relimit",          true);
 pref("javascript.options.tracejit.content",  true);
 pref("javascript.options.tracejit.chrome",   true);
 pref("javascript.options.methodjit.content", true);
 pref("javascript.options.methodjit.chrome",  true);
 pref("javascript.options.jitprofiling.content", true);
 pref("javascript.options.jitprofiling.chrome",  true);
-pref("javascript.options.methodjit_always", true);
+pref("javascript.options.methodjit_always", false);
 pref("javascript.options.typeinference", true);
 // This preference limits the memory usage of javascript.
 // If you want to change these values for your device,
 // please find Bug 417052 comment 17 and Bug 456721
 // Comment 32 and Bug 613551.
 pref("javascript.options.mem.high_water_mark", 128);
 pref("javascript.options.mem.max", -1);
 pref("javascript.options.mem.gc_frequency",   300);