[INFER] Move inference methods out of JSContext, bug 657412.
authorBrian Hackett <bhackett1024@gmail.com>
Thu, 02 Jun 2011 10:40:27 -0700
changeset 76148 b9679727505db2d932c2f1815a94a0a73a8723e8
parent 76147 cbd95be079612742815f98591394a58bac656960
child 76149 aa4d3d18621efe9282615ffb959922b121d4e014
push id67
push userclegnitto@mozilla.com
push dateFri, 04 Nov 2011 22:39:41 +0000
treeherdermozilla-release@04778346a3b0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs657412
milestone6.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
[INFER] 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);