[INFER] Read barriers for call results, bug 663381.
authorBrian Hackett <bhackett1024@gmail.com>
Fri, 10 Jun 2011 19:03:57 -0700
changeset 75159 a2dbb9efcf9ea6125476948278b6a00ef6e3d2bd
parent 75158 a70672667195dbf3e998e30ac14545de6f6efe0d
child 75160 38f2fbc8490da4389234ed4659b67d1aeb2a9195
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs663381
milestone7.0a1
[INFER] Read barriers for call results, bug 663381.
js/src/jit-test/tests/basic/bug657975.js
js/src/jit-test/tests/jaeger/bug563000/eif-trap.js
js/src/jit-test/tests/jaeger/bug563000/trap-from-add-ool.js
js/src/jit-test/tests/jaeger/bug563000/trap-parent.js
js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js
js/src/jit-test/tests/jaeger/bug563000/trap-self.js
js/src/jit-test/tests/jaeger/bug563000/untrap-self.js
js/src/jsanalyze.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsbool.cpp
js/src/jsdate.cpp
js/src/jsdbgapi.cpp
js/src/jsemit.cpp
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsfun.h
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/jsobj.h
js/src/json.cpp
js/src/jsopcode.tbl
js/src/jsparse.cpp
js/src/jspropertycache.cpp
js/src/jsproxy.cpp
js/src/jspubtd.h
js/src/jsreflect.cpp
js/src/jsregexp.cpp
js/src/jsstr.cpp
js/src/jstypedarray.cpp
js/src/jsweakmap.cpp
js/src/jswrapper.cpp
js/src/jsxml.cpp
js/src/methodjit/BaseAssembler.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/FastBuiltins.cpp
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/MonoIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/methodjit/StubCalls.h
js/src/shell/js.cpp
--- a/js/src/jit-test/tests/basic/bug657975.js
+++ b/js/src/jit-test/tests/basic/bug657975.js
@@ -70,10 +70,10 @@ f10 = (function() {
         continue
     }
 })
 trap(f10, 0, '');
 try { f10() } catch (e) {}
 
 // bug 659337
 f11 = Function("for (x = 0; x < 6; x++) { gc() }");
-trap(f11, 23, '');
+trap(f11, 25, '');
 f11()
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js
@@ -2,10 +2,10 @@
 setDebug(true);
 
 function nop(){}
 function caller(obj) {
   assertJit();
   var x = "failure";
   return x;
 }
-trap(caller, 16, "x = 'success'; nop()");
+trap(caller, 18, "x = 'success'; nop()");
 assertEq(caller(this), "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-from-add-ool.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-from-add-ool.js
@@ -1,14 +1,14 @@
 // |jit-test| debug
 setDebug(true);
 x = "notset";
 function main() {
   /* The JSOP_STOP in a. */
-  a = { valueOf: function () { trap(main, 63, "success()"); } };
+  a = { valueOf: function () { trap(main, 65, "success()"); } };
   b = "";
   eval();
   a + b;
   x = "failure";
 }
 function success() { x = "success"; }
 
 main();
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js
@@ -1,14 +1,14 @@
 // |jit-test| debug
 setDebug(true);
 x = "notset";
 function child() {
   /* JSOP_STOP in parent. */
-  trap(parent, 19, "success()");
+  trap(parent, 21, "success()");
 }
 function parent() {
   child();
   x = "failure";
 }
 function success() {
   x = "success";
 }
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js
@@ -2,23 +2,23 @@
 setDebug(true);
 x = "notset";
 
 function doNothing() { }
 
 function myparent(nested) {
   if (nested) {
     /* JSOP_CALL to doNothing in myparent with nested = true. */
-    trap(myparent, 30, "success()");
+    trap(myparent, 32, "success()");
     doNothing();
   } else {
     doNothing();
   }
 }
 /* JSOP_CALL to doNothing in myparent with nested = false. */
-trap(myparent, 43, "myparent(true)");
+trap(myparent, 47, "myparent(true)");
 
 function success() {
   x = "success";
 }
 
 myparent(false);
 assertEq(x, "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-self.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-self.js
@@ -1,12 +1,12 @@
 // |jit-test| debug
 setDebug(true);
 x = "notset";
 function main() {
   /* The JSOP_STOP in a. */
-  trap(main, 29, "success()");
+  trap(main, 31, "success()");
   x = "failure";
 }
 function success() { x = "success"; }
 
 main();
 assertEq(x, "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/untrap-self.js
@@ -1,14 +1,14 @@
 // |jit-test| debug
 setDebug(true);
 x = "notset";
 function main() {
   /* JSOP_STOP in main. */
-  untrap(main, 26);
+  untrap(main, 28);
   x = "success";
 }
 function failure() { x = "failure"; }
 
 /* JSOP_STOP in main. */
-trap(main, 26, "failure()");
+trap(main, 28, "failure()");
 main();
 assertEq(x, "success");
--- a/js/src/jsanalyze.h
+++ b/js/src/jsanalyze.h
@@ -132,16 +132,19 @@ class Bytecode
     bool safePoint : 1;
 
     /*
      * Side effects of this bytecode were not determined by type inference.
      * Either a property set with unknown lvalue, or call with unknown callee.
      */
     bool monitoredTypes : 1;
 
+    /* Call whose result should be monitored. */
+    bool monitoredTypesReturn : 1;
+
     /* Stack depth before this opcode. */
     uint32 stackDepth;
 
   private:
     /*
      * The set of locals defined at this point. This does not include locals which
      * were unconditionally defined at an earlier point in the script.
      */
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2866,17 +2866,17 @@ JS_InitClass(JSContext *cx, JSObject *ob
              JSClass *clasp, JSNative constructor, uintN nargs,
              JSPropertySpec *ps, JSFunctionSpec *fs,
              JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, parent_proto);
     return js_InitClass(cx, obj, parent_proto, Valueify(clasp),
                         Valueify(constructor), nargs,
-                        NULL, ps, fs, static_ps, static_fs);
+                        ps, fs, static_ps, static_fs);
 }
 
 #ifdef JS_THREADSAFE
 JS_PUBLIC_API(JSClass *)
 JS_GetClass(JSContext *cx, JSObject *obj)
 {
     return Jsvalify(obj->getClass());
 }
@@ -4206,30 +4206,30 @@ JS_NewFunction(JSContext *cx, JSNative n
 
     if (!name) {
         atom = NULL;
     } else {
         atom = js_Atomize(cx, name, strlen(name));
         if (!atom)
             return NULL;
     }
-    return js_NewFunction(cx, NULL, Valueify(native), nargs, flags, parent, atom, NULL, name);
+    return js_NewFunction(cx, NULL, Valueify(native), nargs, flags, parent, atom);
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_NewFunctionById(JSContext *cx, JSNative native, uintN nargs, uintN flags, JSObject *parent,
                    jsid id)
 {
     JS_ASSERT(JSID_IS_STRING(id));
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
     return js_NewFunction(cx, NULL, Valueify(native), nargs, flags, parent,
-                          JSID_TO_ATOM(id), NULL, NULL);
+                          JSID_TO_ATOM(id));
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);  // XXX no funobj for now
     if (!parent) {
@@ -4300,100 +4300,16 @@ JS_CloneFunctionObject(JSContext *cx, JS
             return NULL;
         fun->script()->types.setUpvar(cx, i, v);
         clone->getFlatClosureUpvars()[i] = v;
     }
 
     return clone;
 }
 
-JS_PUBLIC_API(void)
-JS_TypeHandlerDynamic(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-    site->returnTypes->addType(cx, TYPE_UNKNOWN);
-}
-
-JS_PUBLIC_API(void)
-JS_TypeHandlerVoid(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    site->returnTypes->addType(cx, TYPE_UNDEFINED);
-}
-
-JS_PUBLIC_API(void)
-JS_TypeHandlerNull(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    site->returnTypes->addType(cx, TYPE_NULL);
-}
-
-JS_PUBLIC_API(void)
-JS_TypeHandlerBool(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    site->returnTypes->addType(cx, TYPE_BOOLEAN);
-}
-
-JS_PUBLIC_API(void)
-JS_TypeHandlerInt(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    site->returnTypes->addType(cx, TYPE_INT32);
-}
-
-JS_PUBLIC_API(void)
-JS_TypeHandlerFloat(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    site->returnTypes->addType(cx, TYPE_DOUBLE);
-}
-
-JS_PUBLIC_API(void)
-JS_TypeHandlerString(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    site->returnTypes->addType(cx, TYPE_STRING);
-}
-
-JS_PUBLIC_API(void)
-JS_TypeHandlerNew(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeFunction *fun = Valueify(jsfun);
-    TypeCallsite *site = Valueify(jssite);
-
-    TypeSet *prototypeTypes =
-        fun->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), true);
-    if (!prototypeTypes)
-        return;
-    prototypeTypes->addNewObject(cx, site->script, fun, site->returnTypes);
-}
-
-JS_PUBLIC_API(void)
-JS_TypeHandlerThis(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    site->thisTypes->addSubset(cx, site->script, site->returnTypes);
-}
-
 JS_PUBLIC_API(JSObject *)
 JS_GetFunctionObject(JSFunction *fun)
 {
     return FUN_OBJECT(fun);
 }
 
 JS_PUBLIC_API(JSString *)
 JS_GetFunctionId(JSFunction *fun)
@@ -4485,76 +4401,71 @@ JS_DefineFunctions(JSContext *cx, JSObje
                 if (!ctor)
                     return JS_FALSE;
             }
 
             flags &= ~JSFUN_GENERIC_NATIVE;
             fun = js_DefineFunction(cx, ctor, ATOM_TO_JSID(atom),
                                     js_generic_native_method_dispatcher,
                                     fs->nargs + 1,
-                                    flags & ~JSFUN_TRCINFO,
-                                    fs->handler, fs->name);
+                                    flags & ~JSFUN_TRCINFO);
             if (!fun)
                 return JS_FALSE;
 
-            if (cx->typeInferenceEnabled())
-                fun->getType()->asFunction()->isGeneric = true;
-
             /*
              * As jsapi.h notes, fs must point to storage that lives as long
              * as fun->object lives.
              */
             Value priv = PrivateValue(fs);
             if (!js_SetReservedSlot(cx, FUN_OBJECT(fun), 0, priv))
                 return JS_FALSE;
         }
 
-        fun = js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), Valueify(fs->call), fs->nargs, flags,
-                                fs->handler, fs->name);
+        fun = js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), Valueify(fs->call), fs->nargs, flags);
         if (!fun)
             return JS_FALSE;
     }
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
                   uintN nargs, uintN attrs)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     if (!atom)
         return NULL;
-    return js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), Valueify(call), nargs, attrs, NULL, name);
+    return js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), Valueify(call), nargs, attrs);
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_DefineUCFunction(JSContext *cx, JSObject *obj,
                     const jschar *name, size_t namelen, JSNative call,
                     uintN nargs, uintN attrs)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     if (!atom)
         return NULL;
-    return js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), Valueify(call), nargs, attrs, NULL, "UCFunction");
+    return js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), Valueify(call), nargs, attrs);
 }
 
 extern JS_PUBLIC_API(JSFunction *)
 JS_DefineFunctionById(JSContext *cx, JSObject *obj, jsid id, JSNative call,
                     uintN nargs, uintN attrs)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-    return js_DefineFunction(cx, obj, id, Valueify(call), nargs, attrs, NULL, NULL);
+    return js_DefineFunction(cx, obj, id, Valueify(call), nargs, attrs);
 }
 
 inline static void
 LAST_FRAME_EXCEPTION_CHECK(JSContext *cx, bool result)
 {
     if (!result && !cx->hasRunOption(JSOPTION_DONT_REPORT_UNCAUGHT))
         js_ReportUncaughtException(cx);
 }
@@ -4864,17 +4775,17 @@ CompileUCFunctionForPrincipalsCommon(JSC
     } else {
         funAtom = js_Atomize(cx, name, strlen(name));
         if (!funAtom) {
             fun = NULL;
             goto out2;
         }
     }
 
-    fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom, NULL, NULL);
+    fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom);
     if (!fun)
         goto out2;
 
     {
         AutoObjectRooter tvr(cx, FUN_OBJECT(fun));
         MUST_FLOW_THROUGH("out");
 
         Bindings bindings(cx);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2088,41 +2088,33 @@ struct JSPropertySpec {
     JSStrictPropertyOp    setter;
 };
 
 struct JSFunctionSpec {
     const char      *name;
     JSNative        call;
     uint16          nargs;
     uint16          flags;
-
-    /* Optional callback giving type information for calls to this function. */
-    JSTypeHandler   handler;
 };
 
 /*
  * Terminating sentinel initializer to put at the end of a JSFunctionSpec array
  * that's passed to JS_DefineFunctions or JS_InitClass.
  */
 #define JS_FS_END JS_FS(NULL,NULL,0,0)
 
 /*
  * Initializer macros for a JSFunctionSpec array element. JS_FN (whose name
  * pays homage to the old JSNative/JSFastNative split) simply adds the flag
  * JSFUN_STUB_GSOPS.
  */
 #define JS_FS(name,call,nargs,flags)                                          \
-    JS_FS_TYPE(name,call,nargs,flags,NULL)
-#define JS_FS_TYPE(name,call,nargs,flags,handler)                             \
-    {name, (JSNative) call, nargs, flags, handler}
-
+    {name, call, nargs, flags}
 #define JS_FN(name,call,nargs,flags)                                          \
-    JS_FN_TYPE(name,call,nargs,flags,NULL)
-#define JS_FN_TYPE(name,call,nargs,flags,handler)                             \
-    {name, (JSNative) call, nargs, (flags) | JSFUN_STUB_GSOPS, handler}
+    {name, call, nargs, (flags) | JSFUN_STUB_GSOPS}
 
 extern JS_PUBLIC_API(JSObject *)
 JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
              JSClass *clasp, JSNative constructor, uintN nargs,
              JSPropertySpec *ps, JSFunctionSpec *fs,
              JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
 
 #ifdef JS_THREADSAFE
@@ -2660,54 +2652,16 @@ JS_DefineUCFunction(JSContext *cx, JSObj
 
 extern JS_PUBLIC_API(JSFunction *)
 JS_DefineFunctionById(JSContext *cx, JSObject *obj, jsid id, JSNative call,
                       uintN nargs, uintN attrs);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent);
 
-/* Frequently used type handlers */
-
-/*
- * Handler which does not describe a function's return value at all. The return
- * value will be observed at runtime and its type used to augment the results
- * of the inference.
- */
-extern JS_PUBLIC_API(void)
-JS_TypeHandlerDynamic(JSContext*, JSTypeFunction*, JSTypeCallsite*);
-
-/* Handlers whose return types are particular primitives. */
-
-extern JS_PUBLIC_API(void)
-JS_TypeHandlerVoid(JSContext*, JSTypeFunction*, JSTypeCallsite*);
-
-extern JS_PUBLIC_API(void)
-JS_TypeHandlerNull(JSContext*, JSTypeFunction*, JSTypeCallsite*);
-
-extern JS_PUBLIC_API(void)
-JS_TypeHandlerBool(JSContext*, JSTypeFunction*, JSTypeCallsite*);
-
-extern JS_PUBLIC_API(void)
-JS_TypeHandlerInt(JSContext*, JSTypeFunction*, JSTypeCallsite*);
-
-extern JS_PUBLIC_API(void)
-JS_TypeHandlerFloat(JSContext*, JSTypeFunction*, JSTypeCallsite*);
-
-extern JS_PUBLIC_API(void)
-JS_TypeHandlerString(JSContext*, JSTypeFunction*, JSTypeCallsite*);
-
-/* Handler whose return type is the new object for the native function. */
-extern JS_PUBLIC_API(void)
-JS_TypeHandlerNew(JSContext*, JSTypeFunction*, JSTypeCallsite*);
-
-/* Handler whose return type is the same as its 'this' type. */
-extern JS_PUBLIC_API(void)
-JS_TypeHandlerThis(JSContext*, JSTypeFunction*, JSTypeCallsite*);
-
 /*
  * Given a buffer, return JS_FALSE if the buffer might become a valid
  * javascript statement with the addition of more lines.  Otherwise return
  * JS_TRUE.  The intent is to support interactive compilation - accumulate
  * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to
  * the compiler.
  */
 extern JS_PUBLIC_API(JSBool)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2173,21 +2173,16 @@ array_push_slowly(JSContext *cx, JSObjec
     if (!js_GetLengthProperty(cx, obj, &length))
         return JS_FALSE;
     if (!InitArrayElements(cx, obj, length, argc, argv, true))
         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())
-        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();
     do {
@@ -2289,48 +2284,42 @@ array_pop_slowly(JSContext *cx, JSObject
 {
     jsuint index;
     JSBool hole;
 
     if (!js_GetLengthProperty(cx, obj, &index))
         return JS_FALSE;
     if (index == 0) {
         vp->setUndefined();
-        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)
-            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();
-        MarkTypeCallerUnexpected(cx, TYPE_UNDEFINED);
         return JS_TRUE;
     }
     index--;
     if (!GetElement(cx, obj, index, &hole, vp))
         return JS_FALSE;
-    if (hole)
-        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,28 +2343,25 @@ 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();
-        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)) {
+            if (vp->isMagic(JS_ARRAY_HOLE))
                 vp->setUndefined();
-                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);
             if (!js_SuppressDeletedIndexProperties(cx, obj, length, length + 1))
@@ -2383,19 +2369,16 @@ array_shift(JSContext *cx, uintN argc, V
             return JS_TRUE;
         }
 
         /* 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)
-            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;
             }
@@ -2468,47 +2451,40 @@ array_unshift(JSContext *cx, uintN argc,
 
         newlen += 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())
-        MarkTypeCallerOverflow(cx);
-
     return JS_TRUE;
 }
 
 static JSBool
 array_splice(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj = ToObject(cx, &vp[1]);
     if (!obj)
         return false;
 
     jsuint length, begin, end, count, delta, last;
     JSBool hole;
 
-    /* Get the type of the result object. */
+    /*
+     * Get the type of the result object: the original type when splicing an
+     * array, a generic array type otherwise.
+     */
     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 = GetTypeNewObject(cx, JSProto_Array);
         if (!type)
             return false;
-        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);
@@ -2676,32 +2652,29 @@ array_concat(JSContext *cx, uintN argc, 
         length = aobj->getArrayLength();
         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
-            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;
-        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++) {
@@ -2791,29 +2764,24 @@ array_slice(JSContext *cx, uintN argc, V
             }
             end = (jsuint)d;
         }
     }
 
     if (begin > end)
         begin = end;
 
-    /* Get the type object for the returned array. */
+    /* Get the type object for the returned array, as for array_splice. */
     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 = GetTypeNewObject(cx, JSProto_Array);
         if (!type)
             return false;
-        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);
@@ -2901,18 +2869,17 @@ array_indexOfHelper(JSContext *cx, JSBoo
             !GetElement(cx, obj, (jsuint)i, &hole, vp)) {
             return JS_FALSE;
         }
         if (!hole) {
             JSBool equal;
             if (!StrictlyEqual(cx, *vp, tosearch, &equal))
                 return JS_FALSE;
             if (equal) {
-                if (!vp->setNumber(i))
-                    MarkTypeCallerOverflow(cx);
+                vp->setNumber(i);
                 return JS_TRUE;
             }
         }
         if (i == stop)
             goto not_found;
         i += direction;
     }
 
@@ -3171,223 +3138,67 @@ array_some(JSContext *cx, uintN argc, Va
 
 static JSBool
 array_every(JSContext *cx, uintN argc, Value *vp)
 {
     return array_extra(cx, EVERY, argc, vp);
 }
 #endif
 
-/*
- * These handlers deal with objects of type other than arrays, except for updates
- * of the 'length' property. Sets of length on non-arrays and overflowing length
- * on arrays are both handled by write barriers within the natives.
- */
-
-static void
-array_TypeSort(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    site->thisTypes->addSubset(cx, site->script, site->returnTypes);
-}
-
-static void
-array_TypeInsert(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-
-    /* The return type is an integer (array length). */
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    site->returnTypes->addType(cx, TYPE_INT32);
-
-    for (size_t ind = 0; ind < site->argumentCount; ind++) {
-        site->thisTypes->addSetProperty(cx, site->script, site->pc,
-                                        site->argumentTypes[ind], JSID_VOID);
-    }
-}
-
-static void
-array_TypeRemove(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    site->thisTypes->addGetProperty(cx, site->script, site->pc, site->returnTypes, JSID_VOID);
-}
-
-static void
-array_TypeSplice(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-
-    /* Treat the returned array the same as the 'this' array. */
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    site->thisTypes->addSubset(cx, site->script, site->returnTypes);
-
-    /* All arguments beyond the first two are new array elements. */
-    for (size_t ind = 2; ind < site->argumentCount; ind++) {
-        site->thisTypes->addSetProperty(cx, site->script, site->pc,
-                                        site->argumentTypes[ind], JSID_VOID);
-    }
-}
-
-static void
-array_TypeConcat(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-
-    if (!site->script->hasGlobal()) {
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-        return;
-    }
-
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    site->thisTypes->addSubset(cx, site->script, site->returnTypes);
-}
-
-static void
-array_TypeSlice(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    site->thisTypes->addFilterPrimitives(cx, site->script, site->returnTypes, false);
-}
-
-/* Handler for all higher order array builtins. */
-static void
-array_TypeExtra(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite,
-                ArrayExtraMode mode)
-{
-    TypeCallsite *site = Valueify(jssite);
-
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-
-    switch (mode) {
-
-      case FOREACH:
-        site->returnTypes->addType(cx, TYPE_UNDEFINED);
-        break;
-
-      case REDUCE:
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-        break;
-
-      case MAP:
-      case FILTER:
-        if (site->script->hasGlobal()) {
-            /* Makes a new array whose element type will be filled in as the code runs. */
-            TypeObject *object = site->getInitObject(cx, true);
-            if (!object)
-                return;
-            site->returnTypes->addType(cx, (jstype) object);
-        } else {
-            site->returnTypes->addType(cx, TYPE_UNKNOWN);
-        }
-        break;
-
-      case SOME:
-        site->returnTypes->addType(cx, TYPE_BOOLEAN);
-        break;
-
-      default:
-        JS_NOT_REACHED("Unexpected ArrayExtraMode");
-    }
-}
-
-static void
-array_TypeExtraForEach(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    array_TypeExtra(cx, jsfun, jssite, FOREACH);
-}
-
-static void
-array_TypeExtraMap(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    array_TypeExtra(cx, jsfun, jssite, MAP);
-}
-
-static void
-array_TypeExtraReduce(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    array_TypeExtra(cx, jsfun, jssite, REDUCE);
-}
-
-static void
-array_TypeExtraFilter(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    array_TypeExtra(cx, jsfun, jssite, FILTER);
-}
-
-static void
-array_TypeExtraSome(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    array_TypeExtra(cx, jsfun, jssite, SOME);
-}
-
 static JSBool
 array_isArray(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj;
     vp->setBoolean(argc > 0 &&
                    vp[2].isObject() &&
                    ((obj = &vp[2].toObject())->isArray() ||
                     (obj->isWrapper() && obj->unwrap()->isArray())));
     return true;
 }
 
 #define GENERIC JSFUN_GENERIC_NATIVE
 
 static JSFunctionSpec array_methods[] = {
 #if JS_HAS_TOSOURCE
-    JS_FN_TYPE(js_toSource_str,      array_toSource,     0,0, JS_TypeHandlerString),
+    JS_FN(js_toSource_str,      array_toSource,     0,0),
 #endif
-    JS_FN_TYPE(js_toString_str,      array_toString,     0,0, JS_TypeHandlerString),
-    JS_FN_TYPE(js_toLocaleString_str,array_toLocaleString,0,0, JS_TypeHandlerString),
+    JS_FN(js_toString_str,      array_toString,     0,0),
+    JS_FN(js_toLocaleString_str,array_toLocaleString,0,0),
 
     /* Perl-ish methods. */
-    JS_FN_TYPE("join",               array_join,         1,GENERIC, JS_TypeHandlerString),
-    JS_FN_TYPE("reverse",            array_reverse,      0,GENERIC, JS_TypeHandlerThis),
-    JS_FN_TYPE("sort",               array_sort,         1,GENERIC, array_TypeSort),
-    JS_FN_TYPE("push",               array_push,         1,GENERIC, array_TypeInsert),
-    JS_FN_TYPE("pop",                array_pop,          0,GENERIC, array_TypeRemove),
-    JS_FN_TYPE("shift",              array_shift,        0,GENERIC, array_TypeRemove),
-    JS_FN_TYPE("unshift",            array_unshift,      1,GENERIC, array_TypeInsert),
-    JS_FN_TYPE("splice",             array_splice,       2,GENERIC, array_TypeSplice),
+    JS_FN("join",               array_join,         1,JSFUN_GENERIC_NATIVE),
+    JS_FN("reverse",            array_reverse,      0,JSFUN_GENERIC_NATIVE),
+    JS_FN("sort",               array_sort,         1,JSFUN_GENERIC_NATIVE),
+    JS_FN("push",               array_push,         1,JSFUN_GENERIC_NATIVE),
+    JS_FN("pop",                array_pop,          0,JSFUN_GENERIC_NATIVE),
+    JS_FN("shift",              array_shift,        0,JSFUN_GENERIC_NATIVE),
+    JS_FN("unshift",            array_unshift,      1,JSFUN_GENERIC_NATIVE),
+    JS_FN("splice",             array_splice,       2,JSFUN_GENERIC_NATIVE),
 
     /* Pythonic sequence methods. */
-    JS_FN_TYPE("concat",             array_concat,       1,GENERIC, array_TypeConcat),
-    JS_FN_TYPE("slice",              array_slice,        2,GENERIC, array_TypeSlice),
+    JS_FN("concat",             array_concat,       1,JSFUN_GENERIC_NATIVE),
+    JS_FN("slice",              array_slice,        2,JSFUN_GENERIC_NATIVE),
 
 #if JS_HAS_ARRAY_EXTRAS
-    JS_FN_TYPE("indexOf",            array_indexOf,      1,GENERIC, JS_TypeHandlerInt),
-    JS_FN_TYPE("lastIndexOf",        array_lastIndexOf,  1,GENERIC, JS_TypeHandlerInt),
-    JS_FN_TYPE("forEach",            array_forEach,      1,GENERIC, array_TypeExtraForEach),
-    JS_FN_TYPE("map",                array_map,          1,GENERIC, array_TypeExtraMap),
-    JS_FN_TYPE("reduce",             array_reduce,       1,GENERIC, array_TypeExtraReduce),
-    JS_FN_TYPE("reduceRight",        array_reduceRight,  1,GENERIC, array_TypeExtraReduce),
-    JS_FN_TYPE("filter",             array_filter,       1,GENERIC, array_TypeExtraFilter),
-    JS_FN_TYPE("some",               array_some,         1,GENERIC, array_TypeExtraSome),
-    JS_FN_TYPE("every",              array_every,        1,GENERIC, array_TypeExtraSome),
+    JS_FN("indexOf",            array_indexOf,      1,JSFUN_GENERIC_NATIVE),
+    JS_FN("lastIndexOf",        array_lastIndexOf,  1,JSFUN_GENERIC_NATIVE),
+    JS_FN("forEach",            array_forEach,      1,JSFUN_GENERIC_NATIVE),
+    JS_FN("map",                array_map,          1,JSFUN_GENERIC_NATIVE),
+    JS_FN("reduce",             array_reduce,       1,JSFUN_GENERIC_NATIVE),
+    JS_FN("reduceRight",        array_reduceRight,  1,JSFUN_GENERIC_NATIVE),
+    JS_FN("filter",             array_filter,       1,JSFUN_GENERIC_NATIVE),
+    JS_FN("some",               array_some,         1,JSFUN_GENERIC_NATIVE),
+    JS_FN("every",              array_every,        1,JSFUN_GENERIC_NATIVE),
 #endif
 
     JS_FS_END
 };
 
 static JSFunctionSpec array_static_methods[] = {
-    JS_FN_TYPE("isArray",            array_isArray,      1,0, JS_TypeHandlerBool),
+    JS_FN("isArray",            array_isArray,      1,0),
     JS_FS_END
 };
 
 JSBool
 js_Array(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj;
 
@@ -3419,57 +3230,20 @@ js_Array(JSContext *cx, uintN argc, Valu
     /* If the length calculation overflowed, make sure that is marked for the new type. */
     if (obj->getArrayLength() > INT32_MAX)
         obj->setArrayLength(cx, obj->getArrayLength());
 
     vp->setObject(*obj);
     return JS_TRUE;
 }
 
-/*
- * Specialized handler for Array() that propagates arguments into indexes of
- * the resulting array.
- */
-static void
-array_TypeNew(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-
-    if (!site->script->hasGlobal()) {
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-        return;
-    }
-
-    TypeObject *object = site->getInitObject(cx, true);
-    if (!object)
-        return;
-    site->returnTypes->addType(cx, (jstype) object);
-
-    if (object->unknownProperties())
-        return;
-
-    TypeSet *indexTypes = object->getProperty(cx, JSID_VOID, true);
-    if (!indexTypes)
-        return;
-
-    /*
-     * Ignore the case where the call is passed a single argument. This is
-     * expected to be the array length, but if it isn't we will catch it in the
-     * Array native itself.
-     */
-    if (site->argumentCount > 1) {
-        for (size_t ind = 0; ind < site->argumentCount; ind++)
-            site->argumentTypes[ind]->addSubset(cx, site->script, indexTypes);
-    }
-}
-
 JSObject *
 js_InitArrayClass(JSContext *cx, JSObject *obj)
 {
-    JSObject *proto = js_InitClass(cx, obj, NULL, &js_ArrayClass, js_Array, 1, array_TypeNew,
+    JSObject *proto = js_InitClass(cx, obj, NULL, &js_ArrayClass, js_Array, 1,
                                    NULL, array_methods, NULL, array_static_methods);
     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.
      */
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -119,20 +119,20 @@ bool_valueOf(JSContext *cx, uintN argc, 
         return false;
 
     vp->setBoolean(b);
     return JS_TRUE;
 }
 
 static JSFunctionSpec boolean_methods[] = {
 #if JS_HAS_TOSOURCE
-    JS_FN_TYPE(js_toSource_str,  bool_toSource,  0, 0, JS_TypeHandlerString),
+    JS_FN(js_toSource_str,  bool_toSource,  0, 0),
 #endif
-    JS_FN_TYPE(js_toString_str,  bool_toString,  0, 0, JS_TypeHandlerString),
-    JS_FN_TYPE(js_valueOf_str,   bool_valueOf,   0, 0, JS_TypeHandlerBool),
+    JS_FN(js_toString_str,  bool_toString,  0, 0),
+    JS_FN(js_valueOf_str,   bool_valueOf,   0, 0),
     JS_FS_END
 };
 
 static JSBool
 Boolean(JSContext *cx, uintN argc, Value *vp)
 {
     Value *argv = vp + 2;
     bool b = argc != 0 ? js_ValueToBoolean(argv[0]) : false;
@@ -144,28 +144,20 @@ Boolean(JSContext *cx, uintN argc, Value
         obj->setPrimitiveThis(BooleanValue(b));
         vp->setObject(*obj);
     } else {
         vp->setBoolean(b);
     }
     return true;
 }
 
-static void type_NewBoolean(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    if (Valueify(jssite)->isNew)
-        JS_TypeHandlerNew(cx, jsfun, jssite);
-    else
-        JS_TypeHandlerBool(cx, jsfun, jssite);
-}
-
 JSObject *
 js_InitBooleanClass(JSContext *cx, JSObject *obj)
 {
-    JSObject *proto = js_InitClass(cx, obj, NULL, &js_BooleanClass, Boolean, 1, type_NewBoolean,
+    JSObject *proto = js_InitClass(cx, obj, NULL, &js_BooleanClass, Boolean, 1,
                                    NULL, boolean_methods, NULL, NULL);
     if (!proto)
         return NULL;
     proto->setPrimitiveThis(BooleanValue(false));
     return proto;
 }
 
 JSString *
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -1449,210 +1449,184 @@ 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())
-            MarkTypeCallerOverflow(cx);
     }
 
     return true;
 }
 
 static JSBool
 date_getFullYear(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj = ToObject(cx, &vp[1]);
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return JS_FALSE;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_YEAR);
-    if (!vp->isInt32())
-        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
-        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return true;
 }
 
 static JSBool
 date_getMonth(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj = ToObject(cx, &vp[1]);
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return false;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MONTH);
-    if (!vp->isInt32())
-        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
-        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return true;
 }
 
 static JSBool
 date_getDate(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj = ToObject(cx, &vp[1]);
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return false;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DATE);
-    if (!vp->isInt32())
-        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
-        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return true;
 }
 
 static JSBool
 date_getDay(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj = ToObject(cx, &vp[1]);
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return false;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DAY);
-    if (!vp->isInt32())
-        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
-        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return true;
 }
 
 static JSBool
 date_getHours(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj = ToObject(cx, &vp[1]);
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return false;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_HOURS);
-    if (!vp->isInt32())
-        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
-        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return JS_TRUE;
 }
 
 static JSBool
 date_getMinutes(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj = ToObject(cx, &vp[1]);
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return false;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MINUTES);
-    if (!vp->isInt32())
-        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
-        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return true;
 }
 
 /* Date.getSeconds is mapped to getUTCSeconds */
 
 static JSBool
@@ -1661,34 +1635,30 @@ date_getUTCSeconds(JSContext *cx, uintN 
     JSObject *obj = ToObject(cx, &vp[1]);
     if (!obj)
         return false;
 
     if (!GetAndCacheLocalTime(cx, obj, vp))
         return false;
 
     *vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_SECONDS);
-    if (!vp->isInt32())
-        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
-        MarkTypeCallerOverflow(cx);
 
     vp->setNumber(result);
     return true;
 }
 
 static JSBool
 date_getTimezoneOffset(JSContext *cx, uintN argc, Value *vp)
 {
@@ -1705,19 +1675,16 @@ date_getTimezoneOffset(JSContext *cx, ui
         return false;
 
     /*
      * 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))
-        MarkTypeCallerOverflow(cx);
-
     vp->setNumber(result);
     return true;
 }
 
 static JSBool
 date_setTime(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj = ToObject(cx, &vp[1]);
@@ -2508,72 +2475,72 @@ date_valueOf(JSContext *cx, uintN argc, 
     return date_toString(cx, argc, vp);
 }
 
 // Don't really need an argument here, but we don't support arg-less builtins
 JS_DEFINE_TRCINFO_1(date_now,
     (1, (static, DOUBLE, date_now_tn, CONTEXT, 0, nanojit::ACCSET_STORE_ANY)))
 
 static JSFunctionSpec date_static_methods[] = {
-    JS_FN_TYPE("UTC",                 date_UTC,                MAXARGS,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("parse",               date_parse,              1,0, JS_TypeHandlerFloat),
-    JS_TN("now", date_now, 0,0, &date_now_trcinfo, JS_TypeHandlerFloat),
+    JS_FN("UTC",                 date_UTC,                MAXARGS,0),
+    JS_FN("parse",               date_parse,              1,0),
+    JS_TN("now",                 date_now,                0,0, &date_now_trcinfo),
     JS_FS_END
 };
 
 static JSFunctionSpec date_methods[] = {
-    JS_FN_TYPE("getTime",             date_getTime,            0,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("getTimezoneOffset",   date_getTimezoneOffset,  0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getYear",             date_getYear,            0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getFullYear",         date_getFullYear,        0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getUTCFullYear",      date_getUTCFullYear,     0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getMonth",            date_getMonth,           0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getUTCMonth",         date_getUTCMonth,        0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getDate",             date_getDate,            0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getUTCDate",          date_getUTCDate,         0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getDay",              date_getDay,             0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getUTCDay",           date_getUTCDay,          0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getHours",            date_getHours,           0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getUTCHours",         date_getUTCHours,        0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getMinutes",          date_getMinutes,         0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getUTCMinutes",       date_getUTCMinutes,      0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getSeconds",          date_getUTCSeconds,      0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getUTCSeconds",       date_getUTCSeconds,      0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getMilliseconds",     date_getUTCMilliseconds, 0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("getUTCMilliseconds",  date_getUTCMilliseconds, 0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("setTime",             date_setTime,            1,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setYear",             date_setYear,            1,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setFullYear",         date_setFullYear,        3,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setUTCFullYear",      date_setUTCFullYear,     3,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setMonth",            date_setMonth,           2,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setUTCMonth",         date_setUTCMonth,        2,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setDate",             date_setDate,            1,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setUTCDate",          date_setUTCDate,         1,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setHours",            date_setHours,           4,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setUTCHours",         date_setUTCHours,        4,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setMinutes",          date_setMinutes,         3,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setUTCMinutes",       date_setUTCMinutes,      3,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setSeconds",          date_setSeconds,         2,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setUTCSeconds",       date_setUTCSeconds,      2,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setMilliseconds",     date_setMilliseconds,    1,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("setUTCMilliseconds",  date_setUTCMilliseconds, 1,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("toUTCString",         date_toGMTString,        0,0, JS_TypeHandlerString),
-    JS_FN_TYPE(js_toLocaleString_str, date_toLocaleString,     0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("toLocaleDateString",  date_toLocaleDateString, 0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("toLocaleTimeString",  date_toLocaleTimeString, 0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("toLocaleFormat",      date_toLocaleFormat,     0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("toDateString",        date_toDateString,       0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("toTimeString",        date_toTimeString,       0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("toISOString",         date_toISOString,        0,0, JS_TypeHandlerString),
-    JS_FN_TYPE(js_toJSON_str,         date_toJSON,             1,0, JS_TypeHandlerString),
+    JS_FN("getTime",             date_getTime,            0,0),
+    JS_FN("getTimezoneOffset",   date_getTimezoneOffset,  0,0),
+    JS_FN("getYear",             date_getYear,            0,0),
+    JS_FN("getFullYear",         date_getFullYear,        0,0),
+    JS_FN("getUTCFullYear",      date_getUTCFullYear,     0,0),
+    JS_FN("getMonth",            date_getMonth,           0,0),
+    JS_FN("getUTCMonth",         date_getUTCMonth,        0,0),
+    JS_FN("getDate",             date_getDate,            0,0),
+    JS_FN("getUTCDate",          date_getUTCDate,         0,0),
+    JS_FN("getDay",              date_getDay,             0,0),
+    JS_FN("getUTCDay",           date_getUTCDay,          0,0),
+    JS_FN("getHours",            date_getHours,           0,0),
+    JS_FN("getUTCHours",         date_getUTCHours,        0,0),
+    JS_FN("getMinutes",          date_getMinutes,         0,0),
+    JS_FN("getUTCMinutes",       date_getUTCMinutes,      0,0),
+    JS_FN("getSeconds",          date_getUTCSeconds,      0,0),
+    JS_FN("getUTCSeconds",       date_getUTCSeconds,      0,0),
+    JS_FN("getMilliseconds",     date_getUTCMilliseconds, 0,0),
+    JS_FN("getUTCMilliseconds",  date_getUTCMilliseconds, 0,0),
+    JS_FN("setTime",             date_setTime,            1,0),
+    JS_FN("setYear",             date_setYear,            1,0),
+    JS_FN("setFullYear",         date_setFullYear,        3,0),
+    JS_FN("setUTCFullYear",      date_setUTCFullYear,     3,0),
+    JS_FN("setMonth",            date_setMonth,           2,0),
+    JS_FN("setUTCMonth",         date_setUTCMonth,        2,0),
+    JS_FN("setDate",             date_setDate,            1,0),
+    JS_FN("setUTCDate",          date_setUTCDate,         1,0),
+    JS_FN("setHours",            date_setHours,           4,0),
+    JS_FN("setUTCHours",         date_setUTCHours,        4,0),
+    JS_FN("setMinutes",          date_setMinutes,         3,0),
+    JS_FN("setUTCMinutes",       date_setUTCMinutes,      3,0),
+    JS_FN("setSeconds",          date_setSeconds,         2,0),
+    JS_FN("setUTCSeconds",       date_setUTCSeconds,      2,0),
+    JS_FN("setMilliseconds",     date_setMilliseconds,    1,0),
+    JS_FN("setUTCMilliseconds",  date_setUTCMilliseconds, 1,0),
+    JS_FN("toUTCString",         date_toGMTString,        0,0),
+    JS_FN(js_toLocaleString_str, date_toLocaleString,     0,0),
+    JS_FN("toLocaleDateString",  date_toLocaleDateString, 0,0),
+    JS_FN("toLocaleTimeString",  date_toLocaleTimeString, 0,0),
+    JS_FN("toLocaleFormat",      date_toLocaleFormat,     0,0),
+    JS_FN("toDateString",        date_toDateString,       0,0),
+    JS_FN("toTimeString",        date_toTimeString,       0,0),
+    JS_FN("toISOString",         date_toISOString,        0,0),
+    JS_FN(js_toJSON_str,         date_toJSON,             1,0),
 #if JS_HAS_TOSOURCE
-    JS_FN_TYPE(js_toSource_str,       date_toSource,           0,0, JS_TypeHandlerString),
+    JS_FN(js_toSource_str,       date_toSource,           0,0),
 #endif
-    JS_FN_TYPE(js_toString_str,       date_toString,           0,0, JS_TypeHandlerString),
-    JS_FN_TYPE(js_valueOf_str,        date_valueOf,            0,0, JS_TypeHandlerDynamic),
+    JS_FN(js_toString_str,       date_toString,           0,0),
+    JS_FN(js_valueOf_str,        date_valueOf,            0,0),
     JS_FS_END
 };
 
 JSBool
 js_Date(JSContext *cx, uintN argc, Value *vp)
 {
     /* Date called as function. */
     if (!IsConstructing(vp))
@@ -2621,30 +2588,22 @@ js_Date(JSContext *cx, uintN argc, Value
     JSObject *obj = js_NewDateObjectMsec(cx, d);
     if (!obj)
         return false;
     vp->setObject(*obj);
 
     return true;
 }
 
-static void type_NewDate(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    if (Valueify(jssite)->isNew)
-        JS_TypeHandlerNew(cx, jsfun, jssite);
-    else
-        JS_TypeHandlerString(cx, jsfun, jssite);
-}
-
 JSObject *
 js_InitDateClass(JSContext *cx, JSObject *obj)
 {
     /* set static LocalTZA */
     LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
-    JSObject *proto = js_InitClass(cx, obj, NULL, &js_DateClass, js_Date, MAXARGS, type_NewDate,
+    JSObject *proto = js_InitClass(cx, obj, NULL, &js_DateClass, js_Date, MAXARGS,
                                    NULL, date_methods, NULL, date_static_methods);
     if (!proto)
         return NULL;
 
     AutoObjectRooter tvr(cx, proto);
 
     SetDateToNaN(cx, proto);
 
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -962,18 +962,17 @@ WrapWatchedSetter(JSContext *cx, jsid id
         if (!js_ValueToStringId(cx, IdToValue(id), &id))
             return NULL;
         atom = JSID_TO_ATOM(id);
     } else {
         atom = NULL;
     }
 
     wrapper = js_NewFunction(cx, NULL, js_watch_set_wrapper, 1, 0,
-                             setter ? CastAsObject(setter)->getParent() : NULL, atom,
-                             JS_TypeHandlerDynamic, "SetWrapper");
+                             setter ? CastAsObject(setter)->getParent() : NULL, atom);
     if (!wrapper)
         return NULL;
     return CastAsStrictPropertyOp(FUN_OBJECT(wrapper));
 }
 
 static const Shape *
 UpdateWatchpointShape(JSContext *cx, JSWatchPoint *wp, const Shape *newShape)
 {
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -6687,16 +6687,18 @@ js_EmitTree(JSContext *cx, JSCodeGenerat
         }
         cg->flags |= oldflags & TCF_IN_FOR_INIT;
         if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - off) < 0)
             return JS_FALSE;
 
         argc = pn->pn_count - 1;
         if (js_Emit3(cx, cg, PN_OP(pn), ARGC_HI(argc), ARGC_LO(argc)) < 0)
             return JS_FALSE;
+        if (!MaybeEmitTypeSet(cx, cg, PN_OP(pn)))
+            return JS_FALSE;
         if (PN_OP(pn) == JSOP_EVAL) {
             EMIT_UINT16_IMM_OP(JSOP_LINENO, pn->pn_pos.begin.lineno);
             if (EmitBlockChain(cx, cg) < 0)
                 return JS_FALSE;
         }
         if (pn->pn_xflags & PNX_SETCALL) {
             if (js_Emit1(cx, cg, JSOP_SETCALL) < 0)
                 return JS_FALSE;
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -977,19 +977,19 @@ exn_toSource(JSContext *cx, uintN argc, 
         vp->setString(result);
         return true;
     }
 }
 #endif
 
 static JSFunctionSpec exception_methods[] = {
 #if JS_HAS_TOSOURCE
-    JS_FN_TYPE(js_toSource_str,   exn_toSource,           0,0, JS_TypeHandlerString),
+    JS_FN(js_toSource_str,   exn_toSource,           0,0),
 #endif
-    JS_FN_TYPE(js_toString_str,   exn_toString,           0,0, JS_TypeHandlerString),
+    JS_FN(js_toString_str,   exn_toString,           0,0),
     JS_FS_END
 };
 
 /* JSProto_ ordering for exceptions shall match JSEXN_ constants. */
 JS_STATIC_ASSERT(JSEXN_ERR == 0);
 JS_STATIC_ASSERT(JSProto_Error + JSEXN_INTERNALERR  == JSProto_InternalError);
 JS_STATIC_ASSERT(JSProto_Error + JSEXN_EVALERR      == JSProto_EvalError);
 JS_STATIC_ASSERT(JSProto_Error + JSEXN_RANGEERR     == JSProto_RangeError);
@@ -1031,17 +1031,17 @@ js_InitExceptionClasses(JSContext *cx, J
     jsid lineNumberId = ATOM_TO_JSID(cx->runtime->atomState.lineNumberAtom);
     JSObject *error_proto = NULL;
     for (intN i = JSEXN_ERR; i != JSEXN_LIMIT; i++) {
         JSProtoKey protoKey = GetExceptionProtoKey(i);
         JSAtom *atom = cx->runtime->atomState.classAtoms[protoKey];
         JSObject *proto =
             DefineConstructorAndPrototype(cx, obj, protoKey, atom,
                                           (i == JSEXN_ERR) ? obj_proto : error_proto,
-                                          &js_ErrorClass, Exception, 1, JS_TypeHandlerNew,
+                                          &js_ErrorClass, Exception, 1,
                                           NULL, (i == JSEXN_ERR) ? exception_methods : NULL,
                                           NULL, NULL);
         if (!proto)
             return NULL;
         JS_ASSERT(proto->privateData == NULL);
 
         if (i == JSEXN_ERR)
             error_proto = proto;
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1939,17 +1939,17 @@ js_XDRFunctionObject(JSXDRState *xdr, JS
             if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes))
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_XDR_CLOSURE_WRAPPER, name);
             return false;
         }
         JS_ASSERT((fun->u.i.wrapper & ~1U) == 0);
         firstword = (fun->u.i.skipmin << 2) | (fun->u.i.wrapper << 1) | !!fun->atom;
         flagsword = (fun->nargs << 16) | fun->flags;
     } else {
-        fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL, NULL, NULL);
+        fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL);
         if (!fun)
             return false;
         FUN_OBJECT(fun)->clearParent();
         if (!FUN_OBJECT(fun)->clearType(cx))
             return false;
     }
 
     AutoObjectRooter tvr(cx, FUN_OBJECT(fun));
@@ -2453,28 +2453,20 @@ fun_bind(JSContext *cx, uintN argc, Valu
         uintN nargs = target->getFunctionPrivate()->nargs;
         if (nargs > argslen)
             length = nargs - argslen;
     }
 
     /* Step 4-6, 10-11. */
     JSAtom *name = target->isFunction() ? target->getFunctionPrivate()->atom : NULL;
 
-    char *printName = NULL;
-#ifdef DEBUG
-    static int boundCount = 0;
-    printName = (char *) alloca(20);
-    JS_snprintf(printName, 20, "BoundFunction:%d", ++boundCount);
-#endif
-
     /* NB: Bound functions abuse |parent| to store their target. */
     JSObject *funobj =
         js_NewFunction(cx, NULL, CallOrConstructBoundFunction, length,
-                       JSFUN_CONSTRUCTOR, target, name,
-                       JS_TypeHandlerDynamic, printName);
+                       JSFUN_CONSTRUCTOR, target, name);
     if (!funobj)
         return false;
 
     /* Steps 7-9. */
     Value thisArg = argc >= 1 ? vp[2] : UndefinedValue();
     if (!funobj->initBoundFunction(cx, thisArg, args, argslen))
         return false;
 
@@ -2483,24 +2475,24 @@ fun_bind(JSContext *cx, uintN argc, Valu
 
     /* Step 22. */
     vp->setObject(*funobj);
     return true;
 }
 
 static JSFunctionSpec function_methods[] = {
 #if JS_HAS_TOSOURCE
-    JS_FN_TYPE(js_toSource_str,   fun_toSource,   0,0, JS_TypeHandlerString),
+    JS_FN(js_toSource_str,   fun_toSource,   0,0),
 #endif
-    JS_FN_TYPE(js_toString_str,   fun_toString,   0,0, JS_TypeHandlerString),
-    JS_FN_TYPE(js_apply_str,      js_fun_apply,   2,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE(js_call_str,       js_fun_call,    1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("bind",            fun_bind,       1,0, JS_TypeHandlerDynamic),
+    JS_FN(js_toString_str,   fun_toString,   0,0),
+    JS_FN(js_apply_str,      js_fun_apply,   2,0),
+    JS_FN(js_call_str,       js_fun_call,    1,0),
+    JS_FN("bind",            fun_bind,       1,0),
 #if JS_HAS_GENERATORS
-    JS_FN_TYPE("isGenerator",     fun_isGenerator,0,0, JS_TypeHandlerBool),
+    JS_FN("isGenerator",     fun_isGenerator,0,0),
 #endif
     JS_FS_END
 };
 
 /*
  * Report "malformed formal parameter" iff no illegal char or similar scanner
  * error was already reported.
  */
@@ -2532,17 +2524,17 @@ Function(JSContext *cx, uintN argc, Valu
 
     /*
      * NB: (new Function) is not lexically closed by its caller, it's just an
      * anonymous function in the top-level scope that its constructor inhabits.
      * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,
      * and so would a call to f from another top-level's script or function.
      */
     JSFunction *fun = js_NewFunction(cx, obj.get(), NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED,
-                                     global, cx->runtime->atomState.anonymousAtom, NULL, NULL);
+                                     global, cx->runtime->atomState.anonymousAtom);
     if (!fun)
         return false;
 
     Bindings bindings(cx);
     AutoBindingsRooter root(cx, bindings);
 
     uintN lineno;
     const char *filename = CurrentScriptFileAndLine(cx, &lineno);
@@ -2736,84 +2728,91 @@ ThrowTypeError(JSContext *cx, uintN argc
                                  JSMSG_THROW_TYPE_ERROR);
     return false;
 }
 
 JSObject *
 js_InitFunctionClass(JSContext *cx, JSObject *obj)
 {
     JSObject *proto = js_InitClass(cx, obj, NULL, &js_FunctionClass, Function, 1,
-                                   JS_TypeHandlerDynamic, NULL, function_methods, NULL, NULL);
+                                   NULL, function_methods, NULL, NULL);
     if (!proto)
         return NULL;
 
     /*
      * 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;
     MarkTypeObjectUnknownProperties(cx, newType);
 
-    JSFunction *fun = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, obj, NULL, NULL, NULL);
+    JSFunction *fun = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, obj, 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)
         return NULL;
     script->noScriptRval = true;
     script->code[0] = JSOP_STOP;
     script->code[1] = SRC_NULL;
 #ifdef CHECK_SCRIPT_OWNER
     script->owner = NULL;
 #endif
     fun->u.i.script = script;
-    fun->getType()->asFunction()->script = script;
+    fun->getType()->functionScript = script;
     script->fun = fun;
     js_CallNewScriptHook(cx, script, fun);
 
     if (obj->isGlobal()) {
         /* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
         JSFunction *throwTypeError =
             js_NewFunction(cx, NULL, reinterpret_cast<Native>(ThrowTypeError), 0,
-                           0, obj, NULL, JS_TypeHandlerVoid, "ThrowTypeError");
+                           0, obj, NULL);
         if (!throwTypeError)
             return NULL;
 
         obj->asGlobal()->setThrowTypeError(throwTypeError);
     }
 
     return proto;
 }
 
 JSFunction *
 js_NewFunction(JSContext *cx, JSObject *funobj, Native native, uintN nargs,
-               uintN flags, JSObject *parent, JSAtom *atom,
-               JSTypeHandler handler, const char *fullName)
+               uintN flags, JSObject *parent, JSAtom *atom)
 {
     JSFunction *fun;
 
     if (funobj) {
         JS_ASSERT(funobj->isFunction());
         funobj->setParent(parent);
     } else {
         funobj = NewFunction(cx, parent);
         if (!funobj)
             return NULL;
-        if (handler) {
-            TypeObject *type = cx->compartment->types.newTypeObject(cx, NULL, fullName, "",
+        if (native) {
+            const char *name = NULL;
+#ifdef DEBUG
+            JSAutoByteString bytes;
+            if (atom)
+                name = js_AtomToPrintableString(cx, atom, &bytes);
+            else
+                name = "Unnamed";
+#endif
+            TypeObject *type = cx->compartment->types.newTypeObject(cx, NULL, name, "",
                                                                     true, false,
                                                                     funobj->getProto());
             if (!type || !funobj->setTypeAndUniqueShape(cx, type))
                 return NULL;
-            type->asFunction()->handler = handler;
-            type->asFunction()->singleton = funobj;
+            type->isFunctionNative = true;
+            type->singleton = funobj;
         }
     }
     JS_ASSERT(!funobj->getPrivate());
     fun = (JSFunction *) funobj;
 
     /* Initialize all function members. */
     fun->nargs = uint16(nargs);
     fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK | JSFUN_TRCINFO);
@@ -2910,17 +2909,17 @@ js_CloneFunctionObject(JSContext *cx, JS
             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())
                 MarkTypeObjectUnknownProperties(cx, type);
             else
-                type->asFunction()->handler = fun->getType()->asFunction()->handler;
+                type->isFunctionNative = true;
         }
     }
     return clone;
 }
 
 #ifdef JS_TRACER
 JS_DEFINE_CALLINFO_4(extern, OBJECT, js_CloneFunctionObject, CONTEXT, FUNCTION, OBJECT, OBJECT, 0,
                      nanojit::ACCSET_STORE_ANY)
@@ -2997,30 +2996,22 @@ js_NewDebuggableFlatClosure(JSContext *c
     JS_ASSERT(!cx->fp()->fun()->optimizedClosure());
     JS_ASSERT(FUN_FLAT_CLOSURE(fun));
 
     return WrapEscapingClosure(cx, cx->fp(), fun);
 }
 
 JSFunction *
 js_DefineFunction(JSContext *cx, JSObject *obj, jsid id, Native native,
-                  uintN nargs, uintN attrs,
-                  JSTypeHandler handler, const char *fullName)
+                  uintN nargs, uintN attrs)
 {
     PropertyOp gop;
     StrictPropertyOp sop;
     JSFunction *fun;
 
-    if (!handler) {
-        handler = JS_TypeHandlerDynamic;
-        if (!fullName)
-            fullName = "Unknown";
-    }
-    JS_ASSERT(fullName);
-
     if (attrs & JSFUN_STUB_GSOPS) {
         /*
          * JSFUN_STUB_GSOPS is a request flag only, not stored in fun->flags or
          * the defined property's attributes. This allows us to encode another,
          * internal flag using the same bit, JSFUN_EXPR_CLOSURE -- see jsfun.h
          * for more on this.
          */
         attrs &= ~JSFUN_STUB_GSOPS;
@@ -3071,18 +3062,17 @@ js_DefineFunction(JSContext *cx, JSObjec
      *
      * FIXME: bug 611190.
      */
     bool wasDelegate = obj->isDelegate();
 
     fun = js_NewFunction(cx, NULL, native, nargs,
                          attrs & (JSFUN_FLAGS_MASK | JSFUN_TRCINFO),
                          obj,
-                         JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : NULL,
-                         handler, fullName);
+                         JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : NULL);
     if (!fun)
         return NULL;
 
     if (!wasDelegate && obj->isDelegate())
         obj->clearDelegate();
 
     if (!obj->defineProperty(cx, id, ObjectValue(*fun), gop, sop, attrs & ~JSFUN_FLAGS_MASK))
         return NULL;
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -234,22 +234,22 @@ struct JSFunction : public JSObject_Slot
 
 /*
  * Trace-annotated native. This expands to a JSFunctionSpec initializer (like
  * JS_FN in jsapi.h). fastcall is a FastNative; trcinfo is a
  * JSNativeTraceInfo*.
  */
 #ifdef JS_TRACER
 /* MSVC demands the intermediate (void *) cast here. */
-# define JS_TN(name,fastcall,nargs,flags,trcinfo,handler)                     \
-    JS_FN_TYPE(name, JS_DATA_TO_FUNC_PTR(Native, trcinfo), nargs,             \
-               (flags) | JSFUN_STUB_GSOPS | JSFUN_TRCINFO, handler)
+# define JS_TN(name,fastcall,nargs,flags,trcinfo)                             \
+    JS_FN(name, JS_DATA_TO_FUNC_PTR(Native, trcinfo), nargs,                  \
+          (flags) | JSFUN_STUB_GSOPS | JSFUN_TRCINFO)
 #else
-# define JS_TN(name,fastcall,nargs,flags,trcinfo,handler)                     \
-    JS_FN_TYPE(name, fastcall, nargs, flags, handler)
+# define JS_TN(name,fastcall,nargs,flags,trcinfo)                             \
+    JS_FN(name, fastcall, nargs, flags)
 #endif
 
 extern JS_PUBLIC_DATA(js::Class) js_CallClass;
 extern JS_PUBLIC_DATA(js::Class) js_FunctionClass;
 extern JS_FRIEND_DATA(js::Class) js_DeclEnvClass;
 
 inline bool
 JSObject::isCall() const
@@ -391,18 +391,17 @@ LookupInterpretedFunctionPrototype(JSCon
 
 } /* namespace js */
 
 extern JSString *
 fun_toStringHelper(JSContext *cx, JSObject *obj, uintN indent);
 
 extern JSFunction *
 js_NewFunction(JSContext *cx, JSObject *funobj, js::Native native, uintN nargs,
-               uintN flags, JSObject *parent, JSAtom *atom,
-               JSTypeHandler handler, const char *fullName);
+               uintN flags, JSObject *parent, JSAtom *atom);
 
 extern JSObject *
 js_InitFunctionClass(JSContext *cx, JSObject *obj);
 
 extern JSObject *
 js_InitArgumentsClass(JSContext *cx, JSObject *obj);
 
 extern void
@@ -444,17 +443,17 @@ js_AllocFlatClosure(JSContext *cx, JSFun
 extern JSObject *
 js_NewFlatClosure(JSContext *cx, JSFunction *fun, JSOp op, size_t oplen);
 
 extern JS_REQUIRES_STACK JSObject *
 js_NewDebuggableFlatClosure(JSContext *cx, JSFunction *fun);
 
 extern JSFunction *
 js_DefineFunction(JSContext *cx, JSObject *obj, jsid id, js::Native native,
-                  uintN nargs, uintN flags, JSTypeHandler handler, const char *fullName);
+                  uintN nargs, uintN flags);
 
 /*
  * Flags for js_ValueToFunction and js_ReportIsNotFunction.  We depend on the
  * fact that JSINVOKE_CONSTRUCT (aka JSFRAME_CONSTRUCTING) is 1, and test that
  * with #if/#error in jsfun.c.
  */
 #define JSV2F_CONSTRUCT         ((uintN)js::INVOKE_CONSTRUCTOR)
 #define JSV2F_SEARCH_STACK      0x10000
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -290,16 +290,33 @@ types::TypeFailure(JSContext *cx, const 
     
     *((int*)NULL) = 0;  /* Should never be reached */
 }
 
 /////////////////////////////////////////////////////////////////////
 // TypeSet
 /////////////////////////////////////////////////////////////////////
 
+TypeSet *
+TypeSet::make(JSContext *cx, const char *name)
+{
+    JS_ASSERT(cx->compartment->activeInference);
+
+    TypeSet *res = ArenaNew<TypeSet>(cx->compartment->pool);
+    if (!res) {
+        cx->compartment->types.setPendingNukeTypes(cx);
+        return NULL;
+    }
+
+    InferSpew(ISpewOps, "typeSet: T%p intermediate %s", res, name);
+    res->setIntermediate();
+
+    return res;
+}
+
 void
 TypeSet::addTypeSet(JSContext *cx, ClonedTypeSet *types)
 {
     if (types->typeFlags & TYPE_FLAG_UNKNOWN) {
         addType(cx, TYPE_UNKNOWN);
         return;
     }
 
@@ -591,29 +608,29 @@ TypeSet::addCallProperty(JSContext *cx, 
         return;
 
     add(cx, ArenaNew<TypeConstraintCallProp>(cx->compartment->pool, script, callpc, id));
 }
 
 /* Constraints for determining the 'this' object at sites invoked using 'new'. */
 class TypeConstraintNewObject : public TypeConstraint
 {
-    TypeFunction *fun;
+    TypeObject *fun;
     TypeSet *target;
 
   public:
-    TypeConstraintNewObject(JSScript *script, TypeFunction *fun, TypeSet *target)
+    TypeConstraintNewObject(JSScript *script, TypeObject *fun, TypeSet *target)
         : TypeConstraint("newObject", script), fun(fun), target(target)
     {}
 
     void newType(JSContext *cx, TypeSet *source, jstype type);
 };
 
 void
-TypeSet::addNewObject(JSContext *cx, JSScript *script, TypeFunction *fun, TypeSet *target)
+TypeSet::addNewObject(JSContext *cx, JSScript *script, TypeObject *fun, TypeSet *target)
 {
     add(cx, ArenaNew<TypeConstraintNewObject>(cx->compartment->pool, script, fun, target));
 }
 
 /*
  * Constraints for watching call edges as they are discovered and invoking native
  * function handlers, adding constraints for arguments, receiver objects and the
  * return value, and updating script foundOffsets.
@@ -930,20 +947,31 @@ GetPropertyObject(JSContext *cx, JSScrip
         return NULL;
     }
 
     if (!object)
         cx->compartment->types.setPendingNukeTypes(cx);
     return object;
 }
 
+static inline bool
+UsePropertyTypeBarrier(jsbytecode *pc)
+{
+    /*
+     * At call opcodes, type barriers can only be added for the call bindings,
+     * which TypeConstraintCall will add barrier constraints for directly.
+     */
+    uint32 format = js_CodeSpec[*pc].format;
+    return (format & JOF_TYPESET) && !(format & JOF_INVOKE);
+}
+
 static inline void
 MarkPropertyAccessUnknown(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target)
 {
-    if (CanHaveReadBarrier(pc))
+    if (UsePropertyTypeBarrier(pc))
         script->analysis(cx)->addTypeBarrier(cx, pc, target, TYPE_UNKNOWN);
     else
         target->addType(cx, TYPE_UNKNOWN);
 }
 
 /*
  * Handle a property access on a specific object. All property accesses go through
  * here, whether via x.f, x[f], or global name accesses.
@@ -978,17 +1006,17 @@ PropertyAccess(JSContext *cx, JSScript *
 
     /* Capture the effects of a standard property access. */
     if (target) {
         TypeSet *types = object->getProperty(cx, id, assign);
         if (!types)
             return;
         if (assign)
             target->addSubset(cx, script, types);
-        else if (CanHaveReadBarrier(pc))
+        else if (UsePropertyTypeBarrier(pc))
             types->addSubsetBarrier(cx, script, pc, target);
         else
             types->addSubset(cx, script, target);
     } else {
         TypeSet *readTypes = object->getProperty(cx, id, false);
         TypeSet *writeTypes = object->getProperty(cx, id, true);
         if (!readTypes || !writeTypes)
             return;
@@ -1077,26 +1105,26 @@ TypeConstraintNewObject::newType(JSConte
         if (object->unknownProperties()) {
             target->addType(cx, TYPE_UNKNOWN);
         } else {
             TypeSet *newTypes = object->getProperty(cx, JSID_EMPTY, false);
             if (!newTypes)
                 return;
             newTypes->addSubset(cx, script, target);
         }
-    } else if (!fun->script) {
+    } else if (!fun->functionScript) {
         /*
          * This constraint should only be used for scripted functions and for
          * native constructors with immutable non-primitive prototypes.
          * Disregard primitives here.
          */
-    } else if (!fun->script->hasGlobal()) {
+    } else if (!fun->functionScript->hasGlobal()) {
         target->addType(cx, TYPE_UNKNOWN);
     } else {
-        TypeObject *object = fun->script->types.standardType(cx, JSProto_Object);
+        TypeObject *object = fun->functionScript->types.standardType(cx, JSProto_Object);
         if (!object) {
             cx->compartment->types.setPendingNukeTypes(cx);
             return;
         }
         target->addType(cx, (jstype) object);
     }
 }
 
@@ -1117,79 +1145,58 @@ TypeConstraintCall::newType(JSContext *c
 
     /* Get the function being invoked. */
     TypeObject *object = (TypeObject*) type;
     if (object->unknownProperties()) {
         /* Unknown return value for calls on generic objects. */
         cx->compartment->types.monitorBytecode(cx, script, pc - script->code);
         return;
     }
+
     if (!object->isFunction) {
-        /*
-         * If a call on a non-function actually occurs, the call's result
-         * should be marked as unknown.
-         */
+        /* Calls on non-functions should always be dynamically monitored. */
         return;
     }
-    TypeFunction *function = object->asFunction();
-
-    if (!function->script) {
-        JS_ASSERT(function->handler && function->singleton);
+
+    if (object->isFunctionNative) {
+        /*
+         * The return value and all side effects within native calls should
+         * be dynamically monitored, except when the compiler is generating
+         * specialized inline code or stub calls for a specific natives and
+         * knows about the behavior of that native.
+         */
+        cx->compartment->types.monitorBytecode(cx, script, pc - script->code, true);
+
+        if (!object->singleton)
+            return;
 
         /*
-         * When creating objects, natives may use the wrong type/prototype for
-         * the result if called by a frame parented to a different global
-         * :FIXME: bug 631135. Rather than try to model this, just mark the
-         * result of cross-global native calls as unknown.
+         * Add type constraints capturing the possible behavior of specialized
+         * natives which operate on properties. :XXX: use better factoring for
+         * both this and the compiler code itself which specializes particular
+         * natives.
          */
-        if (!script->hasGlobal() || script->global() != function->singleton->getGlobal()) {
-            callsite->returnTypes->addType(cx, TYPE_UNKNOWN);
-            return;
-        }
-
-        if (function->isGeneric) {
-            if (callsite->argumentCount == 0) {
-                /* Generic methods called with zero arguments generate runtime errors. */
-                return; 
+
+        Native native = object->singleton->getFunctionPrivate()->maybeNative();
+        JS_ASSERT(native);
+
+        if (native == js::array_push) {
+            for (size_t ind = 0; ind < callsite->argumentCount; ind++) {
+                callsite->thisTypes->addSetProperty(cx, script, pc,
+                                                    callsite->argumentTypes[ind], JSID_VOID);
             }
-
-            /*
-             * Make a new callsite transforming the arguments appropriately, as is
-             * done by the generic native dispatchers. watch out for cases where the
-             * first argument is null, which will transform to the global object.
-             */
-
-            TypeSet *thisTypes = TypeSet::make(cx, "genericthis");
-            if (!thisTypes)
-                return;
-            callsite->argumentTypes[0]->addTransformThis(cx, script, thisTypes);
-
-            TypeCallsite *newSite = ArenaNew<TypeCallsite>(cx->compartment->pool,
-                                                           cx, script, pc, callsite->isNew,
-                                                           callsite->argumentCount - 1);
-            if (!newSite || (callsite->argumentCount > 1 && !newSite->argumentTypes)) {
-                cx->compartment->types.setPendingNukeTypes(cx);
-                return;
-            }
-
-            newSite->thisTypes = thisTypes;
-            newSite->returnTypes = callsite->returnTypes;
-            for (unsigned i = 0; i < callsite->argumentCount - 1; i++)
-                newSite->argumentTypes[i] = callsite->argumentTypes[i + 1];
-
-            function->handler(cx, (JSTypeFunction*)function, (JSTypeCallsite*)newSite);
-        } else {
-            /* Model the function's effects directly. */
-            function->handler(cx, (JSTypeFunction*)function, (JSTypeCallsite*)callsite);
         }
 
+        if (native == js::array_pop)
+            callsite->thisTypes->addGetProperty(cx, script, pc, callsite->returnTypes, JSID_VOID);
+
         return;
     }
 
-    JSScript *callee = function->script;
+    JSScript *callee = object->functionScript;
     unsigned nargs = callee->fun->nargs;
 
     if (!callee->types.ensureTypeArray(cx))
         return;
 
     /* Analyze the function if we have not already done so. */
     if (!callee->ensureRanInference(cx)) {
         cx->compartment->types.setPendingNukeTypes(cx);
@@ -1247,24 +1254,20 @@ TypeConstraintPropagateThis::newType(JSC
     }
 
     /* Ignore calls to primitives, these will go through a stub. */
     if (!TypeIsObject(type))
         return;
 
     /* Ignore calls to natives, these will be handled by TypeConstraintCall. */
     TypeObject *object = (TypeObject*) type;
-    if (object->unknownProperties() || !object->isFunction)
+    if (object->unknownProperties() || !object->isFunction || !object->functionScript)
         return;
-    TypeFunction *function = object->asFunction();
-
-    if (!function->script)
-        return;
-
-    JSScript *callee = function->script;
+
+    JSScript *callee = object->functionScript;
 
     if (!callee->types.ensureTypeArray(cx))
         return;
 
     callee->types.thisTypes()->addType(cx, this->type);
 }
 
 void
@@ -1701,28 +1704,27 @@ ObjectStateChange(JSContext *cx, TypeObj
     if (object->unknownProperties())
         return;
 
     /* All constraints listening to state changes are on the element types. */
     TypeSet *elementTypes = object->getProperty(cx, JSID_VOID, false);
     if (!elementTypes)
         return;
     if (markingUnknown) {
-        JSScript *fixArgsScript = NULL;
+        bool fixArgs = false;
         if (!(object->flags & OBJECT_FLAG_CREATED_ARGUMENTS) && object->isFunction) {
-            TypeFunction *fun = object->asFunction();
-            if (fun->script && fun->script->usedLazyArgs)
-                fixArgsScript = fun->script;
+            if (object->functionScript && object->functionScript->usedLazyArgs)
+                fixArgs = true;
         }
 
         /* Mark as unknown after getting the element types, to avoid assertion. */
         object->flags = OBJECT_FLAG_UNKNOWN_MASK;
 
-        if (fixArgsScript)
-            FixLazyArguments(cx, fixArgsScript);
+        if (fixArgs)
+            FixLazyArguments(cx, object->functionScript);
     }
 
     TypeConstraint *constraint = elementTypes->constraintList;
     while (constraint) {
         constraint->newObjectState(cx, object, force);
         constraint = constraint->next;
     }
 }
@@ -1860,19 +1862,17 @@ TypeCompartment::newTypeObject(JSContext
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     if (!atom)
         return NULL;
     jsid id = ATOM_TO_JSID(atom);
 #else
     jsid id = JSID_VOID;
 #endif
 
-    TypeObject *object = isFunction
-        ? cx->new_<TypeFunction>(id, proto)
-        : cx->new_<TypeObject>(id, proto);
+    TypeObject *object = cx->new_<TypeObject>(id, proto, isFunction);
     if (!object)
         return NULL;
 
     TypeObject *&objects = script ? script->types.typeObjects : this->objects;
     object->next = objects;
     objects = object;
 
     if (!cx->typeInferenceEnabled())
@@ -2136,73 +2136,50 @@ TypeCompartment::addPendingRecompile(JSC
     }
 
     if (!pendingRecompiles->append(script)) {
         cx->compartment->types.setPendingNukeTypes(cx);
         return;
     }
 }
 
-static inline bool
-MonitorResultUnknown(JSOp op)
-{
-    /*
-     * Opcodes which can be monitored and whose result should be marked as
-     * unknown when doing so. :XXX: should use type barriers at calls.
-     */
-    switch (op) {
-      case JSOP_INCNAME:
-      case JSOP_DECNAME:
-      case JSOP_NAMEINC:
-      case JSOP_NAMEDEC:
-      case JSOP_INCGNAME:
-      case JSOP_DECGNAME:
-      case JSOP_GNAMEINC:
-      case JSOP_GNAMEDEC:
-      case JSOP_INCELEM:
-      case JSOP_DECELEM:
-      case JSOP_ELEMINC:
-      case JSOP_ELEMDEC:
-      case JSOP_INCPROP:
-      case JSOP_DECPROP:
-      case JSOP_PROPINC:
-      case JSOP_PROPDEC:
-      case JSOP_CALL:
-      case JSOP_EVAL:
-      case JSOP_FUNCALL:
-      case JSOP_FUNAPPLY:
-      case JSOP_NEW:
-        return true;
-      default:
-        return false;
-    }
-}
-
 void
-TypeCompartment::monitorBytecode(JSContext *cx, JSScript *script, uint32 offset)
+TypeCompartment::monitorBytecode(JSContext *cx, JSScript *script, uint32 offset,
+                                 bool returnOnly)
 {
     ScriptAnalysis *analysis = script->analysis(cx);
-
-    if (analysis->getCode(offset).monitoredTypes)
-        return;
+    JS_ASSERT(analysis->ranInference());
 
     jsbytecode *pc = script->code + offset;
     UntrapOpcode untrap(cx, script, pc);
 
+    JS_ASSERT_IF(returnOnly, js_CodeSpec[*pc].format & JOF_INVOKE);
+
+    Bytecode &code = analysis->getCode(pc);
+
+    if (returnOnly ? code.monitoredTypesReturn : code.monitoredTypes)
+        return;
+
+    InferSpew(ISpewOps, "addMonitorNeeded:%s #%u:%05u", script->id(), offset,
+              returnOnly ? " returnOnly" : "");
+
     /*
-     * We may end up monitoring opcodes before even analyzing them, as we can
-     * peek forward in CALLPROP and CALLELEM ops. Don't add the unknown result
-     * yet in this case, we will do so when analyzing the opcode.
+     * When monitoring side effects for incops, mark the result of the opcode
+     * as unknown. These bytecodes are not JOF_TYPESET so there is no place to
+     * add type barriers at.
      */
-    if (MonitorResultUnknown(JSOp(*pc)) && analysis->hasPushedTypes(pc))
+    if (js_CodeSpec[*pc].format & (JOF_INC | JOF_DEC))
         analysis->addPushedType(cx, offset, 0, TYPE_UNKNOWN);
 
-    InferSpew(ISpewOps, "addMonitorNeeded: #%u:%05u", script->id(), offset);
-
-    script->analysis(cx)->getCode(offset).monitoredTypes = true;
+    /* Dynamically monitor this call to keep track of its result types. */
+    if (js_CodeSpec[*pc].format & JOF_INVOKE)
+        code.monitoredTypesReturn = true;
+
+    if (!returnOnly)
+        code.monitoredTypes = true;
 
     if (script->hasJITCode())
         cx->compartment->types.addPendingRecompile(cx, script);
 
     /* Trigger recompilation of any inline callers. */
     if (script->fun)
         ObjectStateChange(cx, script->fun->getType(), false, true);
 }
@@ -2813,42 +2790,34 @@ TypeObject::markSlotReallocation(JSConte
         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;
+    bool fixArgs = false;
+    if ((flags & ~this->flags & OBJECT_FLAG_CREATED_ARGUMENTS) &&
+        functionScript && functionScript->usedLazyArgs) {
+        fixArgs = true;
     }
 
     this->flags |= flags;
 
-    if (fixArgsScript)
-        FixLazyArguments(cx, fixArgsScript);
+    if (fixArgs)
+        FixLazyArguments(cx, functionScript);
 
     InferSpew(ISpewOps, "%s: setFlags %u", name(), flags);
 
     ObjectStateChange(cx, this, false, false);
 }
 
 void
 TypeObject::markUnknown(JSContext *cx)
@@ -3160,20 +3129,16 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         }
     }
 
     for (unsigned i = 0; i < defCount; i++) {
         pushed[i].setIntermediate();
         InferSpew(ISpewOps, "typeSet: T%p pushed%u #%u:%05u", &pushed[i], i, script->id(), offset);
     }
 
-    /* Add unknown result for opcodes which were monitored before being analyzed. */
-    if (code.monitoredTypes && MonitorResultUnknown(op))
-        pushed[0].addType(cx, TYPE_UNKNOWN);
-
     /* Add type constraints for the various opcodes. */
     switch (op) {
 
         /* Nop bytecodes. */
       case JSOP_POP:
       case JSOP_NOP:
       case JSOP_TRACE:
       case JSOP_NOTRACE:
@@ -3657,26 +3622,29 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
       case JSOP_DEFVAR:
         break;
 
       case JSOP_CALL:
       case JSOP_EVAL:
       case JSOP_FUNCALL:
       case JSOP_FUNAPPLY:
       case JSOP_NEW: {
+        TypeSet *seen = script->types.bytecodeTypes(pc);
+        seen->addSubset(cx, script, &pushed[0]);
+
         /* Construct the base call information about this site. */
         unsigned argCount = GetUseCount(script, offset) - 2;
         TypeCallsite *callsite = ArenaNew<TypeCallsite>(cx->compartment->pool,
                                                         cx, script, pc, op == JSOP_NEW, argCount);
         if (!callsite || (argCount && !callsite->argumentTypes)) {
             cx->compartment->types.setPendingNukeTypes(cx);
             break;
         }
         callsite->thisTypes = poppedTypes(pc, argCount);
-        callsite->returnTypes = &pushed[0];
+        callsite->returnTypes = seen;
 
         for (unsigned i = 0; i < argCount; i++)
             callsite->argumentTypes[i] = poppedTypes(pc, argCount - 1 - i);
 
         /*
          * Mark FUNCALL and FUNAPPLY sites as monitored. The method JIT may
          * lower these into normal calls, and we need to make sure the
          * callee's argument types are checked on entry.
@@ -4174,17 +4142,17 @@ ScriptAnalysis::analyzeTypesNew(JSContex
 
     if (script->fun->getType()->unknownProperties() ||
         script->fun->isFunctionPrototype() ||
         !script->hasGlobal()) {
         script->types.thisTypes()->addType(cx, TYPE_UNKNOWN);
         return;
     }
 
-    TypeFunction *funType = script->fun->getType()->asFunction();
+    TypeObject *funType = script->fun->getType();
     TypeSet *prototypeTypes = funType->getProperty(cx, id_prototype(cx), false);
     if (!prototypeTypes)
         return;
     prototypeTypes->addNewObject(cx, script, funType, script->types.thisTypes());
 }
 
 /*
  * Persistent constraint clearing out newScript and definite properties from
@@ -4454,17 +4422,17 @@ AnalyzeNewScriptProperties(JSContext *cx
             /* Need to definitely be calling Function.call on a specific script. */
             TypeObject *funcallObj = funcallTypes->getSingleObject();
             if (!funcallObj || !funcallObj->singleton ||
                 !funcallObj->singleton->isFunction() ||
                 funcallObj->singleton->getFunctionPrivate()->maybeNative() != js_fun_call) {
                 return false;
             }
             TypeObject *scriptObj = scriptTypes->getSingleObject();
-            if (!scriptObj || !scriptObj->isFunction || !scriptObj->asFunction()->script)
+            if (!scriptObj || !scriptObj->functionScript)
                 return false;
 
             /*
              * Generate constraints to clear definite properties from the type
              * should the Function.call or callee itself change in the future.
              */
             TypeIntermediateClearDefinite *funcallTrap =
                 cx->new_<TypeIntermediateClearDefinite>(calleev.pushedOffset(), 0, type);
@@ -4482,17 +4450,17 @@ AnalyzeNewScriptProperties(JSContext *cx
 
             TypeNewScript::Initializer pushframe(TypeNewScript::Initializer::FRAME_PUSH, uses->offset);
             if (!initializerList->append(pushframe)) {
                 cx->compartment->types.setPendingNukeTypes(cx);
                 *pbaseobj = NULL;
                 return false;
             }
 
-            if (!AnalyzeNewScriptProperties(cx, type, scriptObj->asFunction()->script,
+            if (!AnalyzeNewScriptProperties(cx, type, scriptObj->functionScript,
                                             pbaseobj, initializerList)) {
                 return false;
             }
 
             TypeNewScript::Initializer popframe(TypeNewScript::Initializer::FRAME_POP, 0);
             if (!initializerList->append(popframe)) {
                 cx->compartment->types.setPendingNukeTypes(cx);
                 *pbaseobj = NULL;
@@ -4704,62 +4672,36 @@ ScriptAnalysis::printTypes(JSContext *cx
 /////////////////////////////////////////////////////////////////////
 // Interface functions
 /////////////////////////////////////////////////////////////////////
 
 namespace js {
 namespace types {
 
 void
-MarkTypeCallerUnexpectedSlow(JSContext *cx, jstype type)
+MarkIteratorUnknownSlow(JSContext *cx)
 {
-    /*
-     * 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.
-     */
+    /* Check whether we are actually at an ITER opcode. */
 
     jsbytecode *pc;
     JSScript *script = cx->stack.currentScript(&pc);
     if (!script || !pc)
         return;
 
     /*
      * Watch out if the caller is in a different compartment from this one.
      * This must have gone through a cross-compartment wrapper.
      */
     if (script->compartment != cx->compartment)
         return;
 
     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));
+    if (JSOp(*pc) == JSOP_ITER)
+        TypeDynamicResult(cx, script, pc, TYPE_UNKNOWN);
 }
 
 void
 TypeMonitorCallSlow(JSContext *cx, JSObject *callee,
                     const CallArgs &args, bool constructing)
 {
     unsigned nargs = callee->getFunctionPrivate()->nargs;
     JSScript *script = callee->getFunctionPrivate()->script();
@@ -4831,17 +4773,17 @@ 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)) {
+    if (js_CodeSpec[*pc].format & JOF_TYPESET) {
         TypeSet *types = script->types.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;
     }
@@ -5112,17 +5054,17 @@ JSScript::typeSetFunction(JSContext *cx,
 
     TypeObject *type = cx->compartment->types.newTypeObject(cx, this, name, "",
                                                             true, false, fun->getProto());
     if (!type)
         return false;
 
     if (!fun->setTypeAndUniqueShape(cx, type))
         return false;
-    type->asFunction()->script = this;
+    type->functionScript = this;
     this->fun = fun;
 
     return true;
 }
 
 #ifdef DEBUG
 
 void
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -53,17 +53,16 @@ namespace js {
 
 namespace js {
 namespace types {
 
 /* Forward declarations. */
 class TypeSet;
 struct TypeCallsite;
 struct TypeObject;
-struct TypeFunction;
 struct TypeCompartment;
 struct ClonedTypeSet;
 
 /*
  * Information about a single concrete type. This is a non-zero value whose
  * lower 3 bits indicate a particular primitive type below, and if those bits
  * are zero then a pointer to a type object.
  */
@@ -362,17 +361,17 @@ class TypeSet
     /* Add specific kinds of constraints to this set. */
     inline void add(JSContext *cx, TypeConstraint *constraint, bool callExisting = true);
     void addSubset(JSContext *cx, JSScript *script, TypeSet *target);
     void addGetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
                         TypeSet *target, jsid id);
     void addSetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
                         TypeSet *target, jsid id);
     void addCallProperty(JSContext *cx, JSScript *script, jsbytecode *pc, jsid id);
-    void addNewObject(JSContext *cx, JSScript *script, TypeFunction *fun, TypeSet *target);
+    void addNewObject(JSContext *cx, JSScript *script, TypeObject *fun, TypeSet *target);
     void addCall(JSContext *cx, TypeCallsite *site);
     void addArith(JSContext *cx, JSScript *script,
                   TypeSet *target, TypeSet *other = NULL);
     void addTransformThis(JSContext *cx, JSScript *script, TypeSet *target);
     void addPropagateThis(JSContext *cx, JSScript *script, jsbytecode *pc, jstype type);
     void addFilterPrimitives(JSContext *cx, JSScript *script,
                              TypeSet *target, bool onlyNullVoid);
     void addSubsetBarrier(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target);
@@ -380,17 +379,17 @@ class TypeSet
 
     void addBaseSubset(JSContext *cx, TypeObject *object, TypeSet *target);
     bool addCondensed(JSContext *cx, JSScript *script);
 
     /*
      * Make an intermediate type set with the specified debugging name,
      * not embedded in another structure.
      */
-    static inline TypeSet* make(JSContext *cx, const char *name);
+    static TypeSet *make(JSContext *cx, const char *name);
 
     /*
      * Methods for JIT compilation. If a script is currently being compiled
      * (see AutoEnterCompilation) these will add constraints ensuring that if
      * the return value change in the future due to new type information, the
      * currently compiled script will be marked for recompilation.
      */
 
@@ -618,19 +617,22 @@ struct TypeObject
     JSObject *proto;
 
     /* Lazily filled array of empty shapes for each size of objects with this type. */
     js::EmptyShape **emptyShapes;
 
     /* Vector of TypeObjectFlags for the objects this type represents. */
     TypeObjectFlags flags;
 
-    /* Whether this is a function object, and may be cast into TypeFunction. */
+    /* Whether this is a function. */
     bool isFunction;
 
+    /* Whether this is a function for a native. */
+    bool isFunctionNative;
+
     /* Mark bit for GC. */
     bool marked;
 
     /* If set, newScript information should not be installed on this object. */
     bool newScriptCleared;
 
     /*
      * If non-NULL, objects of this type have always been constructed using
@@ -696,27 +698,23 @@ struct TypeObject
     TypeObject *instanceNext;
 
     /* Link in the list of objects associated with a script or global object. */
     TypeObject *next;
 
     /* If at most one JSObject can have this as its type, that object. */
     JSObject *singleton;
 
+    /* If this is an interpreted function, the corresponding script. */
+    JSScript *functionScript;
+
     TypeObject() {}
 
     /* Make an object with the specified name. */
-    inline TypeObject(jsid id, JSObject *proto);
-
-    /* Coerce this object to a function. */
-    TypeFunction* asFunction()
-    {
-        JS_ASSERT(isFunction);
-        return (TypeFunction *) this;
-    }
+    inline TypeObject(jsid id, JSObject *proto, bool isFunction);
 
     bool unknownProperties() { return flags == OBJECT_FLAG_UNKNOWN_MASK; }
     bool hasAnyFlags(TypeObjectFlags flags) { return (this->flags & flags) != 0; }
     bool hasAllFlags(TypeObjectFlags flags) { return (this->flags & flags) == flags; }
 
     /*
      * Return an immutable, shareable, empty shape with the same clasp as this
      * and the same slotSpan as this had when empty.
@@ -774,39 +772,16 @@ UseNewType(JSContext *cx, JSScript *scri
 /*
  * Add any definite properties to type and compute its newScript according to
  * the specified script which the type is the 'new' value for.
  */
 void
 CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSScript *script);
 
 /*
- * Type information about an interpreted or native function. Note: it is possible for
- * a function JSObject to have a type which is not a TypeFunction. This happens when
- * we are not able to statically model the type of a function due to non-compileAndGo code.
- */
-struct TypeFunction : public TypeObject
-{
-    /* If this function is native, the handler to use at calls to it. */
-    JSTypeHandler handler;
-
-    /* If this function is interpreted, the corresponding script. */
-    JSScript *script;
-
-    /*
-     * Whether this is a generic native handler, and treats its first parameter
-     * the way it normally would its 'this' variable, e.g. Array.reverse(arr)
-     * instead of arr.reverse().
-     */
-    bool isGeneric;
-
-    inline TypeFunction(jsid id, JSObject *proto);
-};
-
-/*
  * Type information about a callsite. this is separated from the bytecode
  * information itself so we can handle higher order functions not called
  * directly via a bytecode.
  */
 struct TypeCallsite
 {
     JSScript *script;
     jsbytecode *pc;
@@ -1037,17 +1012,18 @@ struct TypeCompartment
 
     /* 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);
 
     /* Monitor future effects on a bytecode. */
-    void monitorBytecode(JSContext *cx, JSScript *script, uint32 offset);
+    void monitorBytecode(JSContext *cx, JSScript *script, uint32 offset,
+                         bool returnOnly = false);
 
     void sweep(JSContext *cx);
 };
 
 enum SpewChannel {
     ISpewOps,      /* ops: New constraints and types. */
     ISpewResult,   /* result: Final type sets. */
     SPEW_COUNT
@@ -1076,18 +1052,9 @@ inline const char * TypeString(jstype ty
 #endif
 
 /* Print a warning, dump state and abort the program. */
 void TypeFailure(JSContext *cx, const char *fmt, ...);
 
 } /* namespace types */
 } /* namespace js */
 
-static JS_ALWAYS_INLINE js::types::TypeObject *
-Valueify(JSTypeObject *jstype) { return (js::types::TypeObject*) jstype; }
-
-static JS_ALWAYS_INLINE js::types::TypeFunction *
-Valueify(JSTypeFunction *jstype) { return (js::types::TypeFunction*) jstype; }
-
-static JS_ALWAYS_INLINE js::types::TypeCallsite *
-Valueify(JSTypeCallsite *jssite) { return (js::types::TypeCallsite*) jssite; }
-
 #endif // jsinfer_h___
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -208,41 +208,16 @@ struct AutoEnterCompilation
 
     ~AutoEnterCompilation()
     {
         JS_ASSERT(cx->compartment->types.compiledScript == script);
         cx->compartment->types.compiledScript = NULL;
     }
 };
 
-/* Whether type barriers can be placed at pc for a property read. */
-static inline bool
-CanHaveReadBarrier(const jsbytecode *pc)
-{
-    JS_ASSERT(JSOp(*pc) != JSOP_TRAP);
-
-    switch (JSOp(*pc)) {
-      case JSOP_LENGTH:
-      case JSOP_GETPROP:
-      case JSOP_CALLPROP:
-      case JSOP_GETXPROP:
-      case JSOP_GETELEM:
-      case JSOP_CALLELEM:
-      case JSOP_NAME:
-      case JSOP_CALLNAME:
-      case JSOP_GETGNAME:
-      case JSOP_CALLGNAME:
-      case JSOP_GETGLOBAL:
-      case JSOP_CALLGLOBAL:
-        return true;
-      default:
-        return false;
-    }
-}
-
 /////////////////////////////////////////////////////////////////////
 // Interface functions
 /////////////////////////////////////////////////////////////////////
 
 /*
  * 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
@@ -270,39 +245,27 @@ GetTypeCallerInitObject(JSContext *cx, b
         jsbytecode *pc;
         JSScript *script = cx->stack.currentScript(&pc);
         if (script && script->compartment == cx->compartment)
             return script->types.initObject(cx, pc, isArray);
     }
     return GetTypeNewObject(cx, isArray ? JSProto_Array : JSProto_Object);
 }
 
-/* Mark the immediate scripted caller of a native as having produced an unexpected value. */
+/*
+ * When using a custom iterator within the initialization of a 'for in' loop,
+ * mark the iterator values as unknown.
+ */
 inline void
-MarkTypeCallerUnexpected(JSContext *cx, jstype type)
+MarkIteratorUnknown(JSContext *cx)
 {
-    extern void MarkTypeCallerUnexpectedSlow(JSContext *cx, jstype type);
+    extern void MarkIteratorUnknownSlow(JSContext *cx);
 
     if (cx->typeInferenceEnabled())
-        MarkTypeCallerUnexpectedSlow(cx, type);
-}
-
-inline void
-MarkTypeCallerUnexpected(JSContext *cx, const Value &value)
-{
-    extern void MarkTypeCallerUnexpectedSlow(JSContext *cx, const Value &value);
-
-    if (cx->typeInferenceEnabled())
-        MarkTypeCallerUnexpectedSlow(cx, value);
-}
-
-inline void
-MarkTypeCallerOverflow(JSContext *cx)
-{
-    MarkTypeCallerUnexpected(cx, TYPE_DOUBLE);
+        MarkIteratorUnknownSlow(cx);
 }
 
 /*
  * Monitor a javascript call, either on entry to the interpreter or made
  * from within the interpreter.
  */
 inline void
 TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing)
@@ -1118,33 +1081,16 @@ TypeSet::getObject(unsigned i)
 inline TypeObject *
 TypeSet::getSingleObject()
 {
     if (!baseFlags() && objectCount == 1)
         return getObject(0);
     return NULL;
 }
 
-inline TypeSet *
-TypeSet::make(JSContext *cx, const char *name)
-{
-    JS_ASSERT(cx->compartment->activeInference);
-
-    TypeSet *res = ArenaNew<TypeSet>(cx->compartment->pool);
-    if (!res) {
-        cx->compartment->types.setPendingNukeTypes(cx);
-        return NULL;
-    }
-
-    InferSpew(ISpewOps, "typeSet: T%p intermediate %s", res, name);
-    res->setIntermediate();
-
-    return res;
-}
-
 /////////////////////////////////////////////////////////////////////
 // TypeCallsite
 /////////////////////////////////////////////////////////////////////
 
 inline
 TypeCallsite::TypeCallsite(JSContext *cx, JSScript *script, jsbytecode *pc,
                            bool isNew, unsigned argumentCount)
     : script(script), pc(pc), isNew(isNew), argumentCount(argumentCount),
@@ -1214,37 +1160,32 @@ TypeObject::name()
 {
 #ifdef DEBUG
     return TypeIdString(name_);
 #else
     return NULL;
 #endif
 }
 
-inline TypeObject::TypeObject(jsid name, JSObject *proto)
+inline TypeObject::TypeObject(jsid name, JSObject *proto, bool isFunction)
     : proto(proto), emptyShapes(NULL),
-      flags(0), isFunction(false), marked(false), newScriptCleared(false),
+      flags(0), isFunction(isFunction), isFunctionNative(false),
+      marked(false), newScriptCleared(false),
       newScript(NULL), initializerObject(false), initializerArray(false), initializerOffset(0),
       contribution(0), propertySet(NULL), propertyCount(0),
       instanceList(NULL), instanceNext(NULL), next(NULL),
-      singleton(NULL)
+      singleton(NULL), functionScript(NULL)
 {
 #ifdef DEBUG
     this->name_ = name;
 #endif
 
     InferSpew(ISpewOps, "newObject: %s", this->name());
 }
 
-inline TypeFunction::TypeFunction(jsid name, JSObject *proto)
-    : TypeObject(name, proto), handler(NULL), script(NULL), isGeneric(false)
-{
-    isFunction = true;
-}
-
 inline void
 SweepClonedTypes(ClonedTypeSet *types)
 {
     if (types->objectCount >= 2) {
         for (unsigned i = 0; i < types->objectCount; i++) {
             if (!types->objectSet[i]->marked)
                 types->objectSet[i--] = types->objectSet[--types->objectCount];
         }
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -651,17 +651,16 @@ 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;
         }
-        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());
@@ -1279,17 +1278,16 @@ 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) {
-            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;
@@ -2910,16 +2908,17 @@ BEGIN_CASE(JSOP_STOP)
         atoms = FrameAtomBase(cx, regs.fp());
 
         /* Resume execution in the calling frame. */
         RESET_USE_METHODJIT();
         if (JS_LIKELY(interpReturnOK)) {
             JS_ASSERT(js_CodeSpec[js_GetOpcode(cx, script, regs.pc)].length
                       == JSOP_CALL_LENGTH);
             TRACE_0(LeaveFrame);
+            script->types.monitor(cx, regs.pc, regs.sp[-1]);
             len = JSOP_CALL_LENGTH;
             DO_NEXT_OP(len);
         }
         goto error;
     } else {
         JS_ASSERT(regs.sp == regs.fp()->base());
     }
     interpReturnOK = true;
@@ -4658,32 +4657,34 @@ BEGIN_CASE(JSOP_NEW)
     }
 
     if (!InvokeConstructor(cx, InvokeArgsAlreadyOnTheStack(argc, vp)))
         goto error;
     regs.sp = vp + 1;
     CHECK_INTERRUPT_HANDLER();
     TRACE_0(NativeCallComplete);
 
-  end_new:;
+  end_new:
+    script->types.monitor(cx, regs.pc, regs.sp[-1]);
 }
 END_CASE(JSOP_NEW)
 
 BEGIN_CASE(JSOP_EVAL)
 {
     argc = GET_ARGC(regs.pc);
     vp = regs.sp - (argc + 2);
 
     if (!IsBuiltinEvalForScope(&regs.fp()->scopeChain(), *vp))
         goto call_using_invoke;
 
     if (!DirectEval(cx, CallArgsFromVp(argc, vp)))
         goto error;
 
     regs.sp = vp + 1;
+    script->types.monitor(cx, regs.pc, regs.sp[-1]);
 }
 END_CASE(JSOP_EVAL)
 
 BEGIN_CASE(JSOP_CALL)
 BEGIN_CASE(JSOP_FUNAPPLY)
 BEGIN_CASE(JSOP_FUNCALL)
 {
     argc = GET_ARGC(regs.pc);
@@ -4782,17 +4783,18 @@ BEGIN_CASE(JSOP_FUNCALL)
     ok = Invoke(cx, InvokeArgsAlreadyOnTheStack(argc, vp));
     regs.sp = vp + 1;
     CHECK_INTERRUPT_HANDLER();
     if (!ok)
         goto error;
     JS_RUNTIME_METER(rt, nonInlineCalls);
     TRACE_0(NativeCallComplete);
 
-  end_call:;
+  end_call:
+    script->types.monitor(cx, regs.pc, regs.sp[-1]);
 }
 END_CASE(JSOP_CALL)
 
 } // end block around calling opcodes
 
 BEGIN_CASE(JSOP_SETCALL)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_LEFTSIDE_OF_ASS);
--- 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))
-        types::MarkTypeCallerUnexpected(cx, types::TYPE_UNKNOWN);
+        types::MarkIteratorUnknown(cx);
 
     /* 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()) {
         /*
@@ -745,17 +745,17 @@ iterator_next(JSContext *cx, uintN argc,
         return false;
     }
     return js_IteratorNext(cx, obj, vp);
 }
 
 #define JSPROP_ROPERM   (JSPROP_READONLY | JSPROP_PERMANENT)
 
 static JSFunctionSpec iterator_methods[] = {
-    JS_FN_TYPE(js_next_str,      iterator_next,  0,JSPROP_ROPERM, JS_TypeHandlerDynamic),
+    JS_FN(js_next_str,      iterator_next,  0,JSPROP_ROPERM),
     JS_FS_END
 };
 
 /*
  * Call ToObject(v).__iterator__(keyonly) if ToObject(v).__iterator__ exists.
  * Otherwise construct the default iterator.
  */
 JS_FRIEND_API(JSBool)
@@ -1448,49 +1448,49 @@ generator_throw(JSContext *cx, uintN arg
 
 static JSBool
 generator_close(JSContext *cx, uintN argc, Value *vp)
 {
     return generator_op(cx, JSGENOP_CLOSE, vp, argc);
 }
 
 static JSFunctionSpec generator_methods[] = {
-    JS_FN_TYPE(js_next_str,      generator_next,     0,JSPROP_ROPERM, JS_TypeHandlerDynamic),
-    JS_FN_TYPE(js_send_str,      generator_send,     1,JSPROP_ROPERM, JS_TypeHandlerDynamic),
-    JS_FN_TYPE(js_throw_str,     generator_throw,    1,JSPROP_ROPERM, JS_TypeHandlerDynamic),
-    JS_FN_TYPE(js_close_str,     generator_close,    0,JSPROP_ROPERM, JS_TypeHandlerVoid),
+    JS_FN(js_next_str,      generator_next,     0,JSPROP_ROPERM),
+    JS_FN(js_send_str,      generator_send,     1,JSPROP_ROPERM),
+    JS_FN(js_throw_str,     generator_throw,    1,JSPROP_ROPERM),
+    JS_FN(js_close_str,     generator_close,    0,JSPROP_ROPERM),
     JS_FS_END
 };
 
 #endif /* JS_HAS_GENERATORS */
 
 JSObject *
 js_InitIteratorClasses(JSContext *cx, JSObject *obj)
 {
     JSObject *proto, *stop;
 
     /* Idempotency required: we initialize several things, possibly lazily. */
     if (!js_GetClassObject(cx, obj, JSProto_StopIteration, &stop))
         return NULL;
     if (stop)
         return stop;
 
-    proto = js_InitClass(cx, obj, NULL, &js_IteratorClass, Iterator, 2, JS_TypeHandlerDynamic,
+    proto = js_InitClass(cx, obj, NULL, &js_IteratorClass, Iterator, 2,
                          NULL, iterator_methods, NULL, NULL);
     if (!proto)
         return NULL;
 
 #if JS_HAS_GENERATORS
     /* Initialize the generator internals if configured. */
-    if (!js_InitClass(cx, obj, NULL, &js_GeneratorClass, NULL, 0, NULL,
+    if (!js_InitClass(cx, obj, NULL, &js_GeneratorClass, NULL, 0,
                       NULL, generator_methods, NULL, NULL)) {
         return NULL;
     }
 #endif
 
     MarkStandardClassInitializedNoProto(obj, &js_StopIterationClass);
 
-    proto = js_InitClass(cx, obj, NULL, &js_StopIterationClass, NULL, 0, NULL,
+    proto = js_InitClass(cx, obj, NULL, &js_StopIterationClass, NULL, 0,
                          NULL, NULL, NULL, NULL);
     if (proto)
         types::AddTypeProperty(cx, obj->getType(), js_StopIteration_str, ObjectValue(*proto));
     return proto;
 }
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -121,24 +121,22 @@ Class js_MathClass = {
 
 JSBool
 js_math_abs(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
-        types::MarkTypeCallerOverflow(cx);
         return JS_TRUE;
     }
     if (!ValueToNumber(cx, vp[2], &x))
         return JS_FALSE;
     z = fabs(x);
-    if (!vp->setNumber(z) && !vp[2].isDouble())
-        types::MarkTypeCallerOverflow(cx);
+    vp->setNumber(z);
     return JS_TRUE;
 }
 
 static JSBool
 math_acos(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z;
 
@@ -266,24 +264,22 @@ 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);
-        types::MarkTypeCallerOverflow(cx);
         return JS_TRUE;
     }
     if (!ValueToNumber(cx, vp[2], &x))
         return JS_FALSE;
     z = js_math_ceil_impl(x);
-    if (!vp->setNumber(z))
-        types::MarkTypeCallerOverflow(cx);
+    vp->setNumber(z);
     return JS_TRUE;
 }
 
 static JSBool
 math_cos(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z;
 
@@ -342,24 +338,22 @@ 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);
-        types::MarkTypeCallerOverflow(cx);
         return JS_TRUE;
     }
     if (!ValueToNumber(cx, vp[2], &x))
         return JS_FALSE;
     z = js_math_floor_impl(x);
-    if (!vp->setNumber(z))
-        types::MarkTypeCallerOverflow(cx);
+    vp->setNumber(z);
     return JS_TRUE;
 }
 
 static JSBool
 math_log(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z;
 
@@ -387,74 +381,64 @@ 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);
-        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);
-            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)
-        types::MarkTypeCallerOverflow(cx);
+    vp->setNumber(z);
     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);
-        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);
-            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)
-        types::MarkTypeCallerOverflow(cx);
+    vp->setNumber(z);
     return JS_TRUE;
 }
 
 static jsdouble
 powi(jsdouble x, jsint y)
 {
     jsuint n = (y < 0) ? -y : y;
     jsdouble m = x;
@@ -483,65 +467,56 @@ 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);
-        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)
-                types::MarkTypeCallerOverflow(cx);
             return JS_TRUE;
         }
         if (y == -0.5) {
             vp->setNumber(1.0/sqrt(x));
-            if (!expectDouble)
-                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)
-            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)
-        types::MarkTypeCallerOverflow(cx);
+    vp->setNumber(z);
     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);
 
@@ -616,24 +591,22 @@ 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);
-        types::MarkTypeCallerOverflow(cx);
         return JS_TRUE;
     }
     if (!ValueToNumber(cx, vp[2], &x))
         return JS_FALSE;
     z = js_copysign(floor(x + 0.5), x);
-    if (!vp->setNumber(z))
-        types::MarkTypeCallerOverflow(cx);
+    vp->setNumber(z);
     return JS_TRUE;
 }
 
 static JSBool
 math_sin(JSContext *cx, uintN argc, Value *vp)
 {
     jsdouble x, z;
 
@@ -854,50 +827,38 @@ JS_DEFINE_TRCINFO_1(math_random,
     (1, (static, DOUBLE, math_random_tn, CONTEXT,       0, nanojit::ACCSET_STORE_ANY)))
 JS_DEFINE_TRCINFO_1(js_math_round,
     (1, (static, DOUBLE, math_round_tn, DOUBLE,         1, nanojit::ACCSET_NONE)))
 JS_DEFINE_TRCINFO_1(js_math_ceil,
     (1, (static, DOUBLE, math_ceil_tn, DOUBLE,          1, nanojit::ACCSET_NONE)))
 
 #endif /* JS_TRACER */
 
-static void math_TypeArith(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    types::TypeCallsite *site = Valueify(jssite);
-
-    if (site->isNew)
-        site->returnTypes->addType(cx, types::TYPE_UNKNOWN);
-
-    /* The zero-argument case will be handled as an overflow in the actual natives. */
-    for (size_t ind = 0; ind < site->argumentCount; ind++)
-        site->argumentTypes[ind]->addArith(cx, site->script, site->returnTypes);
-}
-
 static JSFunctionSpec math_static_methods[] = {
 #if JS_HAS_TOSOURCE
-    JS_FN_TYPE(js_toSource_str,  math_toSource,        0, 0, JS_TypeHandlerString),
+    JS_FN(js_toSource_str,  math_toSource,        0, 0),
 #endif
-    JS_TN("abs",            math_abs,             1, 0, &js_math_abs_trcinfo, math_TypeArith),
-    JS_TN("acos",           math_acos,            1, 0, &math_acos_trcinfo, JS_TypeHandlerFloat),
-    JS_TN("asin",           math_asin,            1, 0, &math_asin_trcinfo, JS_TypeHandlerFloat),
-    JS_TN("atan",           math_atan,            1, 0, &math_atan_trcinfo, JS_TypeHandlerFloat),
-    JS_TN("atan2",          math_atan2,           2, 0, &math_atan2_trcinfo, JS_TypeHandlerFloat),
-    JS_TN("ceil",           js_math_ceil,         1, 0, &js_math_ceil_trcinfo, JS_TypeHandlerInt),
-    JS_TN("cos",            math_cos,             1, 0, &math_cos_trcinfo, JS_TypeHandlerFloat),
-    JS_TN("exp",            math_exp,             1, 0, &math_exp_trcinfo, JS_TypeHandlerFloat),
-    JS_TN("floor",          js_math_floor,        1, 0, &js_math_floor_trcinfo, JS_TypeHandlerInt),
-    JS_TN("log",            math_log,             1, 0, &math_log_trcinfo, JS_TypeHandlerFloat),
-    JS_TN("max",            js_math_max,          2, 0, &js_math_max_trcinfo, math_TypeArith),
-    JS_TN("min",            js_math_min,          2, 0, &js_math_min_trcinfo, math_TypeArith),
-    JS_TN("pow",            js_math_pow,          2, 0, &js_math_pow_trcinfo, math_TypeArith),
-    JS_TN("random",         math_random,          0, 0, &math_random_trcinfo, JS_TypeHandlerFloat),
-    JS_TN("round",          js_math_round,        1, 0, &js_math_round_trcinfo, JS_TypeHandlerInt),
-    JS_TN("sin",            math_sin,             1, 0, &math_sin_trcinfo, JS_TypeHandlerFloat),
-    JS_TN("sqrt",           js_math_sqrt,         1, 0, &js_math_sqrt_trcinfo, JS_TypeHandlerFloat),
-    JS_TN("tan",            math_tan,             1, 0, &math_tan_trcinfo, JS_TypeHandlerFloat),
+    JS_TN("abs",            js_math_abs,          1, 0, &js_math_abs_trcinfo),
+    JS_TN("acos",           math_acos,            1, 0, &math_acos_trcinfo),
+    JS_TN("asin",           math_asin,            1, 0, &math_asin_trcinfo),
+    JS_TN("atan",           math_atan,            1, 0, &math_atan_trcinfo),
+    JS_TN("atan2",          math_atan2,           2, 0, &math_atan2_trcinfo),
+    JS_TN("ceil",           js_math_ceil,         1, 0, &js_math_ceil_trcinfo),
+    JS_TN("cos",            math_cos,             1, 0, &math_cos_trcinfo),
+    JS_TN("exp",            math_exp,             1, 0, &math_exp_trcinfo),
+    JS_TN("floor",          js_math_floor,        1, 0, &js_math_floor_trcinfo),
+    JS_TN("log",            math_log,             1, 0, &math_log_trcinfo),
+    JS_TN("max",            js_math_max,          2, 0, &js_math_max_trcinfo),
+    JS_TN("min",            js_math_min,          2, 0, &js_math_min_trcinfo),
+    JS_TN("pow",            js_math_pow,          2, 0, &js_math_pow_trcinfo),
+    JS_TN("random",         math_random,          0, 0, &math_random_trcinfo),
+    JS_TN("round",          js_math_round,        1, 0, &js_math_round_trcinfo),
+    JS_TN("sin",            math_sin,             1, 0, &math_sin_trcinfo),
+    JS_TN("sqrt",           js_math_sqrt,         1, 0, &js_math_sqrt_trcinfo),
+    JS_TN("tan",            math_tan,             1, 0, &math_tan_trcinfo),
     JS_FS_END
 };
 
 bool
 js_IsMathFunction(JSNative native)
 {
     for (size_t i=0; math_static_methods[i].name != NULL; i++) {
         if (native == math_static_methods[i].call)
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -418,17 +418,16 @@ 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);
-        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;
         }
@@ -438,18 +437,17 @@ num_parseInt(JSContext *cx, uintN argc, 
          * the word, which would mean the result of parseInt(string) should be |N|.
          *
          * 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) {
-            if (!vp->setNumber(ParseIntDoubleHelper(vp[2].toDouble())))
-                MarkTypeCallerOverflow(cx);
+            vp->setNumber(ParseIntDoubleHelper(vp[2].toDouble()));
             return true;
         }
     }
 
     /* Step 1. */
     JSString *inputString = js_ValueToString(cx, vp[2]);
     if (!inputString)
         return false;
@@ -459,17 +457,16 @@ 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);
-                MarkTypeCallerOverflow(cx);
                 return true;
             }
             if (radix != 16)
                 stripPrefix = false;
         }
     }
 
     /* Steps 2-5, 9-14. */
@@ -478,18 +475,17 @@ num_parseInt(JSContext *cx, uintN argc, 
         return false;
     const jschar *end = ws + inputString->length();
 
     jsdouble number;
     if (!ParseIntStringHelper(cx, ws, end, radix, stripPrefix, &number))
         return false;
 
     /* Step 15. */
-    if (!vp->setNumber(number))
-        MarkTypeCallerOverflow(cx);
+    vp->setNumber(number);
     return true;
 }
 
 #ifdef JS_TRACER
 static jsdouble FASTCALL
 ParseInt(JSContext* cx, JSString* str)
 {
     TraceMonitor *tm = JS_TRACE_MONITOR_ON_TRACE(cx);
@@ -542,20 +538,20 @@ JS_DEFINE_TRCINFO_2(num_parseInt,
     (2, (static, DOUBLE_FAIL, ParseIntDouble, CONTEXT, DOUBLE,1, nanojit::ACCSET_NONE)))
 
 JS_DEFINE_TRCINFO_1(num_parseFloat,
     (2, (static, DOUBLE_FAIL, ParseFloat, CONTEXT, STRING,   1, nanojit::ACCSET_NONE)))
 
 #endif /* JS_TRACER */
 
 static JSFunctionSpec number_functions[] = {
-    JS_FN_TYPE(js_isNaN_str,         num_isNaN,           1,0, JS_TypeHandlerBool),
-    JS_FN_TYPE(js_isFinite_str,      num_isFinite,        1,0, JS_TypeHandlerBool),
-    JS_TN(js_parseFloat_str,    num_parseFloat,      1,0, &num_parseFloat_trcinfo, JS_TypeHandlerFloat),
-    JS_TN(js_parseInt_str,      num_parseInt,        2,0, &num_parseInt_trcinfo, JS_TypeHandlerInt),
+    JS_FN(js_isNaN_str,         num_isNaN,           1,0),
+    JS_FN(js_isFinite_str,      num_isFinite,        1,0),
+    JS_TN(js_parseFloat_str,    num_parseFloat,      1,0, &num_parseFloat_trcinfo),
+    JS_TN(js_parseInt_str,      num_parseInt,        2,0, &num_parseInt_trcinfo),
     JS_FS_END
 };
 
 Class js_NumberClass = {
     js_Number_str,
     JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Number),
     PropertyStub,         /* addProperty */
     PropertyStub,         /* delProperty */
@@ -958,24 +954,24 @@ JS_DEFINE_TRCINFO_2(num_toString,
          1, nanojit::ACCSET_NONE)),
     (3, (static, STRING_RETRY, js_NumberToStringWithBase, CONTEXT, THIS_DOUBLE, INT32,
          1, nanojit::ACCSET_NONE)))
 
 #endif /* JS_TRACER */
 
 static JSFunctionSpec number_methods[] = {
 #if JS_HAS_TOSOURCE
-    JS_FN_TYPE(js_toSource_str,       num_toSource,       0, 0, JS_TypeHandlerString),
+    JS_FN(js_toSource_str,       num_toSource,          0, 0),
 #endif
-    JS_TN(js_toString_str,            num_toString,       1, 0, &num_toString_trcinfo, JS_TypeHandlerString),
-    JS_FN_TYPE(js_toLocaleString_str, num_toLocaleString, 0, 0, JS_TypeHandlerString),
-    JS_FN_TYPE(js_valueOf_str,        js_num_valueOf,     0, 0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("toFixed",             num_toFixed,        1, 0, JS_TypeHandlerString),
-    JS_FN_TYPE("toExponential",       num_toExponential,  1, 0, JS_TypeHandlerString),
-    JS_FN_TYPE("toPrecision",         num_toPrecision,    1, 0, JS_TypeHandlerString),
+    JS_TN(js_toString_str,       num_toString,          1, 0, &num_toString_trcinfo),
+    JS_FN(js_toLocaleString_str, num_toLocaleString,    0, 0),
+    JS_FN(js_valueOf_str,        js_num_valueOf,        0, 0),
+    JS_FN("toFixed",             num_toFixed,           1, 0),
+    JS_FN("toExponential",       num_toExponential,     1, 0),
+    JS_FN("toPrecision",         num_toPrecision,       1, 0),
     JS_FS_END
 };
 
 /* NB: Keep this in synch with number_constants[]. */
 enum nc_slot {
     NC_NaN,
     NC_POSITIVE_INFINITY,
     NC_NEGATIVE_INFINITY,
@@ -1080,34 +1076,26 @@ js_FinishRuntimeNumberState(JSContext *c
     JSRuntime *rt = cx->runtime;
 
     cx->free_((void *) rt->thousandsSeparator);
     cx->free_((void *) rt->decimalSeparator);
     cx->free_((void *) rt->numGrouping);
     rt->thousandsSeparator = rt->decimalSeparator = rt->numGrouping = NULL;
 }
 
-static void type_NewNumber(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    if (Valueify(jssite)->isNew)
-        JS_TypeHandlerNew(cx, jsfun, jssite);
-    else
-        JS_TypeHandlerFloat(cx, jsfun, jssite);
-}
-
 JSObject *
 js_InitNumberClass(JSContext *cx, JSObject *obj)
 {
     JSObject *proto, *ctor;
     JSRuntime *rt;
 
     /* XXX must do at least once per new thread, so do it per JSContext... */
     FIX_FPU();
 
-    proto = js_InitClass(cx, obj, NULL, &js_NumberClass, Number, 1, type_NewNumber,
+    proto = js_InitClass(cx, obj, NULL, &js_NumberClass, Number, 1,
                          NULL, number_methods, NULL, NULL);
     if (!proto || !(ctor = JS_GetConstructor(cx, proto)))
         return NULL;
     proto->setPrimitiveThis(Int32Value(0));
 
     if (!JS_DefineFunctions(cx, obj, number_functions))
         return NULL;
 
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2810,51 +2810,51 @@ const char js_watch_str[] = "watch";
 const char js_unwatch_str[] = "unwatch";
 #endif
 const char js_hasOwnProperty_str[] = "hasOwnProperty";
 const char js_isPrototypeOf_str[] = "isPrototypeOf";
 const char js_propertyIsEnumerable_str[] = "propertyIsEnumerable";
 
 static JSFunctionSpec object_methods[] = {
 #if JS_HAS_TOSOURCE
-    JS_FN_TYPE(js_toSource_str,             obj_toSource,                0,0, JS_TypeHandlerString),
+    JS_FN(js_toSource_str,             obj_toSource,                0,0),
 #endif
-    JS_FN_TYPE(js_toString_str,             obj_toString,                0,0, JS_TypeHandlerString),
-    JS_FN_TYPE(js_toLocaleString_str,       obj_toLocaleString,          0,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE(js_valueOf_str,              obj_valueOf,                 0,0, JS_TypeHandlerDynamic),
+    JS_FN(js_toString_str,             obj_toString,                0,0),
+    JS_FN(js_toLocaleString_str,       obj_toLocaleString,          0,0),
+    JS_FN(js_valueOf_str,              obj_valueOf,                 0,0),
 #if JS_HAS_OBJ_WATCHPOINT
-    JS_FN_TYPE(js_watch_str,                obj_watch,                   2,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE(js_unwatch_str,              obj_unwatch,                 1,0, JS_TypeHandlerVoid),
+    JS_FN(js_watch_str,                obj_watch,                   2,0),
+    JS_FN(js_unwatch_str,              obj_unwatch,                 1,0),
 #endif
-    JS_FN_TYPE(js_hasOwnProperty_str,       obj_hasOwnProperty,          1,0, JS_TypeHandlerBool),
-    JS_FN_TYPE(js_isPrototypeOf_str,        obj_isPrototypeOf,           1,0, JS_TypeHandlerBool),
-    JS_FN_TYPE(js_propertyIsEnumerable_str, obj_propertyIsEnumerable,    1,0, JS_TypeHandlerBool),
+    JS_FN(js_hasOwnProperty_str,       obj_hasOwnProperty,          1,0),
+    JS_FN(js_isPrototypeOf_str,        obj_isPrototypeOf,           1,0),
+    JS_FN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable,    1,0),
 #if OLD_GETTER_SETTER_METHODS
-    JS_FN_TYPE(js_defineGetter_str,         js_obj_defineGetter,         2,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE(js_defineSetter_str,         js_obj_defineSetter,         2,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE(js_lookupGetter_str,         obj_lookupGetter,            1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE(js_lookupSetter_str,         obj_lookupSetter,            1,0, JS_TypeHandlerDynamic),
+    JS_FN(js_defineGetter_str,         js_obj_defineGetter,         2,0),
+    JS_FN(js_defineSetter_str,         js_obj_defineSetter,         2,0),
+    JS_FN(js_lookupGetter_str,         obj_lookupGetter,            1,0),
+    JS_FN(js_lookupSetter_str,         obj_lookupSetter,            1,0),
 #endif
     JS_FS_END
 };
 
 static JSFunctionSpec object_static_methods[] = {
-    JS_FN_TYPE("getPrototypeOf",            obj_getPrototypeOf,          1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("getOwnPropertyDescriptor",  obj_getOwnPropertyDescriptor,2,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("keys",                      obj_keys,                    1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("defineProperty",            obj_defineProperty,          3,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("defineProperties",          obj_defineProperties,        2,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("create",                    obj_create,                  2,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("getOwnPropertyNames",       obj_getOwnPropertyNames,     1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("isExtensible",              obj_isExtensible,            1,0, JS_TypeHandlerBool),
-    JS_FN_TYPE("preventExtensions",         obj_preventExtensions,       1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("freeze",                    obj_freeze,                  1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("isFrozen",                  obj_isFrozen,                1,0, JS_TypeHandlerBool),
-    JS_FN_TYPE("seal",                      obj_seal,                    1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("isSealed",                  obj_isSealed,                1,0, JS_TypeHandlerBool),
+    JS_FN("getPrototypeOf",            obj_getPrototypeOf,          1,0),
+    JS_FN("getOwnPropertyDescriptor",  obj_getOwnPropertyDescriptor,2,0),
+    JS_FN("keys",                      obj_keys,                    1,0),
+    JS_FN("defineProperty",            obj_defineProperty,          3,0),
+    JS_FN("defineProperties",          obj_defineProperties,        2,0),
+    JS_FN("create",                    obj_create,                  2,0),
+    JS_FN("getOwnPropertyNames",       obj_getOwnPropertyNames,     1,0),
+    JS_FN("isExtensible",              obj_isExtensible,            1,0),
+    JS_FN("preventExtensions",         obj_preventExtensions,       1,0),
+    JS_FN("freeze",                    obj_freeze,                  1,0),
+    JS_FN("isFrozen",                  obj_isFrozen,                1,0),
+    JS_FN("seal",                      obj_seal,                    1,0),
+    JS_FN("isSealed",                  obj_isSealed,                1,0),
     JS_FS_END
 };
 
 JSBool
 js_Object(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj;
     if (argc == 0) {
@@ -3957,51 +3957,34 @@ Class js_BlockClass = {
     PropertyStub,         /* delProperty */
     PropertyStub,         /* getProperty */
     StrictPropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
     ConvertStub
 };
 
-static void object_TypeNew(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-
-    if (site->argumentCount == 0) {
-        TypeObject *object = site->getInitObject(cx, false);
-        if (!object)
-            return;
-        site->returnTypes->addType(cx, (jstype) object);
-    } else {
-        /* The value is converted to an object, don't keep track of the return type. */
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-    }
-}
-
 JSObject *
 js_InitObjectClass(JSContext *cx, JSObject *obj)
 {
     JSObject *proto = js_InitClass(cx, obj, NULL, &js_ObjectClass, js_Object, 1,
-                                   object_TypeNew,
                                    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;
     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);
+    JSObject *evalobj = js_DefineFunction(cx, obj, id, eval, 1, JSFUN_STUB_GSOPS);
     if (!evalobj)
         return NULL;
     if (obj->isGlobal())
         obj->asGlobal()->setOriginalEval(evalobj);
 
     return proto;
 }
 
@@ -4064,17 +4047,16 @@ ClearClassObject(JSContext *cx, JSObject
     obj->setSlot(key, UndefinedValue());
     obj->setSlot(JSProto_LIMIT + key, UndefinedValue());
 }
 
 JSObject *
 DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
                               JSObject *protoProto, Class *clasp,
                               Native constructor, uintN nargs,
-                              JSTypeHandler ctorHandler,
                               JSPropertySpec *ps, JSFunctionSpec *fs,
                               JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
 {
     /*
      * Create a prototype object for this class.
      *
      * FIXME: lazy standard (built-in) class initialization and even older
      * eager boostrapping code rely on all of these properties:
@@ -4139,21 +4121,17 @@ DefineConstructorAndPrototype(JSContext 
                            ? JSPROP_READONLY | JSPROP_PERMANENT
                            : 0;
             if (!DefineStandardSlot(cx, obj, key, atom, ObjectValue(*proto), attrs, named))
                 goto bad;
         }
 
         ctor = proto;
     } else {
-        if (!ctorHandler)
-            ctorHandler = JS_TypeHandlerDynamic;
-
-        JSFunction *fun = js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR, obj, atom,
-                                         ctorHandler, clasp->name);
+        JSFunction *fun = js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR, obj, atom);
         if (!fun)
             goto bad;
 
         /*
          * Set the class object early for standard class constructors. Type
          * inference may need to access these, and js_GetClassPrototype will
          * fail if it tries to do a reentrant reconstruction of the class.
          */
@@ -4300,17 +4278,16 @@ MarkStandardClassInitializedNoProto(JSOb
         obj->setSlot(key, BooleanValue(true));
 }
 
 }
 
 JSObject *
 js_InitClass(JSContext *cx, JSObject *obj, JSObject *protoProto,
              Class *clasp, Native constructor, uintN nargs,
-             JSTypeHandler ctorHandler,
              JSPropertySpec *ps, JSFunctionSpec *fs,
              JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
 {
     JSAtom *atom = js_Atomize(cx, clasp->name, strlen(clasp->name));
     if (!atom)
         return NULL;
 
     /*
@@ -4328,17 +4305,17 @@ js_InitClass(JSContext *cx, JSObject *ob
     JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
     if (key != JSProto_Null &&
         !protoProto &&
         !js_GetClassPrototype(cx, obj, JSProto_Object, &protoProto)) {
         return NULL;
     }
 
     return DefineConstructorAndPrototype(cx, obj, key, atom, protoProto, clasp, constructor, nargs,
-                                         ctorHandler, ps, fs, static_ps, static_fs);
+                                         ps, fs, static_ps, static_fs);
 }
 
 void
 JSObject::clearSlotRange(size_t start, size_t length)
 {
     JS_ASSERT(start + length <= capacity);
     if (isDenseArray()) {
         ClearValueRange(slots + start, length, true);
@@ -4386,19 +4363,17 @@ JSObject::numDynamicSlots(size_t capacit
 {
     JS_ASSERT(capacity >= numFixedSlots());
     return isDenseArray() ? capacity : capacity - numFixedSlots();
 }
 
 bool
 JSObject::allocSlots(JSContext *cx, size_t newcap)
 {
-    uint32 oldcap = numSlots();
-
-    JS_ASSERT(newcap >= oldcap && !hasSlotsArray());
+    JS_ASSERT(newcap >= numSlots() && !hasSlotsArray());
 
     /*
      * If we are allocating slots for an object whose type is always created
      * by calling 'new' on a particular script, bump the GC kind for that
      * type to give these objects a larger number of fixed slots when future
      * objects are constructed.
      */
     if (type->newScript) {
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1541,32 +1541,30 @@ JS_FRIEND_API(JSBool) js_obj_defineSette
 extern JSObject *
 js_InitObjectClass(JSContext *cx, JSObject *obj);
 
 namespace js {
 JSObject *
 DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
                               JSObject *protoProto, Class *clasp,
                               Native constructor, uintN nargs,
-                              JSTypeHandler ctorHandler,
                               JSPropertySpec *ps, JSFunctionSpec *fs,
                               JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
 
 bool
 IsStandardClassResolved(JSObject *obj, js::Class *clasp);
 
 void
 MarkStandardClassInitializedNoProto(JSObject *obj, js::Class *clasp);
 
 }
 
 extern JSObject *
 js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
              js::Class *clasp, js::Native constructor, uintN nargs,
-             JSTypeHandler ctorHandler,
              JSPropertySpec *ps, JSFunctionSpec *fs,
              JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
 
 /*
  * Select Object.prototype method names shared between jsapi.cpp and jsobj.cpp.
  */
 extern const char js_watch_str[];
 extern const char js_unwatch_str[];
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -128,17 +128,16 @@ 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 {
-        MarkTypeCallerUnexpected(cx, types::TYPE_UNDEFINED);
         vp->setUndefined();
     }
 
     return true;
 }
 
 JSBool
 js_TryJSON(JSContext *cx, Value *vp)
@@ -915,20 +914,20 @@ json_toSource(JSContext *cx, uintN argc,
 {
     vp->setString(CLASS_ATOM(cx, JSON));
     return JS_TRUE;
 }
 #endif
 
 static JSFunctionSpec json_static_methods[] = {
 #if JS_HAS_TOSOURCE
-    JS_FN_TYPE(js_toSource_str,  json_toSource,      0, 0, JS_TypeHandlerString),
+    JS_FN(js_toSource_str,  json_toSource,      0, 0),
 #endif
-    JS_FN_TYPE("parse",          js_json_parse,      2, 0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("stringify",      js_json_stringify,  3, 0, JS_TypeHandlerString),
+    JS_FN("parse",          js_json_parse,      2, 0),
+    JS_FN("stringify",      js_json_stringify,  3, 0),
     JS_FS_END
 };
 
 JSObject *
 js_InitJSONClass(JSContext *cx, JSObject *obj)
 {
     JSObject *JSON = NewNonFunction<WithProto::Class>(cx, &js_JSONClass, NULL, obj);
     if (!JSON)
--- a/js/src/jsopcode.tbl
+++ b/js/src/jsopcode.tbl
@@ -173,17 +173,17 @@ OPDEF(JSOP_NAMEDEC,   50, "namedec",    
 OPDEF(JSOP_PROPDEC,   51, "propdec",    NULL,         3,  1,  1, 15,  JOF_ATOM|JOF_PROP|JOF_DEC|JOF_POST|JOF_TMPSLOT3)
 OPDEF(JSOP_ELEMDEC,   52, "elemdec",    NULL,         1,  2,  1, 15,  JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_POST|JOF_TMPSLOT2)
 
 OPDEF(JSOP_GETPROP,   53, "getprop",    NULL,         5,  1,  1, 18,  JOF_ATOM|JOF_PROP|JOF_TYPESET)
 OPDEF(JSOP_SETPROP,   54, "setprop",    NULL,         3,  2,  1,  3,  JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
 OPDEF(JSOP_GETELEM,   55, "getelem",    NULL,         3,  2,  1, 18,  JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC)
 OPDEF(JSOP_SETELEM,   56, "setelem",    NULL,         1,  3,  1,  3,  JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING)
 OPDEF(JSOP_CALLNAME,  57, "callname",   NULL,         5,  0,  2, 19,  JOF_ATOM|JOF_NAME|JOF_TYPESET|JOF_CALLOP)
-OPDEF(JSOP_CALL,      58, "call",       NULL,         3, -1,  1, 18,  JOF_UINT16|JOF_INVOKE)
+OPDEF(JSOP_CALL,      58, "call",       NULL,         5, -1,  1, 18,  JOF_UINT16|JOF_INVOKE|JOF_TYPESET)
 OPDEF(JSOP_NAME,      59, "name",       NULL,         5,  0,  1, 19,  JOF_ATOM|JOF_NAME|JOF_TYPESET)
 OPDEF(JSOP_DOUBLE,    60, "double",     NULL,         3,  0,  1, 16,  JOF_ATOM)
 OPDEF(JSOP_STRING,    61, "string",     NULL,         3,  0,  1, 19,  JOF_ATOM)
 OPDEF(JSOP_ZERO,      62, "zero",       "0",          1,  0,  1, 16,  JOF_BYTE)
 OPDEF(JSOP_ONE,       63, "one",        "1",          1,  0,  1, 16,  JOF_BYTE)
 OPDEF(JSOP_NULL,      64, js_null_str,  js_null_str,  1,  0,  1, 19,  JOF_BYTE)
 OPDEF(JSOP_THIS,      65, js_this_str,  js_this_str,  1,  0,  1, 19,  JOF_BYTE)
 OPDEF(JSOP_FALSE,     66, js_false_str, js_false_str, 1,  0,  1, 19,  JOF_BYTE)
@@ -216,27 +216,27 @@ OPDEF(JSOP_SETCALL,   74, "setcall",    
  *
  * JSOP_ENDITER cleans up after the loop. It uses the slot above the iterator
  * for temporary GC rooting.
  */
 OPDEF(JSOP_ITER,      75, "iter",       NULL,         2,  1,  1,  0,  JOF_UINT8)
 OPDEF(JSOP_MOREITER,  76, "moreiter",   NULL,         1,  1,  2,  0,  JOF_BYTE)
 OPDEF(JSOP_ENDITER,   77, "enditer",    NULL,         1,  1,  0,  0,  JOF_BYTE)
 
-OPDEF(JSOP_FUNAPPLY,  78, "funapply",   NULL,         3, -1,  1, 18,  JOF_UINT16|JOF_INVOKE)
+OPDEF(JSOP_FUNAPPLY,  78, "funapply",   NULL,         5, -1,  1, 18,  JOF_UINT16|JOF_INVOKE|JOF_TYPESET)
 OPDEF(JSOP_SWAP,      79, "swap",       NULL,         1,  2,  2,  0,  JOF_BYTE)
 
 /* Push object literal: either an XML object or initialiser object. */
 OPDEF(JSOP_OBJECT,    80, "object",     NULL,         3,  0,  1, 19,  JOF_OBJECT)
 
 /* Pop value and discard it. */
 OPDEF(JSOP_POP,       81, "pop",        NULL,         1,  1,  0,  2,  JOF_BYTE)
 
 /* Call a function as a constructor; operand is argc. */
-OPDEF(JSOP_NEW,       82, js_new_str,   NULL,         3, -1,  1, 17,  JOF_UINT16|JOF_INVOKE)
+OPDEF(JSOP_NEW,       82, js_new_str,   NULL,         5, -1,  1, 17,  JOF_UINT16|JOF_INVOKE|JOF_TYPESET)
 
 /* Trap into debugger for breakpoint, etc. */
 OPDEF(JSOP_TRAP,      83, "trap",       NULL,         1,  0,  0,  0,  JOF_BYTE)
 
 /* Fast get/set ops for function arguments and local variables. */
 OPDEF(JSOP_GETARG,    84, "getarg",     NULL,         3,  0,  1, 19,  JOF_QARG |JOF_NAME)
 OPDEF(JSOP_SETARG,    85, "setarg",     NULL,         3,  1,  1,  3,  JOF_QARG |JOF_NAME|JOF_SET)
 OPDEF(JSOP_GETLOCAL,  86,"getlocal",    NULL,         3,  0,  1, 19,  JOF_LOCAL|JOF_NAME)
@@ -312,17 +312,17 @@ OPDEF(JSOP_LINENO,    119,"lineno",     
  */
 OPDEF(JSOP_CONDSWITCH,120,"condswitch", NULL,         1,  0,  0,  0,  JOF_BYTE|JOF_PARENHEAD)
 OPDEF(JSOP_CASE,      121,"case",       NULL,         3,  2,  1,  0,  JOF_JUMP|JOF_TMPSLOT2)
 OPDEF(JSOP_DEFAULT,   122,"default",    NULL,         3,  1,  0,  0,  JOF_JUMP)
 
 /*
  * ECMA-compliant call to eval op
  */
-OPDEF(JSOP_EVAL,      123,"eval",       NULL,         3, -1,  1, 18,  JOF_UINT16|JOF_INVOKE)
+OPDEF(JSOP_EVAL,      123,"eval",       NULL,         5, -1,  1, 18,  JOF_UINT16|JOF_INVOKE|JOF_TYPESET)
 
 /*
  * ECMA-compliant helper for 'for (x[i] in o)' loops.
  */
 OPDEF(JSOP_ENUMELEM,  124,"enumelem",   NULL,         1,  3,  0,  3,  JOF_BYTE |JOF_SET|JOF_TMPSLOT)
 
 /*
  * Getter and setter prefix bytecodes.  These modify the next bytecode, either
@@ -601,14 +601,14 @@ OPDEF(JSOP_UNBRANDTHIS,   235,"unbrandth
 
 OPDEF(JSOP_SHARPINIT,     236,"sharpinit",     NULL,  3,  0,  0,  0,  JOF_UINT16|JOF_SHARPSLOT)
 
 /* Static binding for globals. */
 OPDEF(JSOP_GETGLOBAL,     237,"getglobal",     NULL,  5,  0,  1, 19,  JOF_GLOBAL|JOF_NAME|JOF_TYPESET)
 OPDEF(JSOP_CALLGLOBAL,    238,"callglobal",    NULL,  5,  0,  2, 19,  JOF_GLOBAL|JOF_NAME|JOF_TYPESET|JOF_CALLOP)
 
 /* Like JSOP_FUNAPPLY but for f.call instead of f.apply. */
-OPDEF(JSOP_FUNCALL,       239,"funcall",       NULL,  3, -1,  1, 18,  JOF_UINT16|JOF_INVOKE)
+OPDEF(JSOP_FUNCALL,       239,"funcall",       NULL,  5, -1,  1, 18,  JOF_UINT16|JOF_INVOKE|JOF_TYPESET)
 
 OPDEF(JSOP_FORGNAME,      240,"forgname",      NULL,  3,  1,  1, 19,  JOF_ATOM|JOF_GNAME|JOF_FOR|JOF_TMPSLOT3)
 
 /* Substituted for JSOP_SETELEM to indicate opcodes which have written holes in dense arrays. */
 OPDEF(JSOP_SETHOLE,       241, "sethole",      NULL,  1,  3,  1,  3,  JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING)
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -2009,17 +2009,17 @@ Parser::newFunction(JSTreeContext *tc, J
      * function's parent slot to tc->scopeChain. If the global context is a
      * compile-and-go one, we leave the pre-set parent intact; otherwise we
      * clear parent and proto.
      */
     while (tc->parent)
         tc = tc->parent;
     parent = tc->inFunction() ? NULL : tc->scopeChain();
 
-    fun = js_NewFunction(context, NULL, NULL, 0, JSFUN_INTERPRETED | lambda, parent, atom, NULL, NULL);
+    fun = js_NewFunction(context, NULL, NULL, 0, JSFUN_INTERPRETED | lambda, parent, atom);
     if (fun && !tc->compileAndGo()) {
         FUN_OBJECT(fun)->clearParent();
         if (!FUN_OBJECT(fun)->clearType(context))
             return NULL;
     }
     return fun;
 }
 
--- a/js/src/jspropertycache.cpp
+++ b/js/src/jspropertycache.cpp
@@ -317,21 +317,20 @@ GetAtomFromBytecode(JSContext *cx, jsbyt
 
 JS_REQUIRES_STACK JSAtom *
 PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject **pobjp,
                         PropertyCacheEntry *entry)
 {
     JSObject *obj, *pobj, *tmp;
     uint32 vcap;
 
-    StackFrame *fp = cx->fp();
     JSScript *script = cx->stack.currentScript();
 
     JS_ASSERT(this == &JS_PROPERTY_CACHE(cx));
-    JS_ASSERT(uintN((fp->hasImacropc() ? fp->imacropc() : pc) - script->code)
+    JS_ASSERT(uintN((cx->fp()->hasImacropc() ? cx->fp()->imacropc() : pc) - script->code)
               < script->length);
 
     JSOp op = js_GetOpcode(cx, script, pc);
     const JSCodeSpec &cs = js_CodeSpec[op];
 
     obj = *objp;
     vcap = entry->vcap;
 
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -1284,21 +1284,21 @@ proxy_fix(JSContext *cx, uintN argc, Val
         vp->setBoolean(true);
     }
     return true;
 }
 
 #endif
 
 static JSFunctionSpec static_methods[] = {
-    JS_FN_TYPE("create",         proxy_create,          2, 0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("createFunction", proxy_createFunction,  3, 0, JS_TypeHandlerDynamic),
+    JS_FN("create",         proxy_create,          2, 0),
+    JS_FN("createFunction", proxy_createFunction,  3, 0),
 #ifdef DEBUG
-    JS_FN_TYPE("isTrapping",     proxy_isTrapping,      1, 0, JS_TypeHandlerBool),
-    JS_FN_TYPE("fix",            proxy_fix,             1, 0, JS_TypeHandlerBool),
+    JS_FN("isTrapping",     proxy_isTrapping,      1, 0),
+    JS_FN("fix",            proxy_fix,             1, 0),
 #endif
     JS_FS_END
 };
 
 extern Class CallableObjectClass;
 
 static const uint32 JSSLOT_CALLABLE_CALL = 0;
 static const uint32 JSSLOT_CALLABLE_CONSTRUCT = 1;
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -387,29 +387,16 @@ typedef JSBool
  * Typedef for native functions called by the JS VM.
  *
  * See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros.
  */
 
 typedef JSBool
 (* JSNative)(JSContext *cx, uintN argc, jsval *vp);
 
-/*
- * Typedefs for type information on contexts, functions, objects and call sites.
- * These are values from the js::types namespace and need to be cast before
- * they can be used.
- */
-typedef struct JSTypeFunction JSTypeFunction;
-typedef struct JSTypeObject JSTypeObject;
-typedef struct JSTypeCallsite JSTypeCallsite;
-
-/* Typedef for handlers describing type information of native functions. */
-typedef void
-(* JSTypeHandler)(JSContext *cx, JSTypeFunction *fun, JSTypeCallsite *callsite);
-
 /* Callbacks and their arguments. */
 
 typedef enum JSContextOp {
     JSCONTEXT_NEW,
     JSCONTEXT_DESTROY
 } JSContextOp;
 
 /*
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -3290,17 +3290,17 @@ reflect_parse(JSContext *cx, uint32 argc
         return JS_FALSE;
     }
 
     JS_SET_RVAL(cx, vp, Jsvalify(val));
     return JS_TRUE;
 }
 
 static JSFunctionSpec static_methods[] = {
-    JS_FN_TYPE("parse", reflect_parse, 1, 0, JS_TypeHandlerDynamic),
+    JS_FN("parse", reflect_parse, 1, 0),
     JS_FS_END
 };
 
 
 JSObject *
 js_InitReflectClass(JSContext *cx, JSObject *obj)
 {
     JSObject *Reflect = NewNonFunction<WithProto::Class>(cx, &js_ReflectClass, NULL, obj);
--- a/js/src/jsregexp.cpp
+++ b/js/src/jsregexp.cpp
@@ -784,42 +784,35 @@ regexp_construct(JSContext *cx, uintN ar
         /*
          * If first arg is regexp and no flags are given, just return the arg.
          * Otherwise, delegate to the standard constructor.
          * See ECMAv5 15.10.3.1.
          */
         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.
-             */
-            MarkTypeCallerUnexpected(cx, *vp);
             return true;
         }
     }
 
     JSObject *obj = NewBuiltinClassInstance(cx, &js_RegExpClass);
     if (!obj)
         return false;
 
     return CompileRegExpAndSwap(cx, obj, argc, argv, &JS_RVAL(cx, vp));
 }
 
 static JSFunctionSpec regexp_methods[] = {
 #if JS_HAS_TOSOURCE
-    JS_FN_TYPE(js_toSource_str,  regexp_toString,    0,0, JS_TypeHandlerString),
+    JS_FN(js_toSource_str,  regexp_toString,    0,0),
 #endif
-    JS_FN_TYPE(js_toString_str,  regexp_toString,    0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("compile",        regexp_compile,     2,0, JS_TypeHandlerThis),
-    /* Note: .exec handler should subsume .test for RegExp.exec -> RegExp.test JIT optimizations */
-    JS_FN_TYPE("exec",           js_regexp_exec,     1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("test",           js_regexp_test,     1,0, JS_TypeHandlerBool),
+    JS_FN(js_toString_str,  regexp_toString,    0,0),
+    JS_FN("compile",        regexp_compile,     2,0),
+    JS_FN("exec",           js_regexp_exec,     1,0),
+    JS_FN("test",           js_regexp_test,     1,0),
     JS_FS_END
 };
 
 JSObject *
 js_InitRegExpClass(JSContext *cx, JSObject *global)
 {
     JS_ASSERT(global->isGlobal());
     JS_ASSERT(global->isNative());
@@ -863,18 +856,17 @@ js_InitRegExpClass(JSContext *cx, JSObje
     if (!JS_DefineFunctions(cx, proto, regexp_methods))
         return NULL;
     if (!cx->typeInferenceEnabled())
         proto->brand(cx);
 
     /* Create the RegExp constructor. */
     JSAtom *regExpAtom = CLASS_ATOM(cx, RegExp);
     JSFunction *ctor =
-        js_NewFunction(cx, NULL, regexp_construct, 2, JSFUN_CONSTRUCTOR, global, regExpAtom,
-                       JS_TypeHandlerNew, "RegExp");
+        js_NewFunction(cx, NULL, regexp_construct, 2, JSFUN_CONSTRUCTOR, global, regExpAtom);
     if (!ctor)
         return NULL;
 
     /* RegExp creates regular expressions. */
     FUN_CLASP(ctor) = &js_RegExpClass;
 
     /* Define RegExp.prototype and RegExp.prototype.constructor. */
     if (!js_SetClassPrototype(cx, ctor, proto, JSPROP_PERMANENT | JSPROP_READONLY))
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -604,25 +604,25 @@ const char js_unescape_str[] = "unescape
 const char js_uneval_str[] = "uneval";
 #endif
 const char js_decodeURI_str[] = "decodeURI";
 const char js_encodeURI_str[] = "encodeURI";
 const char js_decodeURIComponent_str[] = "decodeURIComponent";
 const char js_encodeURIComponent_str[] = "encodeURIComponent";
 
 static JSFunctionSpec string_functions[] = {
-    JS_FN_TYPE(js_escape_str,             str_escape,                1,0, JS_TypeHandlerString),
-    JS_FN_TYPE(js_unescape_str,           str_unescape,              1,0, JS_TypeHandlerString),
+    JS_FN(js_escape_str,             str_escape,                1,0),
+    JS_FN(js_unescape_str,           str_unescape,              1,0),
 #if JS_HAS_UNEVAL
-    JS_FN_TYPE(js_uneval_str,             str_uneval,                1,0, JS_TypeHandlerString),
+    JS_FN(js_uneval_str,             str_uneval,                1,0),
 #endif
-    JS_FN_TYPE(js_decodeURI_str,          str_decodeURI,             1,0, JS_TypeHandlerString),
-    JS_FN_TYPE(js_encodeURI_str,          str_encodeURI,             1,0, JS_TypeHandlerString),
-    JS_FN_TYPE(js_decodeURIComponent_str, str_decodeURI_Component,   1,0, JS_TypeHandlerString),
-    JS_FN_TYPE(js_encodeURIComponent_str, str_encodeURI_Component,   1,0, JS_TypeHandlerString),
+    JS_FN(js_decodeURI_str,          str_decodeURI,             1,0),
+    JS_FN(js_encodeURI_str,          str_encodeURI,             1,0),
+    JS_FN(js_decodeURIComponent_str, str_decodeURI_Component,   1,0),
+    JS_FN(js_encodeURIComponent_str, str_encodeURI_Component,   1,0),
 
     JS_FS_END
 };
 
 jschar      js_empty_ucstr[]  = {0};
 JSSubString js_EmptySubString = {0, js_empty_ucstr};
 
 #define STRING_ELEMENT_ATTRS (JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
@@ -1054,17 +1054,16 @@ js_str_charCodeAt(JSContext *cx, uintN a
     if (!chars)
         return false;
 
     vp->setInt32(chars[i]);
     return true;
 
 out_of_range:
     vp->setDouble(js_NaN);
-    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.
@@ -3118,86 +3117,67 @@ js_String_getelem(JSContext* cx, JSStrin
     return JSAtom::getUnitStringForElement(cx, str, size_t(i));
 }
 #endif
 
 JS_DEFINE_TRCINFO_1(str_concat,
     (3, (extern, STRING_RETRY, js_ConcatStrings, CONTEXT, THIS_STRING, STRING,
          1, nanojit::ACCSET_NONE)))
 
-static void type_StringSplit(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    TypeCallsite *site = Valueify(jssite);
-
-    if (!site->script->hasGlobal()) {
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-        return;
-    }
-
-    if (site->isNew)
-        site->returnTypes->addType(cx, TYPE_UNKNOWN);
-
-    TypeObject *type = site->getInitObject(cx, true);
-    if (!type)
-        return;
-
-    site->returnTypes->addType(cx, (jstype) type);
-}
-
 static JSFunctionSpec string_methods[] = {
 #if JS_HAS_TOSOURCE
-    JS_FN_TYPE("quote",             str_quote,             0,JSFUN_GENERIC_NATIVE, JS_TypeHandlerString),
-    JS_FN_TYPE(js_toSource_str,     str_toSource,          0,0, JS_TypeHandlerString),
+    JS_FN("quote",             str_quote,             0,JSFUN_GENERIC_NATIVE),
+    JS_FN(js_toSource_str,     str_toSource,          0,0),
 #endif
 
     /* Java-like methods. */
-    JS_FN_TYPE(js_toString_str,     js_str_toString,       0,0, JS_TypeHandlerString),
-    JS_FN_TYPE(js_valueOf_str,      js_str_toString,       0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("substring",         str_substring,         2,JSFUN_GENERIC_NATIVE, JS_TypeHandlerString),
-    JS_FN_TYPE("toLowerCase",       str_toLowerCase,       0,JSFUN_GENERIC_NATIVE, JS_TypeHandlerString),
-    JS_FN_TYPE("toUpperCase",       str_toUpperCase,       0,JSFUN_GENERIC_NATIVE, JS_TypeHandlerString),
-    JS_FN_TYPE("charAt",            js_str_charAt,         1,JSFUN_GENERIC_NATIVE, JS_TypeHandlerString),
-    JS_FN_TYPE("charCodeAt",        js_str_charCodeAt,     1,JSFUN_GENERIC_NATIVE, JS_TypeHandlerInt),
-    JS_FN_TYPE("indexOf",           str_indexOf,           1,JSFUN_GENERIC_NATIVE, JS_TypeHandlerInt),
-    JS_FN_TYPE("lastIndexOf",       str_lastIndexOf,       1,JSFUN_GENERIC_NATIVE, JS_TypeHandlerInt),
-    JS_FN_TYPE("trim",              str_trim,              0,JSFUN_GENERIC_NATIVE, JS_TypeHandlerString),
-    JS_FN_TYPE("trimLeft",          str_trimLeft,          0,JSFUN_GENERIC_NATIVE, JS_TypeHandlerString),
-    JS_FN_TYPE("trimRight",         str_trimRight,         0,JSFUN_GENERIC_NATIVE, JS_TypeHandlerString),
-    JS_FN_TYPE("toLocaleLowerCase", str_toLocaleLowerCase, 0,JSFUN_GENERIC_NATIVE, JS_TypeHandlerString),
-    JS_FN_TYPE("toLocaleUpperCase", str_toLocaleUpperCase, 0,JSFUN_GENERIC_NATIVE, JS_TypeHandlerString),
-    JS_FN_TYPE("localeCompare",     str_localeCompare,     1,JSFUN_GENERIC_NATIVE, JS_TypeHandlerInt),
+    JS_FN(js_toString_str,     js_str_toString,       0,0),
+    JS_FN(js_valueOf_str,      js_str_toString,       0,0),
+    JS_FN("substring",         str_substring,         2,JSFUN_GENERIC_NATIVE),
+    JS_FN("toLowerCase",       str_toLowerCase,       0,JSFUN_GENERIC_NATIVE),
+    JS_FN("toUpperCase",       str_toUpperCase,       0,JSFUN_GENERIC_NATIVE),
+    JS_FN("charAt",            js_str_charAt,         1,JSFUN_GENERIC_NATIVE),
+    JS_FN("charCodeAt",        js_str_charCodeAt,     1,JSFUN_GENERIC_NATIVE),
+    JS_FN("indexOf",           str_indexOf,           1,JSFUN_GENERIC_NATIVE),
+    JS_FN("lastIndexOf",       str_lastIndexOf,       1,JSFUN_GENERIC_NATIVE),
+    JS_FN("trim",              str_trim,              0,JSFUN_GENERIC_NATIVE),
+    JS_FN("trimLeft",          str_trimLeft,          0,JSFUN_GENERIC_NATIVE),
+    JS_FN("trimRight",         str_trimRight,         0,JSFUN_GENERIC_NATIVE),
+    JS_FN("toLocaleLowerCase", str_toLocaleLowerCase, 0,JSFUN_GENERIC_NATIVE),
+    JS_FN("toLocaleUpperCase", str_toLocaleUpperCase, 0,JSFUN_GENERIC_NATIVE),
+    JS_FN("localeCompare",     str_localeCompare,     1,JSFUN_GENERIC_NATIVE),
 
     /* Perl-ish methods (search is actually Python-esque). */
-    JS_FN_TYPE("match",             str_match,             1,JSFUN_GENERIC_NATIVE, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("search",            str_search,            1,JSFUN_GENERIC_NATIVE, JS_TypeHandlerInt),
-    JS_FN_TYPE("replace",           str_replace,           2,JSFUN_GENERIC_NATIVE, JS_TypeHandlerString),
-    JS_FN_TYPE("split",             str_split,             2,JSFUN_GENERIC_NATIVE, type_StringSplit),
+    JS_FN("match",             str_match,             1,JSFUN_GENERIC_NATIVE),
+    JS_FN("search",            str_search,            1,JSFUN_GENERIC_NATIVE),
+    JS_FN("replace",           str_replace,           2,JSFUN_GENERIC_NATIVE),
+    JS_FN("split",             str_split,             2,JSFUN_GENERIC_NATIVE),
 #if JS_HAS_PERL_SUBSTR
-    JS_FN_TYPE("substr",            str_substr,            2,JSFUN_GENERIC_NATIVE, JS_TypeHandlerString),
+    JS_FN("substr",            str_substr,            2,JSFUN_GENERIC_NATIVE),
 #endif
 
     /* Python-esque sequence methods. */
-    JS_TN("concat",                 str_concat,            1,JSFUN_GENERIC_NATIVE, &str_concat_trcinfo, JS_TypeHandlerString),
-    JS_FN_TYPE("slice",             str_slice,             2,JSFUN_GENERIC_NATIVE, JS_TypeHandlerString),
+    JS_TN("concat",            str_concat,            1,JSFUN_GENERIC_NATIVE, &str_concat_trcinfo),
+    JS_FN("slice",             str_slice,             2,JSFUN_GENERIC_NATIVE),
 
     /* HTML string methods. */
 #if JS_HAS_STR_HTML_HELPERS
-    JS_FN_TYPE("bold",              str_bold,              0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("italics",           str_italics,           0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("fixed",             str_fixed,             0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("fontsize",          str_fontsize,          1,0, JS_TypeHandlerString),
-    JS_FN_TYPE("fontcolor",         str_fontcolor,         1,0, JS_TypeHandlerString),
-    JS_FN_TYPE("link",              str_link,              1,0, JS_TypeHandlerString),
-    JS_FN_TYPE("anchor",            str_anchor,            1,0, JS_TypeHandlerString),
-    JS_FN_TYPE("strike",            str_strike,            0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("small",             str_small,             0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("big",               str_big,               0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("blink",             str_blink,             0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("sup",               str_sup,               0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("sub",               str_sub,               0,0, JS_TypeHandlerString),
+    JS_FN("bold",              str_bold,              0,0),
+    JS_FN("italics",           str_italics,           0,0),
+    JS_FN("fixed",             str_fixed,             0,0),
+    JS_FN("fontsize",          str_fontsize,          1,0),
+    JS_FN("fontcolor",         str_fontcolor,         1,0),
+    JS_FN("link",              str_link,              1,0),
+    JS_FN("anchor",            str_anchor,            1,0),
+    JS_FN("strike",            str_strike,            0,0),
+    JS_FN("small",             str_small,             0,0),
+    JS_FN("big",               str_big,               0,0),
+    JS_FN("blink",             str_blink,             0,0),
+    JS_FN("sup",               str_sup,               0,0),
+    JS_FN("sub",               str_sub,               0,0),
 #endif
 
     JS_FS_END
 };
 
 /*
  * Set up some tools to make it easier to generate large tables. After constant
  * folding, for each n, Rn(0) is the comma-separated list R(0), R(1), ..., R(2^n-1).
@@ -3464,28 +3444,20 @@ String_fromCharCode(JSContext* cx, int32
     return js_NewStringCopyN(cx, &c, 1);
 }
 #endif
 
 JS_DEFINE_TRCINFO_1(str_fromCharCode,
     (2, (static, STRING_RETRY, String_fromCharCode, CONTEXT, INT32, 1, nanojit::ACCSET_NONE)))
 
 static JSFunctionSpec string_static_methods[] = {
-    JS_TN("fromCharCode", str_fromCharCode, 1, 0, &str_fromCharCode_trcinfo, JS_TypeHandlerString),
+    JS_TN("fromCharCode", str_fromCharCode, 1, 0, &str_fromCharCode_trcinfo),
     JS_FS_END
 };
 
-static void type_NewString(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite)
-{
-    if (Valueify(jssite)->isNew)
-        JS_TypeHandlerNew(cx, jsfun, jssite);
-    else
-        JS_TypeHandlerString(cx, jsfun, jssite);
-}
-
 const Shape *
 StringObject::assignInitialShape(JSContext *cx)
 {
     JS_ASSERT(!cx->compartment->initialStringShape);
     JS_ASSERT(nativeEmpty());
 
     return addDataProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom),
                            LENGTH_SLOT, JSPROP_PERMANENT | JSPROP_READONLY);
@@ -3513,18 +3485,17 @@ js_InitStringClass(JSContext *cx, JSObje
     if (!protoType || !proto->setTypeAndUniqueShape(cx, protoType))
         return NULL;
 
     if (!proto->asString()->init(cx, cx->runtime->emptyString))
         return NULL;
 
     /* Now create the String function. */
     JSAtom *atom = CLASS_ATOM(cx, String);
-    JSFunction *ctor = js_NewFunction(cx, NULL, js_String, 1, JSFUN_CONSTRUCTOR, global, atom,
-                                      type_NewString, js_String_str);
+    JSFunction *ctor = js_NewFunction(cx, NULL, js_String, 1, JSFUN_CONSTRUCTOR, global, atom);
     if (!ctor)
         return NULL;
 
     /* String creates string objects. */
     FUN_CLASP(ctor) = &js_StringClass;
 
     /* Define String.prototype and String.prototype.constructor. */
     if (!js_SetClassPrototype(cx, ctor, proto, JSPROP_PERMANENT | JSPROP_READONLY))
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -1465,18 +1465,18 @@ JSPropertySpec TypedArray::jsprops[] = {
 };
 
 /*
  * TypedArray boilerplate
  */
 
 #define IMPL_TYPED_ARRAY_STATICS(_typedArray)                                  \
 template<> JSFunctionSpec _typedArray::jsfuncs[] = {                           \
-    JS_FN_TYPE("subarray", _typedArray::fun_subarray, 2, 0, JS_TypeHandlerThis), \
-    JS_FN_TYPE("set",   _typedArray::fun_set,   2, 0, JS_TypeHandlerVoid),     \
+    JS_FN("subarray", _typedArray::fun_subarray, 2, 0),                            \
+    JS_FN("set", _typedArray::fun_set, 2, 0),                                  \
     JS_FS_END                                                                  \
 }
 
 #define IMPL_TYPED_ARRAY_SLOW_CLASS(_typedArray)                               \
 {                                                                              \
     #_typedArray,                                                              \
     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray),     \
     PropertyStub,         /* addProperty */                                    \
@@ -1524,17 +1524,16 @@ template<> JSFunctionSpec _typedArray::j
     }                                                                          \
 }
 
 #define INIT_TYPED_ARRAY_CLASS(_typedArray,_type)                              \
 do {                                                                           \
     proto = js_InitClass(cx, obj, NULL,                                        \
                          &TypedArray::slowClasses[TypedArray::_type],          \
                          _typedArray::class_constructor, 3,                    \
-                         JS_TypeHandlerNew,                                    \
                          _typedArray::jsprops,                                 \
                          _typedArray::jsfuncs,                                 \
                          NULL, NULL);                                          \
     if (!proto)                                                                \
         return NULL;                                                           \
     AddTypePropertyId(cx, proto->getType(), JSID_VOID, types::TYPE_INT32);     \
     if (_typedArray::ArrayElementTypeMayBeDouble())                            \
         AddTypePropertyId(cx, proto->getType(), JSID_VOID, types::TYPE_DOUBLE); \
@@ -1596,17 +1595,17 @@ js_InitTypedArrayClasses(JSContext *cx, 
     if (!js_GetClassObject(cx, obj, JSProto_ArrayBuffer, &stop))
         return NULL;
     if (stop)
         return stop;
 
     JSObject *proto;
 
     proto = js_InitClass(cx, obj, NULL, &ArrayBuffer::jsclass,
-                         ArrayBuffer::class_constructor, 1, JS_TypeHandlerNew,
+                         ArrayBuffer::class_constructor, 1,
                          ArrayBuffer::jsprops, NULL, NULL, NULL);
     if (!proto)
         return NULL;
 
     INIT_TYPED_ARRAY_CLASS(Int8Array,TYPE_INT8);
     INIT_TYPED_ARRAY_CLASS(Uint8Array,TYPE_UINT8);
     INIT_TYPED_ARRAY_CLASS(Int16Array,TYPE_INT16);
     INIT_TYPED_ARRAY_CLASS(Uint16Array,TYPE_UINT16);
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -332,27 +332,27 @@ Class WeakMap::jsclass = {
     NULL,                 /* xdrObject   */
     NULL,                 /* hasInstance */
     WeakMap::mark
 };
 
 }
 
 JSFunctionSpec WeakMap::methods[] = {
-    JS_FN_TYPE("has",    WeakMap::has, 1, 0,     JS_TypeHandlerBool),
-    JS_FN_TYPE("get",    WeakMap::get, 2, 0,     JS_TypeHandlerDynamic),
-    JS_FN_TYPE("delete", WeakMap::delete_, 1, 0, JS_TypeHandlerBool),
-    JS_FN_TYPE("set",    WeakMap::set, 2, 0,     JS_TypeHandlerVoid),
+    JS_FN("has",    WeakMap::has, 1, 0),
+    JS_FN("get",    WeakMap::get, 2, 0),
+    JS_FN("delete", WeakMap::delete_, 1, 0),
+    JS_FN("set",    WeakMap::set, 2, 0),
     JS_FS_END
 };
 
 JSObject *
 js_InitWeakMapClass(JSContext *cx, JSObject *obj)
 {
     JSObject *proto = js_InitClass(cx, obj, NULL, &WeakMap::jsclass, WeakMap::construct, 0,
-                                   JS_TypeHandlerNew, NULL, WeakMap::methods, NULL, NULL);
+                                   NULL, WeakMap::methods, NULL, NULL);
     if (!proto)
         return NULL;
 
     proto->setPrivate(NULL);
 
     return proto;
 }
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -637,17 +637,17 @@ Reify(JSContext *cx, JSCompartment *orig
     return VectorToValueIterator(cx, obj, ni->flags, keys, vp); 
 }
 
 bool
 JSCrossCompartmentWrapper::iterate(JSContext *cx, JSObject *wrapper, uintN flags, Value *vp)
 {
     /* Notify type inference of custom iterators, see GetCustomIterator. */
     if (!(flags & JSITER_OWNONLY))
-        types::MarkTypeCallerUnexpected(cx, types::TYPE_UNKNOWN);
+        types::MarkIteratorUnknown(cx);
 
     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
@@ -7113,24 +7113,24 @@ js_GetXMLObject(JSContext *cx, JSXML *xm
         return NULL;
     xml->object = obj;
     return obj;
 }
 
 JSObject *
 js_InitNamespaceClass(JSContext *cx, JSObject *obj)
 {
-    return js_InitClass(cx, obj, NULL, &js_NamespaceClass, Namespace, 2, JS_TypeHandlerDynamic,
+    return js_InitClass(cx, obj, NULL, &js_NamespaceClass, Namespace, 2,
                         namespace_props, namespace_methods, NULL, NULL);
 }
 
 JSObject *
 js_InitQNameClass(JSContext *cx, JSObject *obj)
 {
-    JSObject *proto = js_InitClass(cx, obj, NULL, &js_QNameClass, QName, 2, JS_TypeHandlerDynamic,
+    JSObject *proto = js_InitClass(cx, obj, NULL, &js_QNameClass, QName, 2,
                                    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;
@@ -7146,17 +7146,17 @@ js_InitXMLClass(JSContext *cx, JSObject 
     JSObject *proto, *pobj;
     JSFunction *fun;
     JSXML *xml;
     JSProperty *prop;
     Shape *shape;
     jsval cval, vp[3];
 
     /* Define the XML class constructor and prototype. */
-    proto = js_InitClass(cx, obj, NULL, &js_XMLClass, XML, 1, JS_TypeHandlerDynamic,
+    proto = js_InitClass(cx, obj, NULL, &js_XMLClass, XML, 1,
                          NULL, xml_methods,
                          xml_static_props, xml_static_methods);
     if (!proto)
         return NULL;
 
     /* Define the isXMLName function. */
     if (!JS_DefineFunction(cx, obj, js_isXMLName_str, xml_isXMLName, 1, 0))
         return NULL;
--- a/js/src/methodjit/BaseAssembler.h
+++ b/js/src/methodjit/BaseAssembler.h
@@ -875,16 +875,86 @@ static const JSC::MacroAssembler::Regist
     static uint32 maskAddress(Address address) {
         return Registers::maskReg(address.base);
     }
 
     static uint32 maskAddress(BaseIndex address) {
         return Registers::maskReg(address.base) |
                Registers::maskReg(address.index);
     }
+
+    /*
+     * Generate code testing whether an in memory value at address has a type
+     * in the specified set. Updates mismatches with any failure jumps. Assumes
+     * no data registers are live.
+     */
+    bool generateTypeCheck(JSContext *cx, Address address,
+                           types::TypeSet *types, Vector<Jump> *mismatches)
+    {
+        if (types->unknown())
+            return true;
+
+        Vector<Jump> matches(cx);
+
+        if (types->hasType(types::TYPE_DOUBLE)) {
+            /* Type sets containing double also contain int. */
+            if (!matches.append(testNumber(Assembler::Equal, address)))
+                return false;
+        } else if (types->hasType(types::TYPE_INT32)) {
+            if (!matches.append(testInt32(Assembler::Equal, address)))
+                return false;
+        }
+
+        if (types->hasType(types::TYPE_UNDEFINED)) {
+            if (!matches.append(testUndefined(Assembler::Equal, address)))
+                return false;
+        }
+
+        if (types->hasType(types::TYPE_BOOLEAN)) {
+            if (!matches.append(testBoolean(Assembler::Equal, address)))
+                return false;
+        }
+
+        if (types->hasType(types::TYPE_STRING)) {
+            if (!matches.append(testString(Assembler::Equal, address)))
+                return false;
+        }
+
+        if (types->hasType(types::TYPE_NULL)) {
+            if (!matches.append(testNull(Assembler::Equal, address)))
+                return false;
+        }
+
+        unsigned count = types->getObjectCount();
+        if (count != 0) {
+            if (!mismatches->append(testObject(Assembler::NotEqual, address)))
+                return false;
+            Registers tempRegs(Registers::AvailRegs);
+            RegisterID reg = tempRegs.takeAnyReg().reg();
+
+            loadPayload(address, reg);
+            loadPtr(Address(reg, offsetof(JSObject, type)), reg);
+
+            for (unsigned i = 0; i < count; i++) {
+                types::TypeObject *object = types->getObject(i);
+                if (object) {
+                    if (!matches.append(branchPtr(Assembler::Equal, reg, ImmPtr(object))))
+                        return false;
+                }
+            }
+        }
+
+        if (!mismatches->append(jump()))
+            return false;
+
+        for (unsigned i = 0; i < matches.length(); i++)
+            matches[i].linkTo(label(), this);
+
+        return true;
+    }
 };
 
 /* Return f<true> if the script is strict mode code, f<false> otherwise. */
 #define STRICT_VARIANT(f)                                                     \
     (FunctionTemplateConditional(script->strictModeCode,                      \
                                  f<true>, f<false>))
 
 /* Save some typing. */
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -250,17 +250,17 @@ mjit::Compiler::scanInlineCalls(uint32 i
         if (!code)
             continue;
 
         /* :XXX: Not yet inlining 'new' calls. */
         if (JSOp(*pc) != JSOP_CALL)
             continue;
 
         /* Not inlining at monitored call sites or those with type barriers. */
-        if (code->monitoredTypes || analysis->typeBarriers(pc) != NULL)
+        if (code->monitoredTypes || code->monitoredTypesReturn || analysis->typeBarriers(pc) != NULL)
             continue;
 
         uint32 argc = GET_ARGC(pc);
         types::TypeSet *calleeTypes = analysis->poppedTypes(pc, argc + 1);
 
         if (calleeTypes->getKnownTypeTag(cx) != JSVAL_TYPE_OBJECT)
             continue;
 
@@ -3203,21 +3203,20 @@ mjit::Compiler::recompileCheckHelper()
     stubcc.linkExit(jump, Uses(0));
     stubcc.leave();
 
     OOL_STUBCALL(stubs::RecompileForInline, REJOIN_RESUME);
     stubcc.rejoin(Changes(0));
 }
 
 void
-mjit::Compiler::addReturnSite(bool ool)
+mjit::Compiler::addReturnSite()
 {
-    Assembler &masm = ool ? stubcc.masm : this->masm;
     InternalCallSite site(masm.distanceOf(masm.label()), a->inlineIndex, PC,
-                          REJOIN_SCRIPTED, ool);
+                          REJOIN_SCRIPTED, false);
     addCallSite(site);
     masm.loadPtr(Address(JSFrameReg, StackFrame::offsetOfPrev()), JSFrameReg);
 }
 
 void
 mjit::Compiler::emitUncachedCall(uint32 argc, bool callingNew)
 {
     CallPatchInfo callPatch;
@@ -3235,27 +3234,33 @@ mjit::Compiler::emitUncachedCall(uint32 
     masm.loadPtr(FrameAddress(offsetof(VMFrame, regs.sp)), JSFrameReg);
     callPatch.hasFastNcode = true;
     callPatch.fastNcodePatch =
         masm.storePtrWithPatch(ImmPtr(NULL),
                                Address(JSFrameReg, StackFrame::offsetOfNcode()));
 
     masm.jump(r0);
     callPatch.joinPoint = masm.label();
-    addReturnSite(false /* ool */);
+    addReturnSite();
 
     frame.popn(argc + 2);
 
     frame.takeReg(JSReturnReg_Type);
     frame.takeReg(JSReturnReg_Data);
     frame.pushRegs(JSReturnReg_Type, JSReturnReg_Data, knownPushedType(0));
 
+    BarrierState barrier = testBarrier(JSReturnReg_Type, JSReturnReg_Data,
+                                       /* testUndefined = */ false,
+                                       /* testReturn = */ true);
+
     stubcc.linkExitDirect(notCompiled, stubcc.masm.label());
     stubcc.rejoin(Changes(1));
     callPatches.append(callPatch);
+
+    finishBarrier(barrier, REJOIN_FALLTHROUGH, 0);
 }
 
 static bool
 IsLowerableFunCallOrApply(jsbytecode *pc)
 {
 #ifdef JS_MONOIC
     return (*pc == JSOP_FUNCALL && GET_ARGC(pc) >= 1) ||
            (*pc == JSOP_FUNAPPLY && GET_ARGC(pc) == 2);
@@ -3635,33 +3640,37 @@ mjit::Compiler::inlineCallHelper(uint32 
 
     InlineFrameAssembler inlFrame(masm, callIC, flags);
     callPatch.hasFastNcode = true;
     callPatch.fastNcodePatch = inlFrame.assemble(NULL);
 
     callIC.hotJump = masm.jump();
     callIC.joinPoint = callPatch.joinPoint = masm.label();
     callIC.callIndex = callSites.length();
-    addReturnSite(false /* ool */);
+    addReturnSite();
     if (lowerFunCallOrApply)
         uncachedCallPatch.joinPoint = callIC.joinPoint;
 
     /*
      * We've placed hotJump, joinPoint and hotPathLabel, and no other labels are located by offset
      * in the in-line path so we can check the IC space now.
      */
     CHECK_IC_SPACE();
 
     JSValueType type = knownPushedType(0);
 
     frame.popn(speculatedArgc + 2);
     frame.takeReg(JSReturnReg_Type);
     frame.takeReg(JSReturnReg_Data);
     frame.pushRegs(JSReturnReg_Type, JSReturnReg_Data, type);
 
+    BarrierState barrier = testBarrier(JSReturnReg_Type, JSReturnReg_Data,
+                                       /* testUndefined = */ false,
+                                       /* testReturn = */ true);
+
     /*
      * Now that the frame state is set, generate the rejoin path. Note that, if
      * lowerFunCallOrApply, we cannot just call 'stubcc.rejoin' since the return
      * value has been placed at vp[1] which is not the stack address associated
      * with frame.peek(-1).
      */
     callIC.slowJoinPoint = stubcc.masm.label();
     rejoin1.linkTo(callIC.slowJoinPoint, &stubcc.masm);
@@ -3676,16 +3685,18 @@ mjit::Compiler::inlineCallHelper(uint32 
     if (lowerFunCallOrApply)
         stubcc.crossJump(uncachedCallSlowRejoin, masm.label());
 
     callICs.append(callIC);
     callPatches.append(callPatch);
     if (lowerFunCallOrApply)
         callPatches.append(uncachedCallPatch);
 
+    finishBarrier(barrier, REJOIN_FALLTHROUGH, 0);
+
     applyTricks = NoApplyTricks;
     return true;
 #endif
 }
 
 CompileStatus
 mjit::Compiler::callArrayBuiltin(uint32 argc, bool callingNew)
 {
@@ -7142,17 +7153,17 @@ mjit::Compiler::monitored(jsbytecode *pc
 bool
 mjit::Compiler::hasTypeBarriers(jsbytecode *pc)
 {
     if (!cx->typeInferenceEnabled())
         return false;
 
 #if 0
     /* Stress test. */
-    return types::CanHaveReadBarrier(pc);
+    return js_CodeSpec[*pc].format & JOF_TYPESET;
 #endif
 
     return analysis->typeBarriers(pc) != NULL;
 }
 
 void
 mjit::Compiler::pushSyncedEntry(uint32 pushed)
 {
@@ -7321,35 +7332,51 @@ mjit::Compiler::addTypeTest(types::TypeS
 
     for (unsigned i = 0; i < matches.length(); i++)
         matches[i].linkTo(masm.label(), &masm);
 
     return mismatch;
 }
 
 mjit::Compiler::BarrierState
-mjit::Compiler::testBarrier(RegisterID typeReg, RegisterID dataReg, bool testUndefined)
+mjit::Compiler::testBarrier(RegisterID typeReg, RegisterID dataReg,
+                            bool testUndefined, bool testReturn)
 {
     BarrierState state;
     state.typeReg = typeReg;
     state.dataReg = dataReg;
 
-    if (!hasTypeBarriers(PC)) {
+    if (!cx->typeInferenceEnabled() || !(js_CodeSpec[*PC].format & JOF_TYPESET))
+        return state;
+
+    types::TypeSet *types = script->types.bytecodeTypes(PC);
+    if (types->unknown()) {
+        /*
+         * If the result of this opcode is already unknown, there is no way for
+         * a type barrier to fail.
+         */
+        return state;
+    }
+
+    if (testReturn) {
+        JS_ASSERT(!testUndefined);
+        if (!analysis->getCode(PC).monitoredTypesReturn)
+            return state;
+    } else if (!hasTypeBarriers(PC)) {
         if (testUndefined)
             state.jump.setJump(masm.testUndefined(Assembler::Equal, typeReg));
         return state;
     }
 
 #if 0
     /* Stress test. */
     state.jump.setJump(masm.testInt32(Assembler::NotEqual, typeReg));
     return state;
 #endif
 
-    types::TypeSet *types = script->types.bytecodeTypes(PC);
     types->addFreeze(cx);
 
     /* Cannot have type barriers when the result of the operation is already unknown. */
     JS_ASSERT(!types->unknown());
 
     state.jump = trySingleTypeTest(types, typeReg);
     if (!state.jump.isSet())
         state.jump.setJump(addTypeTest(types, typeReg, dataReg));
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -480,17 +480,17 @@ class Compiler : public BaseCompiler
     ~Compiler();
 
     CompileStatus compile();
 
     Label getLabel() { return masm.label(); }
     bool knownJump(jsbytecode *pc);
     Label labelOf(jsbytecode *target, uint32 inlineIndex);
     void addCallSite(const InternalCallSite &callSite);
-    void addReturnSite(bool ool);
+    void addReturnSite();
     void inlineStubCall(void *stub, RejoinState rejoin);
 
     bool debugMode() { return debugMode_; }
     bool inlining() { return inlining_; }
 
     jsbytecode *outerPC() {
         if (a == outer)
             return PC;
@@ -558,17 +558,17 @@ class Compiler : public BaseCompiler
         RegisterID dataReg;
     };
 
     MaybeJump trySingleTypeTest(types::TypeSet *types, RegisterID typeReg);
     Jump addTypeTest(types::TypeSet *types, RegisterID typeReg, RegisterID dataReg);
     BarrierState pushAddressMaybeBarrier(Address address, JSValueType type, bool reuseBase,
                                          bool testUndefined = false);
     BarrierState testBarrier(RegisterID typeReg, RegisterID dataReg,
-                             bool testUndefined = false);
+                             bool testUndefined = false, bool testReturn = false);
     void finishBarrier(const BarrierState &barrier, RejoinState rejoin, uint32 which);
 
     /* Non-emitting helpers. */
     void pushSyncedEntry(uint32 pushed);
     uint32 fullAtomIndex(jsbytecode *pc);
     bool jumpInScript(Jump j, jsbytecode *pc);
     bool compareTwoValues(JSContext *cx, JSOp op, const Value &lhs, const Value &rhs);
     bool canUseApplyTricks();
--- a/js/src/methodjit/FastBuiltins.cpp
+++ b/js/src/methodjit/FastBuiltins.cpp
@@ -478,16 +478,19 @@ mjit::Compiler::inlineNativeFunction(uin
                            : JSVAL_TYPE_UNKNOWN;
 
     if (argc == 0) {
         if (native == js::array_pop && thisType == JSVAL_TYPE_OBJECT) {
             /*
              * Only inline pop() on dense arrays which have never been used in
              * an iterator --- when popping elements we don't account for
              * suppressing deleted properties in active iterators.
+             *
+             * Constraints propagating properties directly into the result
+             * type set are generated by TypeConstraintCall during inference.
              */
             if (!thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY |
                                            types::OBJECT_FLAG_ITERATED) &&
                 !arrayPrototypeHasIndexedProperty()) {
                 bool packed = !thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY);
                 return compileArrayPop(thisValue, packed);
             }
         }
@@ -517,17 +520,22 @@ mjit::Compiler::inlineNativeFunction(uin
         if (native == js_str_charCodeAt && argType == JSVAL_TYPE_INT32 &&
             thisType == JSVAL_TYPE_STRING && type == JSVAL_TYPE_INT32) {
             return compileGetChar(thisValue, arg, GetCharCode);
         }
         if (native == js_str_charAt && argType == JSVAL_TYPE_INT32 &&
             thisType == JSVAL_TYPE_STRING && type == JSVAL_TYPE_STRING) {
             return compileGetChar(thisValue, arg, GetChar);
         }
-        if (native == js::array_push && thisType == JSVAL_TYPE_OBJECT) {
+        if (native == js::array_push &&
+            thisType == JSVAL_TYPE_OBJECT && type == JSVAL_TYPE_INT32) {
+            /*
+             * Constraints propagating properties into the 'this' object are
+             * generated by TypeConstraintCall during inference.
+             */
             if (!thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
                 !arrayPrototypeHasIndexedProperty()) {
                 return compileArrayPush(thisValue, arg);
             }
         }
     } else if (argc == 2) {
         FrameEntry *arg1 = frame.peek(-2);
         FrameEntry *arg2 = frame.peek(-1);
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -183,26 +183,29 @@ InlineReturn(VMFrame &f)
 
 void JS_FASTCALL
 stubs::SlowCall(VMFrame &f, uint32 argc)
 {
     Value *vp = f.regs.sp - (argc + 2);
 
     if (!Invoke(f.cx, InvokeArgsAlreadyOnTheStack(argc, vp)))
         THROW();
+
+    f.script()->types.monitor(f.cx, f.pc(), vp[0]);
 }
 
 void JS_FASTCALL
 stubs::SlowNew(VMFrame &f, uint32 argc)
 {
-    JSContext *cx = f.cx;
     Value *vp = f.regs.sp - (argc + 2);
 
-    if (!InvokeConstructor(cx, InvokeArgsAlreadyOnTheStack(argc, vp)))
+    if (!InvokeConstructor(f.cx, InvokeArgsAlreadyOnTheStack(argc, vp)))
         THROW();
+
+    f.script()->types.monitor(f.cx, f.pc(), vp[0]);
 }
 
 /*
  * This function must only be called after the early prologue, since it depends
  * on fp->exec.fun.
  */
 static inline void
 RemovePartialFrame(JSContext *cx, StackFrame *fp)
@@ -383,16 +386,18 @@ UncachedInlineCall(VMFrame &f, uint32 fl
             return true;
         }
     }
 
     /* Otherwise, run newscript in the interpreter. */
     bool ok = !!Interpret(cx, cx->fp());
     InlineReturn(f);
 
+    f.script()->types.monitor(cx, f.pc(), vp[0]);
+
     *pret = NULL;
     return ok;
 }
 
 void * JS_FASTCALL
 stubs::UncachedNew(VMFrame &f, uint32 argc)
 {
     UncachedCallResult ucr;
@@ -409,16 +414,17 @@ stubs::UncachedNewHelper(VMFrame &f, uin
     /* Try to do a fast inline call before the general Invoke path. */
     if (IsFunctionObject(*vp, &ucr->fun) && ucr->fun->isInterpretedConstructor()) {
         ucr->callee = &vp->toObject();
         if (!UncachedInlineCall(f, StackFrame::CONSTRUCTING, &ucr->codeAddr, &ucr->unjittable, argc))
             THROW();
     } else {
         if (!InvokeConstructor(cx, InvokeArgsAlreadyOnTheStack(argc, vp)))
             THROW();
+        f.script()->types.monitor(cx, f.pc(), vp[0]);
     }
 }
 
 void * JS_FASTCALL
 stubs::UncachedCall(VMFrame &f, uint32 argc)
 {
     UncachedCallResult ucr;
     UncachedCallHelper(f, argc, &ucr);
@@ -435,17 +441,17 @@ stubs::Eval(VMFrame &f, uint32 argc)
             THROW();
         return;
     }
 
     JS_ASSERT(f.fp() == f.cx->fp());
     if (!DirectEval(f.cx, CallArgsFromVp(argc, vp)))
         THROW();
 
-    f.regs.sp = vp + 1;
+    f.script()->types.monitor(f.cx, f.pc(), vp[0]);
 }
 
 void
 stubs::UncachedCallHelper(VMFrame &f, uint32 argc, UncachedCallResult *ucr)
 {
     ucr->init();
 
     JSContext *cx = f.cx;
@@ -459,23 +465,25 @@ stubs::UncachedCallHelper(VMFrame &f, ui
             if (!UncachedInlineCall(f, 0, &ucr->codeAddr, &ucr->unjittable, argc))
                 THROW();
             return;
         }
 
         if (ucr->fun->isNative()) {
             if (!CallJSNative(cx, ucr->fun->u.n.native, argc, vp))
                 THROW();
+            f.script()->types.monitor(cx, f.pc(), vp[0]);
             return;
         }
     }
 
     if (!Invoke(f.cx, InvokeArgsAlreadyOnTheStack(argc, vp)))
         THROW();
 
+    f.script()->types.monitor(cx, f.pc(), vp[0]);
     return;
 }
 
 void JS_FASTCALL
 stubs::PutActivationObjects(VMFrame &f)
 {
     JS_ASSERT(f.fp()->hasCallObj() || f.fp()->hasArgsObj());
     f.fp()->putActivationObjects();
@@ -1373,16 +1381,17 @@ js_InternalInterpret(void *returnData, v
         RemoveOrphanedNative(cx, fp);
         if (rejoin == REJOIN_NATIVE_LOWERED) {
             /*
              * Lowered natives return like other native calls, but store their
              * return values in the 'this' value's slot.
              */
             nextsp[-1] = nextsp[0];
         }
+        script->types.monitor(cx, pc, nextsp[-1]);
         f.regs.pc = nextpc;
         break;
       }
 
       case REJOIN_PUSH_BOOLEAN:
         nextsp[-1].setBoolean(returnReg != NULL);
         f.regs.pc = nextpc;
         break;
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -804,25 +804,25 @@ class CallCompiler : public BaseCompiler
         return true;
     }
 
     bool generateNativeStub()
     {
         JITScript *jit = f.jit();
 
         /* Snapshot the frameDepth before SplatApplyArgs modifies it. */
-        uintN initialFrameDepth = f.regs.sp - f.regs.fp()->slots();
+        uintN initialFrameDepth = f.regs.sp - f.fp()->slots();
 
         /*
          * SplatApplyArgs has not been called, so we call it here before
          * potentially touching f.u.call.dynamicArgc.
          */
         Value *vp;
         if (ic.frameSize.isStatic()) {
-            JS_ASSERT(f.regs.sp - f.regs.fp()->slots() == (int)ic.frameSize.staticLocalSlots());
+            JS_ASSERT(f.regs.sp - f.fp()->slots() == (int)ic.frameSize.staticLocalSlots());
             vp = f.regs.sp - (2 + ic.frameSize.staticArgc());
         } else {
             JS_ASSERT(!f.regs.inlined());
             JS_ASSERT(*f.regs.pc == JSOP_FUNAPPLY && GET_ARGC(f.regs.pc) == 2);
             if (!ic::SplatApplyArgs(f))       /* updates regs.sp */
                 THROWV(true);
             vp = f.regs.sp - (2 + f.u.call.dynamicArgc);
         }
@@ -838,16 +838,18 @@ class CallCompiler : public BaseCompiler
         if (callingNew)
             vp[1].setMagicWithObjectOrNullPayload(NULL);
 
         RecompilationMonitor monitor(cx);
 
         if (!CallJSNative(cx, fun->u.n.native, ic.frameSize.getArgc(f), vp))
             THROWV(true);
 
+        f.script()->types.monitor(f.cx, f.pc(), vp[0]);
+
         /* Don't touch the IC if the call triggered a recompilation. */
         if (monitor.recompiled())
             return true;
 
         /* Right now, take slow-path for IC misses or multiple stubs. */
         if (ic.fastGuardedNative || ic.hasJsFunCheck)
             return true;
 
@@ -914,40 +916,34 @@ class CallCompiler : public BaseCompiler
         /* Grab cx. */
 #ifdef JS_CPU_X86
         RegisterID cxReg = tempRegs.takeAnyReg().reg();
 #else
         RegisterID cxReg = Registers::ArgReg0;
 #endif
         masm.loadPtr(FrameAddress(offsetof(VMFrame, cx)), cxReg);
 
-        /* Compute vp. */
+        /*
+         * Compute vp. This will always be at the same offset from fp for a
+         * given callsite, regardless of any dynamically computed argc,
+         * so get that offset from the active call.
+         */
 #ifdef JS_CPU_X86
         RegisterID vpReg = t0;
 #else
         RegisterID vpReg = Registers::ArgReg2;
 #endif
+        uint32 vpOffset = (uint32) ((char *) vp - (char *) f.fp());
+        masm.addPtr(Imm32(vpOffset), JSFrameReg, vpReg);
+
+        /* Compute argc. */
         MaybeRegisterID argcReg;
-        if (ic.frameSize.isStatic()) {
-            uint32 vpOffset = sizeof(StackFrame) + (vp - f.regs.fp()->slots()) * sizeof(Value);
-            masm.addPtr(Imm32(vpOffset), JSFrameReg, vpReg);
-        } else {
+        if (!ic.frameSize.isStatic()) {
             argcReg = tempRegs.takeAnyReg().reg();
             masm.load32(FrameAddress(offsetof(VMFrame, u.call.dynamicArgc)), argcReg.reg());
-            masm.loadPtr(FrameAddress(offsetof(VMFrame, regs.sp)), vpReg);
-
-            /* vpOff = (argc + 2) * sizeof(Value) */
-            RegisterID vpOff = tempRegs.takeAnyReg().reg();
-            masm.move(argcReg.reg(), vpOff);
-            masm.add32(Imm32(2), vpOff);  /* callee, this */
-            JS_STATIC_ASSERT(sizeof(Value) == 8);
-            masm.lshift32(Imm32(3), vpOff);
-            masm.subPtr(vpOff, vpReg);
-
-            tempRegs.putReg(vpOff);
         }
 
         /* Mark vp[1] as magic for |new|. */
         if (callingNew) {
             Value v;
             v.setMagicWithObjectOrNullPayload(NULL);
             masm.storeValue(v, Address(vpReg, sizeof(Value)));
         }
@@ -969,35 +965,72 @@ class CallCompiler : public BaseCompiler
          * break inferred types for the call's result and any subsequent test,
          * as RegExp.exec has a type handler with unknown result.
          */
         if (native == js_regexp_exec && !CallResultEscapes(f.pc()))
             native = js_regexp_test;
 
         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, native), false);
 
-        if (cx->typeInferenceEnabled())
-            masm.storePtr(ImmPtr(NULL), FrameAddress(offsetof(VMFrame, stubRejoin)));
-
         /* Reload fp, which may have been clobbered by restoreStackBase(). */
         masm.loadPtr(FrameAddress(VMFrame::offsetOfFp), JSFrameReg);
 
         Jump hasException = masm.branchTest32(Assembler::Zero, Registers::ReturnReg,
                                               Registers::ReturnReg);
 
+        Vector<Jump> mismatches(f.cx);
+        if (cx->typeInferenceEnabled()) {
+            /*
+             * Test the result of this native against the known result type
+             * set for the call. We don't assume knowledge about the types that
+             * natives can return, except when generating specialized paths in
+             * FastBuiltins. We don't need to record dependencies on the result
+             * type set, as the compiler will already have done so when making
+             * the call IC.
+             */
+            Address address(JSFrameReg, vpOffset);
+            types::TypeSet *types = f.script()->types.bytecodeTypes(f.pc());
+            if (!masm.generateTypeCheck(f.cx, address, types, &mismatches))
+                THROWV(true);
+
+            /*
+             * Can no longer trigger recompilation in this stub, clear the stub
+             * rejoin on the VMFrame.
+             */
+            masm.storePtr(ImmPtr(NULL), FrameAddress(offsetof(VMFrame, stubRejoin)));
+        }
+
+        /*
+         * The final jump is a indirect on x64, so that we'll always be able
+         * to repatch it to the interpoline later.
+         */
+        Label finished = masm.label();
 #ifdef JS_CPU_X64
         void *slowJoin = ic.slowPathStart.labelAtOffset(ic.slowJoinOffset).executableAddress();
         DataLabelPtr done = masm.moveWithPatch(ImmPtr(slowJoin), Registers::ValueReg);
         masm.jump(Registers::ValueReg);
 #else
         Jump done = masm.jump();
 #endif
 
+        /* Generate a call for type check failures on the native result. */
+        if (!mismatches.empty()) {
+            for (unsigned i = 0; i < mismatches.length(); i++)
+                mismatches[i].linkTo(masm.label(), &masm);
+            masm.addPtr(Imm32(vpOffset), JSFrameReg, Registers::ArgReg1);
+            masm.fallibleVMCall(true, JS_FUNC_TO_DATA_PTR(void *, stubs::TypeBarrierReturn),
+                                f.regs.pc, NULL, initialFrameDepth);
+            masm.storePtr(ImmPtr(NULL), FrameAddress(offsetof(VMFrame, stubRejoin)));
+            masm.jump().linkTo(finished, &masm);
+        }
+
         /* Move JaegerThrowpoline into register for very far jump on x64. */
         hasException.linkTo(masm.label(), &masm);
+        if (cx->typeInferenceEnabled())
+            masm.storePtr(ImmPtr(NULL), FrameAddress(offsetof(VMFrame, stubRejoin)));
         masm.throwInJIT();
 
         LinkerHelper linker(masm);
         JSC::ExecutablePool *ep = poolForSize(linker, CallICInfo::Pool_NativeStub);
         if (!ep)
             THROWV(true);
 
         ic.fastGuardedNative = obj;
@@ -1245,82 +1278,16 @@ ic::SplatApplyArgs(VMFrame &f)
     /* Steps 7-8. */
     if (!GetElements(cx, aobj, n, f.regs.sp - n))
         THROWV(false);
 
     f.u.call.dynamicArgc = n;
     return true;
 }
 
-static bool
-GenerateTypeCheck(JSContext *cx, Assembler &masm, Address address,
-                  types::TypeSet *types, Vector<Jump> *mismatches)
-{
-    if (types->unknown())
-        return true;
-
-    Vector<Jump> matches(cx);
-
-    if (types->hasType(types::TYPE_DOUBLE)) {
-        /* Type sets containing double also contain int. */
-        if (!matches.append(masm.testNumber(Assembler::Equal, address)))
-            return false;
-    } else if (types->hasType(types::TYPE_INT32)) {
-        if (!matches.append(masm.testInt32(Assembler::Equal, address)))
-            return false;
-    }
-
-    if (types->hasType(types::TYPE_UNDEFINED)) {
-        if (!matches.append(masm.testUndefined(Assembler::Equal, address)))
-            return false;
-    }
-
-    if (types->hasType(types::TYPE_BOOLEAN)) {
-        if (!matches.append(masm.testBoolean(Assembler::Equal, address)))
-            return false;
-    }
-
-    if (types->hasType(types::TYPE_STRING)) {
-        if (!matches.append(masm.testString(Assembler::Equal, address)))
-            return false;
-    }
-
-    if (types->hasType(types::TYPE_NULL)) {
-        if (!matches.append(masm.testNull(Assembler::Equal, address)))
-            return false;
-    }
-
-    unsigned count = types->getObjectCount();
-    if (count != 0) {
-        if (!mismatches->append(masm.testObject(Assembler::NotEqual, address)))
-            return false;
-        Registers tempRegs(Registers::AvailRegs);
-        RegisterID reg = tempRegs.takeAnyReg().reg();
-
-        masm.loadPayload(address, reg);
-        masm.loadPtr(Address(reg, offsetof(JSObject, type)), reg);
-
-        for (unsigned i = 0; i < count; i++) {
-            types::TypeObject *object = types->getObject(i);
-            if (object) {
-                if (!matches.append(masm.branchPtr(Assembler::Equal, reg, ImmPtr(object))))
-                    return false;
-            }
-        }
-    }
-
-    if (!mismatches->append(masm.jump()))
-        return false;
-
-    for (unsigned i = 0; i < matches.length(); i++)
-        matches[i].linkTo(masm.label(), &masm);
-
-    return true;
-}
-
 void
 ic::GenerateArgumentCheckStub(VMFrame &f)
 {
     JS_ASSERT(f.cx->typeInferenceEnabled());
 
     JITScript *jit = f.jit();
     StackFrame *fp = f.fp();
     JSFunction *fun = fp->fun();
@@ -1329,23 +1296,23 @@ ic::GenerateArgumentCheckStub(VMFrame &f
     if (jit->argsCheckPool)
         jit->resetArgsCheck();
 
     Assembler masm;
     Vector<Jump> mismatches(f.cx);
 
     if (!f.fp()->isConstructing()) {
         Address address(JSFrameReg, StackFrame::offsetOfThis(fun));
-        if (!GenerateTypeCheck(f.cx, masm, address, script->types.thisTypes(), &mismatches))
+        if (!masm.generateTypeCheck(f.cx, address, script->types.thisTypes(), &mismatches))
             return;
     }
 
     for (unsigned i = 0; i < fun->nargs; i++) {
         Address address(JSFrameReg, StackFrame::offsetOfFormalArg(fun, i));
-        if (!GenerateTypeCheck(f.cx, masm, address, script->types.argTypes(i), &mismatches))
+        if (!masm.generateTypeCheck(f.cx, address, script->types.argTypes(i), &mismatches))
             return;
     }
 
     Jump done = masm.jump();
 
     LinkerHelper linker(masm);
     JSC::ExecutablePool *ep = linker.init(f.cx);
     if (!ep)
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -2781,16 +2781,26 @@ stubs::TypeBarrierHelper(VMFrame &f, uin
     if (f.script()->hasAnalysis() && f.script()->analysis(f.cx)->ranInference()) {
         AutoEnterTypeInference enter(f.cx);
         f.script()->analysis(f.cx)->breakTypeBarriers(f.cx, f.pc() - f.script()->code, false);
     }
 
     f.script()->types.monitor(f.cx, f.pc(), result);
 }
 
+/*
+ * Variant of TypeBarrierHelper for checking types after making a native call.
+ * The stack is already correct, and no fixup should be performed.
+ */
+void JS_FASTCALL
+stubs::TypeBarrierReturn(VMFrame &f, Value *vp)
+{
+    f.script()->types.monitor(f.cx, f.pc(), vp[0]);
+}
+
 void JS_FASTCALL
 stubs::NegZeroHelper(VMFrame &f)
 {
     f.regs.sp[-1].setDouble(-0.0);
     f.script()->types.monitorOverflow(f.cx, f.pc());
 }
 
 void JS_FASTCALL
--- a/js/src/methodjit/StubCalls.h
+++ b/js/src/methodjit/StubCalls.h
@@ -215,16 +215,17 @@ void JS_FASTCALL FastInstanceOf(VMFrame 
 void JS_FASTCALL ArgCnt(VMFrame &f);
 void JS_FASTCALL Unbrand(VMFrame &f);
 
 /*
  * Helper for triggering recompilation should a name read miss a type barrier,
  * produce undefined or -0.
  */
 void JS_FASTCALL TypeBarrierHelper(VMFrame &f, uint32 which);
+void JS_FASTCALL TypeBarrierReturn(VMFrame &f, Value *vp);
 void JS_FASTCALL NegZeroHelper(VMFrame &f);
 
 void JS_FASTCALL CallPropSwap(VMFrame &f);
 void JS_FASTCALL CheckArgumentTypes(VMFrame &f);
 
 #ifdef DEBUG
 void JS_FASTCALL AssertArgumentTypes(VMFrame &f);
 #endif
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -4816,117 +4816,117 @@ ParseLegacyJSON(JSContext *cx, uintN arg
     size_t length;
     const jschar *chars = JS_GetStringCharsAndLength(cx, str, &length);
     if (!chars)
         return false;
     return js::ParseJSONWithReviver(cx, chars, length, js::NullValue(), js::Valueify(vp), LEGACY);
 }
 
 static JSFunctionSpec shell_functions[] = {
-    JS_FN_TYPE("version",        Version,        0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("revertVersion",  RevertVersion,  0,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("options",        Options,        0,0, JS_TypeHandlerString),
-    JS_FN_TYPE("load",           Load,           1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("evaluate",       Evaluate,       1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("run",            Run,            1,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("readline",       ReadLine,       0,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("print",          Print,          0,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("putstr",         PutStr,         0,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("dateNow",        Now,            0,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("help",           Help,           0,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("quit",           Quit,           0,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("assertEq",       AssertEq,       2,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("assertJit",      AssertJit,      0,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("gc",             ::GC,           0,0, JS_TypeHandlerString),
+    JS_FN("version",        Version,        0,0),
+    JS_FN("revertVersion",  RevertVersion,  0,0),
+    JS_FN("options",        Options,        0,0),
+    JS_FN("load",           Load,           1,0),
+    JS_FN("evaluate",       Evaluate,       1,0),
+    JS_FN("run",            Run,            1,0),
+    JS_FN("readline",       ReadLine,       0,0),
+    JS_FN("print",          Print,          0,0),
+    JS_FN("putstr",         PutStr,         0,0),
+    JS_FN("dateNow",        Now,            0,0),
+    JS_FN("help",           Help,           0,0),
+    JS_FN("quit",           Quit,           0,0),
+    JS_FN("assertEq",       AssertEq,       2,0),
+    JS_FN("assertJit",      AssertJit,      0,0),
+    JS_FN("gc",             ::GC,           0,0),
 #ifdef JS_GCMETER
-    JS_FN_TYPE("gcstats",        GCStats,        0,0, JS_TypeHandlerVoid),
+    JS_FN("gcstats",        GCStats,        0,0),
 #endif
-    JS_FN_TYPE("gcparam",        GCParameter,    2,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("countHeap",      CountHeap,      0,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("makeFinalizeObserver", MakeFinalizeObserver, 0,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("finalizeCount",  FinalizeCount,  0,0, JS_TypeHandlerInt),
+    JS_FN("gcparam",        GCParameter,    2,0),
+    JS_FN("countHeap",      CountHeap,      0,0),
+    JS_FN("makeFinalizeObserver", MakeFinalizeObserver, 0,0),
+    JS_FN("finalizeCount",  FinalizeCount, 0,0),
 #ifdef JS_GC_ZEAL
-    JS_FN_TYPE("gczeal",         GCZeal,         2,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("schedulegc",     ScheduleGC,     1,0, JS_TypeHandlerVoid),
+    JS_FN("gczeal",         GCZeal,         2,0),
+    JS_FN("schedulegc",     ScheduleGC,     1,0),
 #endif
-    JS_FN_TYPE("internalConst",  InternalConst,  1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("setDebug",       SetDebug,       1,0, JS_TypeHandlerBool),
-    JS_FN_TYPE("setDebuggerHandler", SetDebuggerHandler, 1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("setThrowHook",   SetThrowHook,   1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("trap",           Trap,           3,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("untrap",         Untrap,         2,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("line2pc",        LineToPC,       0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("pc2line",        PCToLine,       0,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("stringsAreUTF8", StringsAreUTF8, 0,0, JS_TypeHandlerBool),
-    JS_FN_TYPE("testUTF8",       TestUTF8,       1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("throwError",     ThrowError,     0,0, JS_TypeHandlerVoid),
+    JS_FN("internalConst",  InternalConst,  1,0),
+    JS_FN("setDebug",       SetDebug,       1,0),
+    JS_FN("setDebuggerHandler", SetDebuggerHandler, 1,0),
+    JS_FN("setThrowHook",   SetThrowHook,   1,0),
+    JS_FN("trap",           Trap,           3,0),
+    JS_FN("untrap",         Untrap,         2,0),
+    JS_FN("line2pc",        LineToPC,       0,0),
+    JS_FN("pc2line",        PCToLine,       0,0),
+    JS_FN("stringsAreUTF8", StringsAreUTF8, 0,0),
+    JS_FN("testUTF8",       TestUTF8,       1,0),
+    JS_FN("throwError",     ThrowError,     0,0),
 #ifdef DEBUG
-    JS_FN_TYPE("disassemble",    DisassembleToString, 1,0, JS_TypeHandlerString),
-    JS_FN_TYPE("dis",            Disassemble,    1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("disfile",        DisassFile,     1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("dissrc",         DisassWithSrc,  1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("dumpHeap",       DumpHeap,       0,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("dumpObject",     DumpObject,     1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("notes",          Notes,          1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("tracing",        Tracing,        0,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("stats",          DumpStats,      1,0, JS_TypeHandlerVoid),
+    JS_FN("disassemble",    DisassembleToString, 1,0),
+    JS_FN("dis",            Disassemble,    1,0),
+    JS_FN("disfile",        DisassFile,     1,0),
+    JS_FN("dissrc",         DisassWithSrc,  1,0),
+    JS_FN("dumpHeap",       DumpHeap,       0,0),
+    JS_FN("dumpObject",     DumpObject,     1,0),
+    JS_FN("notes",          Notes,          1,0),
+    JS_FN("tracing",        Tracing,        0,0),
+    JS_FN("stats",          DumpStats,      1,0),
 #endif
 #ifdef TEST_CVTARGS
-    JS_FN_TYPE("cvtargs",        ConvertArgs,    0,0, JS_TypeHandlerVoid),
+    JS_FN("cvtargs",        ConvertArgs,    0,0),
 #endif
-    JS_FN_TYPE("build",          BuildDate,      0,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("clear",          Clear,          0,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("intern",         Intern,         1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("clone",          Clone,          1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("getpda",         GetPDA,         1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("getslx",         GetSLX,         1,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("toint32",        ToInt32,        1,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("evalcx",         EvalInContext,  1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("evalInFrame",    EvalInFrame,    2,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("shapeOf",        ShapeOf,        1,0, JS_TypeHandlerInt),
-    JS_FN_TYPE("resolver",       Resolver,       1,0, JS_TypeHandlerDynamic),
+    JS_FN("build",          BuildDate,      0,0),
+    JS_FN("clear",          Clear,          0,0),
+    JS_FN("intern",         Intern,         1,0),
+    JS_FN("clone",          Clone,          1,0),
+    JS_FN("getpda",         GetPDA,         1,0),
+    JS_FN("getslx",         GetSLX,         1,0),
+    JS_FN("toint32",        ToInt32,        1,0),
+    JS_FN("evalcx",         EvalInContext,  1,0),
+    JS_FN("evalInFrame",    EvalInFrame,    2,0),
+    JS_FN("shapeOf",        ShapeOf,        1,0),
+    JS_FN("resolver",       Resolver,       1,0),
 #ifdef MOZ_CALLGRIND
-    JS_FN_TYPE("startCallgrind", js_StartCallgrind,  0,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("stopCallgrind",  js_StopCallgrind,   0,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("dumpCallgrind",  js_DumpCallgrind,   1,0, JS_TypeHandlerVoid),
+    JS_FN("startCallgrind", js_StartCallgrind,  0,0),
+    JS_FN("stopCallgrind",  js_StopCallgrind,   0,0),
+    JS_FN("dumpCallgrind",  js_DumpCallgrind,   1,0),
 #endif
 #ifdef MOZ_VTUNE
-    JS_FN_TYPE("startVtune",     js_StartVtune,    1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("stopVtune",      js_StopVtune,     0,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("pauseVtune",     js_PauseVtune,    0,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("resumeVtune",    js_ResumeVtune,   0,0, JS_TypeHandlerVoid),
+    JS_FN("startVtune",     js_StartVtune,    1,0),
+    JS_FN("stopVtune",      js_StopVtune,     0,0),
+    JS_FN("pauseVtune",     js_PauseVtune,    0,0),
+    JS_FN("resumeVtune",    js_ResumeVtune,   0,0),
 #endif
 #ifdef MOZ_TRACEVIS
-    JS_FN_TYPE("startTraceVis",  StartTraceVisNative, 1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("stopTraceVis",   StopTraceVisNative,  0,0, JS_TypeHandlerVoid),
+    JS_FN("startTraceVis",  StartTraceVisNative, 1,0),
+    JS_FN("stopTraceVis",   StopTraceVisNative,  0,0),
 #endif
 #ifdef DEBUG
-    JS_FN_TYPE("arrayInfo",      js_ArrayInfo,   1,0, JS_TypeHandlerVoid),
+    JS_FN("arrayInfo",      js_ArrayInfo,   1,0),
 #endif
 #ifdef JS_THREADSAFE
-    JS_FN_TYPE("sleep",          Sleep_fn,       1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("scatter",        Scatter,        1,0, JS_TypeHandlerDynamic),
+    JS_FN("sleep",          Sleep_fn,       1,0),
+    JS_FN("scatter",        Scatter,        1,0),
 #endif
-    JS_FN_TYPE("snarf",          Snarf,          0,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("read",           Snarf,          0,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("compile",        Compile,        1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("parse",          Parse,          1,0, JS_TypeHandlerVoid),
-    JS_FN_TYPE("timeout",        Timeout,        1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("elapsed",        Elapsed,        0,0, JS_TypeHandlerFloat),
-    JS_FN_TYPE("parent",         Parent,         1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("wrap",           Wrap,           1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("serialize",      Serialize,      1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("deserialize",    Deserialize,    1,0, JS_TypeHandlerDynamic),
+    JS_FN("snarf",          Snarf,          0,0),
+    JS_FN("read",           Snarf,          0,0),
+    JS_FN("compile",        Compile,        1,0),
+    JS_FN("parse",          Parse,          1,0),
+    JS_FN("timeout",        Timeout,        1,0),
+    JS_FN("elapsed",        Elapsed,        0,0),
+    JS_FN("parent",         Parent,         1,0),
+    JS_FN("wrap",           Wrap,           1,0),
+    JS_FN("serialize",      Serialize,      1,0),
+    JS_FN("deserialize",    Deserialize,    1,0),
 #ifdef JS_METHODJIT
-    JS_FN_TYPE("mjitcodestats",  MJitCodeStats,  0,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("mjitdatastats",  MJitDataStats,  0,0, JS_TypeHandlerDynamic),
+    JS_FN("mjitcodestats",  MJitCodeStats,  0,0),
+    JS_FN("mjitdatastats",  MJitDataStats,  0,0),
 #endif
-    JS_FN_TYPE("stringstats",    StringStats,    0,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("newGlobal",      NewGlobal,      1,0, JS_TypeHandlerDynamic),
-    JS_FN_TYPE("parseLegacyJSON",ParseLegacyJSON,1,0, JS_TypeHandlerDynamic),
+    JS_FN("stringstats",    StringStats,    0,0),
+    JS_FN("newGlobal",      NewGlobal,      1,0),
+    JS_FN("parseLegacyJSON",ParseLegacyJSON,1,0),
     JS_FS_END
 };
 
 static const char shell_help_header[] =
 "Command                  Description\n"
 "=======                  ===========\n";
 
 static const char *const shell_help_messages[] = {
@@ -5310,17 +5310,17 @@ its_bindMethod(JSContext *cx, uintN argc
 
     if (!JS_DefinePropertyById(cx, thisobj, id, *vp, NULL, NULL, JSPROP_ENUMERATE))
         return JS_FALSE;
 
     return JS_SetParent(cx, method, thisobj);
 }
 
 static JSFunctionSpec its_methods[] = {
-    {"bindMethod",      its_bindMethod, 2,0, JS_TypeHandlerDynamic},
+    {"bindMethod",      its_bindMethod, 2,0},
     {NULL,NULL,0,0}
 };
 
 #ifdef JSD_LOWLEVEL_SOURCE
 /*
  * This facilitates sending source to JSD (the debugger system) in the shell
  * where the source is loaded using the JSFILE hack in jsscan. The function
  * below is used as a callback for the jsdbgapi JS_SetSourceHandler hook.