Backed out changeset f682453c06d0. Failing scriptaculous unit tests, doesn't build on windows or mac ppc.
authorRobert Sayre <sayrer@gmail.com>
Thu, 11 Dec 2008 20:43:32 -0800
changeset 23059 5a26ec73cf0d3c0c8862a83e3be7f2c6ff3161f7
parent 23058 f682453c06d06ac83b76a0f58fb868f76da37201
child 23060 5f64a0d18e530c6389c11c649086bb7ba72524e6
push id4346
push userrsayre@mozilla.com
push dateFri, 26 Dec 2008 01:26:36 +0000
treeherdermozilla-central@8eb5a5b83a93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.2a1pre
backs outf682453c06d06ac83b76a0f58fb868f76da37201
Backed out changeset f682453c06d0. Failing scriptaculous unit tests, doesn't build on windows or mac ppc.
js/src/Makefile.in
js/src/builtins.tbl
js/src/imacro_asm.js.in
js/src/imacros.c.out
js/src/imacros.jsasm
js/src/js.cpp
js/src/jsbuiltins.cpp
js/src/jsemit.cpp
js/src/jsinterp.cpp
js/src/jsobj.cpp
js/src/jsopcode.tbl
js/src/jstracer.cpp
js/src/jstracer.h
js/src/trace-test.js
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -651,16 +651,8 @@ host_jsoplengen.$(OBJ_SUFFIX): jsopcode.
 ifdef HAVE_DTRACE
 $(CURDIR)/javascript-trace.h: $(srcdir)/javascript-trace.d
 	dtrace -h -s $(srcdir)/javascript-trace.d -o javascript-trace.h.in
 	sed 's/if _DTRACE_VERSION/ifdef INCLUDE_MOZILLA_DTRACE/' \
 	    javascript-trace.h.in > javascript-trace.h
 
 $(CPPSRCS:%.cpp=%.$(OBJ_SUFFIX)): $(CURDIR)/javascript-trace.h
 endif
-
-imacro_asm.js: imacro_asm.js.in
-	$(CC) -c -x c -E -P -I$(srcdir) $? > $@
-
-GARBAGE += imacro_asm.js
-
-%.c.out: %.jsasm $(PROGRAM) imacro_asm.js
-	./$(PROGRAM) imacro_asm.js $< > $@
--- a/js/src/builtins.tbl
+++ b/js/src/builtins.tbl
@@ -89,9 +89,10 @@ BUILTIN2(extern, OBJECT,    js_FastNewOb
 BUILTIN3(extern, BOOL,      js_AddProperty, CONTEXT, OBJECT, SCOPEPROP,         0, 0)
 BUILTIN3(extern, BOOL,      js_HasNamedProperty, CONTEXT, OBJECT, STRING,       0, 0)
 BUILTIN3(extern, BOOL,      js_HasNamedPropertyInt32, CONTEXT, OBJECT, INT32,   0, 0)
 BUILTIN3(extern, JSVAL,     js_CallGetter, CONTEXT, OBJECT, SCOPEPROP,          0, 0)
 BUILTIN2(extern, STRING,    js_TypeOfObject, CONTEXT, OBJECT,                   1, 1)
 BUILTIN2(extern, STRING,    js_TypeOfBoolean, CONTEXT, INT32,                   1, 1)
 BUILTIN2(extern, DOUBLE,    js_BooleanOrUndefinedToNumber, CONTEXT, INT32,      1, 1)
 BUILTIN2(extern, STRING,    js_BooleanOrUndefinedToString, CONTEXT, INT32,      1, 1)
+BUILTIN2(extern, STRING,    js_ObjectToString, CONTEXT, OBJECT,                 0, 0)
 BUILTIN1(extern, OBJECT,    js_Arguments, CONTEXT,                              0, 0)
deleted file mode 100644
--- a/js/src/imacro_asm.js.in
+++ /dev/null
@@ -1,308 +0,0 @@
-/* vim: set sw=4 ts=8 et tw=78 ft=javascript: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the TraceMonkey IMacro Assembler.
- *
- * The Initial Developer of the Original Code is
- * Brendan Eich <brendan@mozilla.org>.
- * Portions created by the Initial Developer are Copyright (C) 2008
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/*
- * An imacro (interpreter-macro) assembler in JS, with a light dusting of C
- * pre-processor. We depend on the snarf function from the js shell, defined
- * originally for the Narcissus metacircular evaluator, now unconditionally
- * compiled into the shell.
- *
- * Filename suffix conventions, used by Makefile.in rules:
- *   .js.in     C-pre-processed JS source
- *   .jsasm     SpiderMonkey JS assembly source, which could be input to other
- *              assemblers than imacro_asm.js, hence the generic suffix!
- *   .c.out     C source output by imacro_asm.js
- */
-
-#define ASSERT(cond)    _ASSERT(cond, #cond)
-
-function _ASSERT(cond, message) {
-    if (!cond)
-        throw new Error("Assertion failed: " + message);
-}
-
-const js_arguments_str  = "arguments";
-const js_new_str        = "new";
-const js_typeof_str     = "typeof";
-const js_void_str       = "void";
-const js_null_str       = "null";
-const js_this_str       = "this";
-const js_false_str      = "false";
-const js_true_str       = "true";
-const js_throw_str      = "throw";
-const js_in_str         = "in";
-const js_instanceof_str = "instanceof";
-const js_getter_str     = "getter";
-const js_setter_str     = "setter";
-
-#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format)               \
-    {jsop: #op, opcode: val, opname: name, opsrc: token, oplen: length,       \
-     pops: nuses, pushes: ndefs, precedence: prec, flags: #format},
-
-const NULL = null;
-
-const opinfo = [
-#include "jsopcode.tbl"
-];
-
-const opname2info = {};
-const jsop2opcode = {};
-
-for (let i = 0; i < opinfo.length; i++) {
-    let info = opinfo[i];
-    ASSERT(info.opcode == i);
-    opname2info[info.opname] = info;
-    jsop2opcode[info.jsop] = info.opcode;
-}
-
-function formatoffset(n, w) {
-    let s = n.toString();
-    while (s.length < w)
-        s = ' ' + s;
-    return s;
-}
-
-function immediate(op) {
-    let info = op.info;
-    if (info.flags.indexOf("JOF_ATOM") >= 0) {
-        if (/^(?:void|object|function|string|number|boolean)$/.test(op.imm1))
-            return "0, COMMON_TYPE_ATOM_INDEX(JSTYPE_" + op.imm1.toUpperCase() + ")";
-        return "0, COMMON_ATOM_INDEX(" + op.imm1 + ")";
-    }
-    if (info.flags.indexOf("JOF_JUMP") >= 0)
-        return ((op.target >> 8) & 0xff) + ", " + (op.target & 0xff);
-    if (info.flags.indexOf("JOF_UINT16") >= 0)
-        return ((op.imm1 & 0xff00) >> 8) + ", " + (op.imm1 & 0xff);
-    throw new Error(info.jsop + " format not yet implemented");
-}
-
-/*
- * Syntax (spaces are significant only to delimit tokens):
- *
- *   Assembly   ::= (Directive? '\n')*
- *   Directive  ::= (name ':')? Operation
- *   Operation  ::= opname Operands?
- *   Operands   ::= Operand (',' Operand)*
- *   Operand    ::= name | number
- *
- * We simplify given line structure and the maximum of one immediate operand,
- * by parsing using split and regexps.
- *
- * Pseudo-ops start with . and include .igroup and .imacro, terminated by .end.
- * .imacro must nest in .igroup, neither nests in itself. See imacros.jsasm for
- * examples.
- */
-function assemble(filename) {
-    let igroup = null, imacro = null;
-    let opcode2extra = [];
-
-    print("/* GENERATED BY imacro_asm.js from " + filename + " -- DO NOT EDIT!!! */");
-
-    let s = snarf(filename);
-    let a = s.split('\n');
-    for (let i = 0; i < a.length; i++) {
-        if (/^\s*(?:#.*)?$/.test(a[i]))
-            continue;
-        let m = /(?:(\w+):)?\s*(\.?\w+)(?:\s+(\w+))?(?:\s+([\w-]+))?(?:\s*(?:#.*))?$/.exec(a[i]);
-        if (!m)
-            throw new Error(a[i]);
-
-        let [, label, opname, imm1, imm2] = m;
-
-        if (opname[0] == '.') {
-            if (label)
-                throw new Error("invalid label " + label + " before " + opname);
-
-            switch (opname) {
-              case ".igroup":
-                if (!imm1)
-                    throw new Error("missing .igroup name");
-                if (igroup)
-                    throw new Error("nested .igroup " + imm1);
-                let oprange = imm2.match(/^(\w+)(?:-(\w+))?$/);
-                if (!oprange)
-                    throw new Error("invalid igroup operator range " + imm2);
-                let firstop = jsop2opcode[oprange[1]];
-                igroup = {
-                    name:    imm1,
-                    firstop: firstop,
-                    lastop:  oprange[2] ? jsop2opcode[oprange[2]] : firstop,
-                    imacros: []
-                };
-                break;
-
-              case ".imacro":
-                if (!igroup)
-                    throw new Error(".imacro outside of .igroup");
-                if (!imm1)
-                    throw new Error("missing .imacro name");
-                if (imacro)
-                    throw new Error("nested .imacro " + imm1);
-                imacro = {
-                    name:      imm1,
-                    offset:    0,
-                    code:      [],
-                    labeldefs: {},
-                    labelrefs: {}
-                };
-                break;
-
-              case ".end":
-                if (!imacro) {
-                    if (!igroup)
-                        throw new Error(".end without prior .igroup or .imacro");
-                    if (imm1 && (imm1 != igroup.name || imm2))
-                        throw new Error(".igroup/.end name mismatch");
-
-                    let maxdepth = 0;
-
-                    print("static struct {");
-                    for (let j = 0; j < igroup.imacros.length; j++) {
-                        imacro = igroup.imacros[j];
-                        print("    jsbytecode " + imacro.name + "[" + imacro.offset + "];");
-                    }
-                    print("} " + igroup.name + "_imacros = {");
-
-                    for (let j = 0; j < igroup.imacros.length; j++) {
-                        let depth = 0;
-
-                        imacro = igroup.imacros[j];
-                        print("    {");
-                        for (let k = 0; k < imacro.code.length; k++) {
-                            let op = imacro.code[k];
-
-                            print("/*" + formatoffset(op.offset,2) + "*/  " + op.info.jsop +
-                                  (op.imm1 ? ", " + immediate(op) : "") + ",");
-
-                            depth -= (op.info.pops < 0) ? 2 + op.imm1 : op.info.pops;
-                            depth += op.info.pushes;
-                            if (depth > maxdepth)
-                                maxdepth = depth;
-                        }
-                        print("    },");
-                    }
-
-                    print("};");
-
-                    let opcode = igroup.firstop;
-                    let oplast = igroup.lastop;
-                    do {
-                        opcode2extra[opcode] = maxdepth;
-                    } while (opcode++ != oplast);
-                    igroup = null;
-                } else {
-                    ASSERT(igroup);
-
-                    if (imm1 && imm1 != imacro.name)
-                        throw new Error(".imacro/.end name mismatch");
-
-                    // Backpatch the forward references to labels that must now be defined.
-                    for (label in imacro.labelrefs) {
-                        if (!imacro.labelrefs.hasOwnProperty(label))
-                            continue;
-                        if (!imacro.labeldefs.hasOwnProperty(label))
-                            throw new Error("label " + label + " used but not defined");
-                        let link = imacro.labelrefs[label];
-                        ASSERT(link >= 0);
-                        for (;;) {
-                            let op = imacro.code[link];
-                            ASSERT(op);
-                            ASSERT(op.hasOwnProperty('target'));
-                            let next = op.target;
-                            op.target = imacro.labeldefs[label] - op.offset;
-                            if (next < 0)
-                                break;
-                            link = next;
-                        }
-                    }
-
-                    igroup.imacros.push(imacro);
-                }
-                imacro = null;
-                break;
-
-              default:
-                throw new Error("unknown pseudo-op " + opname);
-            }
-            continue;
-        }
-
-        if (!opname2info.hasOwnProperty(opname))
-            throw new Error("unknown opcode " + opname + (label ? " (label " + label + ")" : ""));
-
-        let info = opname2info[opname];
-        if (info.oplen == -1)
-            throw new Error("unimplemented opcode " + opname);
-
-        if (label) {
-            if (!imacro)
-                throw new Error("label " + label + " outside of .imacro");
-            imacro.labeldefs[label] = imacro.offset;
-        }
-
-        let op = {offset: imacro.offset, info: info, imm1: imm1, imm2: imm2};
-        if (info.flags.indexOf("JOF_JUMP") >= 0) {
-            if (imacro.labeldefs.hasOwnProperty(imm1)) {
-                // Backward reference can be resolved right away, no backpatching needed.
-                op.target = imacro.labeldefs[imm1] - op.offset;
-            } else {
-                // Link op into the .target-linked backpatch chain at labelrefs[imm1].
-                // The linked list terminates with a -1 sentinel.
-                op.target = imacro.labelrefs.hasOwnProperty(imm1) ? imacro.labelrefs[imm1] : -1;
-                imacro.labelrefs[imm1] = imacro.code.length;
-            }
-        }
-
-        imacro.code.push(op);
-        imacro.offset += info.oplen;
-    }
-
-    print("uint8 js_opcode2extra[JSOP_LIMIT] = {");
-    for (let i = 0; i < opinfo.length; i++) {
-        print("    " + ((i in opcode2extra) ? opcode2extra[i] : "0") +
-              ",  /* " + opinfo[i].jsop + " */");
-    }
-    print("};");
-}
-
-for (let i = 0; i < arguments.length; i++) {
-    try {
-        assemble(arguments[i]);
-    } catch (e) {
-        print(e.name + ": " + e.message + "\n" + e.stack);
-    }
-}
deleted file mode 100644
--- a/js/src/imacros.c.out
+++ /dev/null
@@ -1,407 +0,0 @@
-/* GENERATED BY imacro_asm.js from ../imacros.jsasm -- DO NOT EDIT!!! */
-static struct {
-    jsbytecode any_obj[36];
-    jsbytecode obj_any[38];
-    jsbytecode obj_obj[72];
-} binary_imacros = {
-    {
-/* 0*/  JSOP_DUP,
-/* 1*/  JSOP_DUP,
-/* 2*/  JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
-/* 5*/  JSOP_IFPRIMTOP, 0, 16,
-/* 8*/  JSOP_SWAP,
-/* 9*/  JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
-/*12*/  JSOP_CALL, 0, 1,
-/*15*/  JSOP_IFPRIMTOP, 0, 17,
-/*18*/  JSOP_GOTO, 0, 4,
-/*21*/  JSOP_POP,
-/*22*/  JSOP_POP,
-/*23*/  JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
-/*26*/  JSOP_CALL, 0, 0,
-/*29*/  JSOP_GOTO, 0, 5,
-/*32*/  JSOP_SWAP,
-/*33*/  JSOP_POP,
-/*34*/  JSOP_IMACOP,
-/*35*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_SWAP,
-/* 1*/  JSOP_DUP,
-/* 2*/  JSOP_DUP,
-/* 3*/  JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
-/* 6*/  JSOP_IFPRIMTOP, 0, 16,
-/* 9*/  JSOP_SWAP,
-/*10*/  JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
-/*13*/  JSOP_CALL, 0, 1,
-/*16*/  JSOP_IFPRIMTOP, 0, 17,
-/*19*/  JSOP_GOTO, 0, 4,
-/*22*/  JSOP_POP,
-/*23*/  JSOP_POP,
-/*24*/  JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
-/*27*/  JSOP_CALL, 0, 0,
-/*30*/  JSOP_GOTO, 0, 5,
-/*33*/  JSOP_SWAP,
-/*34*/  JSOP_POP,
-/*35*/  JSOP_SWAP,
-/*36*/  JSOP_IMACOP,
-/*37*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_SWAP,
-/* 1*/  JSOP_DUP,
-/* 2*/  JSOP_DUP,
-/* 3*/  JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
-/* 6*/  JSOP_IFPRIMTOP, 0, 16,
-/* 9*/  JSOP_SWAP,
-/*10*/  JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
-/*13*/  JSOP_CALL, 0, 1,
-/*16*/  JSOP_IFPRIMTOP, 0, 17,
-/*19*/  JSOP_GOTO, 0, 4,
-/*22*/  JSOP_POP,
-/*23*/  JSOP_POP,
-/*24*/  JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
-/*27*/  JSOP_CALL, 0, 0,
-/*30*/  JSOP_GOTO, 0, 5,
-/*33*/  JSOP_SWAP,
-/*34*/  JSOP_POP,
-/*35*/  JSOP_SWAP,
-/*36*/  JSOP_DUP,
-/*37*/  JSOP_DUP,
-/*38*/  JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
-/*41*/  JSOP_IFPRIMTOP, 0, 16,
-/*44*/  JSOP_SWAP,
-/*45*/  JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
-/*48*/  JSOP_CALL, 0, 1,
-/*51*/  JSOP_IFPRIMTOP, 0, 17,
-/*54*/  JSOP_GOTO, 0, 4,
-/*57*/  JSOP_POP,
-/*58*/  JSOP_POP,
-/*59*/  JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
-/*62*/  JSOP_CALL, 0, 0,
-/*65*/  JSOP_GOTO, 0, 5,
-/*68*/  JSOP_SWAP,
-/*69*/  JSOP_POP,
-/*70*/  JSOP_IMACOP,
-/*71*/  JSOP_STOP,
-    },
-};
-static struct {
-    jsbytecode any_obj[36];
-    jsbytecode obj_any[38];
-    jsbytecode obj_obj[72];
-} add_imacros = {
-    {
-/* 0*/  JSOP_DUP,
-/* 1*/  JSOP_DUP,
-/* 2*/  JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
-/* 5*/  JSOP_IFPRIMTOP, 0, 16,
-/* 8*/  JSOP_SWAP,
-/* 9*/  JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_VOID),
-/*12*/  JSOP_CALL, 0, 1,
-/*15*/  JSOP_IFPRIMTOP, 0, 17,
-/*18*/  JSOP_GOTO, 0, 4,
-/*21*/  JSOP_POP,
-/*22*/  JSOP_POP,
-/*23*/  JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
-/*26*/  JSOP_CALL, 0, 0,
-/*29*/  JSOP_GOTO, 0, 5,
-/*32*/  JSOP_SWAP,
-/*33*/  JSOP_POP,
-/*34*/  JSOP_ADD,
-/*35*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_SWAP,
-/* 1*/  JSOP_DUP,
-/* 2*/  JSOP_DUP,
-/* 3*/  JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
-/* 6*/  JSOP_IFPRIMTOP, 0, 16,
-/* 9*/  JSOP_SWAP,
-/*10*/  JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_VOID),
-/*13*/  JSOP_CALL, 0, 1,
-/*16*/  JSOP_IFPRIMTOP, 0, 17,
-/*19*/  JSOP_GOTO, 0, 4,
-/*22*/  JSOP_POP,
-/*23*/  JSOP_POP,
-/*24*/  JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
-/*27*/  JSOP_CALL, 0, 0,
-/*30*/  JSOP_GOTO, 0, 5,
-/*33*/  JSOP_SWAP,
-/*34*/  JSOP_POP,
-/*35*/  JSOP_SWAP,
-/*36*/  JSOP_ADD,
-/*37*/  JSOP_STOP,
-    },
-    {
-/* 0*/  JSOP_SWAP,
-/* 1*/  JSOP_DUP,
-/* 2*/  JSOP_DUP,
-/* 3*/  JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
-/* 6*/  JSOP_IFPRIMTOP, 0, 16,
-/* 9*/  JSOP_SWAP,
-/*10*/  JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_VOID),
-/*13*/  JSOP_CALL, 0, 1,
-/*16*/  JSOP_IFPRIMTOP, 0, 17,
-/*19*/  JSOP_GOTO, 0, 4,
-/*22*/  JSOP_POP,
-/*23*/  JSOP_POP,
-/*24*/  JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
-/*27*/  JSOP_CALL, 0, 0,
-/*30*/  JSOP_GOTO, 0, 5,
-/*33*/  JSOP_SWAP,
-/*34*/  JSOP_POP,
-/*35*/  JSOP_SWAP,
-/*36*/  JSOP_DUP,
-/*37*/  JSOP_DUP,
-/*38*/  JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
-/*41*/  JSOP_IFPRIMTOP, 0, 16,
-/*44*/  JSOP_SWAP,
-/*45*/  JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_VOID),
-/*48*/  JSOP_CALL, 0, 1,
-/*51*/  JSOP_IFPRIMTOP, 0, 17,
-/*54*/  JSOP_GOTO, 0, 4,
-/*57*/  JSOP_POP,
-/*58*/  JSOP_POP,
-/*59*/  JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
-/*62*/  JSOP_CALL, 0, 0,
-/*65*/  JSOP_GOTO, 0, 5,
-/*68*/  JSOP_SWAP,
-/*69*/  JSOP_POP,
-/*70*/  JSOP_ADD,
-/*71*/  JSOP_STOP,
-    },
-};
-uint8 js_opcode2extra[JSOP_LIMIT] = {
-    0,  /* JSOP_INTERRUPT */
-    0,  /* JSOP_PUSH */
-    0,  /* JSOP_POPV */
-    0,  /* JSOP_ENTERWITH */
-    0,  /* JSOP_LEAVEWITH */
-    0,  /* JSOP_RETURN */
-    0,  /* JSOP_GOTO */
-    0,  /* JSOP_IFEQ */
-    0,  /* JSOP_IFNE */
-    0,  /* JSOP_ARGUMENTS */
-    0,  /* JSOP_FORARG */
-    0,  /* JSOP_FORLOCAL */
-    0,  /* JSOP_DUP */
-    0,  /* JSOP_DUP2 */
-    0,  /* JSOP_SETCONST */
-    3,  /* JSOP_BITOR */
-    3,  /* JSOP_BITXOR */
-    3,  /* JSOP_BITAND */
-    3,  /* JSOP_EQ */
-    3,  /* JSOP_NE */
-    3,  /* JSOP_LT */
-    3,  /* JSOP_LE */
-    3,  /* JSOP_GT */
-    3,  /* JSOP_GE */
-    3,  /* JSOP_LSH */
-    3,  /* JSOP_RSH */
-    3,  /* JSOP_URSH */
-    3,  /* JSOP_ADD */
-    3,  /* JSOP_SUB */
-    3,  /* JSOP_MUL */
-    3,  /* JSOP_DIV */
-    3,  /* JSOP_MOD */
-    0,  /* JSOP_NOT */
-    0,  /* JSOP_BITNOT */
-    0,  /* JSOP_NEG */
-    0,  /* JSOP_NEW */
-    0,  /* JSOP_DELNAME */
-    0,  /* JSOP_DELPROP */
-    0,  /* JSOP_DELELEM */
-    0,  /* JSOP_TYPEOF */
-    0,  /* JSOP_VOID */
-    0,  /* JSOP_INCNAME */
-    0,  /* JSOP_INCPROP */
-    0,  /* JSOP_INCELEM */
-    0,  /* JSOP_DECNAME */
-    0,  /* JSOP_DECPROP */
-    0,  /* JSOP_DECELEM */
-    0,  /* JSOP_NAMEINC */
-    0,  /* JSOP_PROPINC */
-    0,  /* JSOP_ELEMINC */
-    0,  /* JSOP_NAMEDEC */
-    0,  /* JSOP_PROPDEC */
-    0,  /* JSOP_ELEMDEC */
-    0,  /* JSOP_GETPROP */
-    0,  /* JSOP_SETPROP */
-    0,  /* JSOP_GETELEM */
-    0,  /* JSOP_SETELEM */
-    0,  /* JSOP_CALLNAME */
-    0,  /* JSOP_CALL */
-    0,  /* JSOP_NAME */
-    0,  /* JSOP_DOUBLE */
-    0,  /* JSOP_STRING */
-    0,  /* JSOP_ZERO */
-    0,  /* JSOP_ONE */
-    0,  /* JSOP_NULL */
-    0,  /* JSOP_THIS */
-    0,  /* JSOP_FALSE */
-    0,  /* JSOP_TRUE */
-    0,  /* JSOP_OR */
-    0,  /* JSOP_AND */
-    0,  /* JSOP_TABLESWITCH */
-    0,  /* JSOP_LOOKUPSWITCH */
-    0,  /* JSOP_STRICTEQ */
-    0,  /* JSOP_STRICTNE */
-    0,  /* JSOP_NULLTHIS */
-    0,  /* JSOP_ITER */
-    0,  /* JSOP_NEXTITER */
-    0,  /* JSOP_ENDITER */
-    0,  /* JSOP_APPLY */
-    0,  /* JSOP_SWAP */
-    0,  /* JSOP_OBJECT */
-    0,  /* JSOP_POP */
-    0,  /* JSOP_POS */
-    0,  /* JSOP_TRAP */
-    0,  /* JSOP_GETARG */
-    0,  /* JSOP_SETARG */
-    0,  /* JSOP_GETLOCAL */
-    0,  /* JSOP_SETLOCAL */
-    0,  /* JSOP_UINT16 */
-    0,  /* JSOP_NEWINIT */
-    0,  /* JSOP_ENDINIT */
-    0,  /* JSOP_INITPROP */
-    0,  /* JSOP_INITELEM */
-    0,  /* JSOP_DEFSHARP */
-    0,  /* JSOP_USESHARP */
-    0,  /* JSOP_INCARG */
-    0,  /* JSOP_DECARG */
-    0,  /* JSOP_ARGINC */
-    0,  /* JSOP_ARGDEC */
-    0,  /* JSOP_INCLOCAL */
-    0,  /* JSOP_DECLOCAL */
-    0,  /* JSOP_LOCALINC */
-    0,  /* JSOP_LOCALDEC */
-    0,  /* JSOP_IMACOP */
-    0,  /* JSOP_FORNAME */
-    0,  /* JSOP_FORPROP */
-    0,  /* JSOP_FORELEM */
-    0,  /* JSOP_POPN */
-    0,  /* JSOP_BINDNAME */
-    0,  /* JSOP_SETNAME */
-    0,  /* JSOP_THROW */
-    0,  /* JSOP_IN */
-    0,  /* JSOP_INSTANCEOF */
-    0,  /* JSOP_DEBUGGER */
-    0,  /* JSOP_GOSUB */
-    0,  /* JSOP_RETSUB */
-    0,  /* JSOP_EXCEPTION */
-    0,  /* JSOP_LINENO */
-    0,  /* JSOP_CONDSWITCH */
-    0,  /* JSOP_CASE */
-    0,  /* JSOP_DEFAULT */
-    0,  /* JSOP_EVAL */
-    0,  /* JSOP_ENUMELEM */
-    0,  /* JSOP_GETTER */
-    0,  /* JSOP_SETTER */
-    0,  /* JSOP_DEFFUN */
-    0,  /* JSOP_DEFCONST */
-    0,  /* JSOP_DEFVAR */
-    0,  /* JSOP_ANONFUNOBJ */
-    0,  /* JSOP_NAMEDFUNOBJ */
-    0,  /* JSOP_SETLOCALPOP */
-    0,  /* JSOP_IFPRIMTOP */
-    0,  /* JSOP_SETCALL */
-    0,  /* JSOP_TRY */
-    0,  /* JSOP_FINALLY */
-    0,  /* JSOP_NOP */
-    0,  /* JSOP_ARGSUB */
-    0,  /* JSOP_ARGCNT */
-    0,  /* JSOP_DEFLOCALFUN */
-    0,  /* JSOP_GOTOX */
-    0,  /* JSOP_IFEQX */
-    0,  /* JSOP_IFNEX */
-    0,  /* JSOP_ORX */
-    0,  /* JSOP_ANDX */
-    0,  /* JSOP_GOSUBX */
-    0,  /* JSOP_CASEX */
-    0,  /* JSOP_DEFAULTX */
-    0,  /* JSOP_TABLESWITCHX */
-    0,  /* JSOP_LOOKUPSWITCHX */
-    0,  /* JSOP_BACKPATCH */
-    0,  /* JSOP_BACKPATCH_POP */
-    0,  /* JSOP_THROWING */
-    0,  /* JSOP_SETRVAL */
-    0,  /* JSOP_RETRVAL */
-    0,  /* JSOP_GETGVAR */
-    0,  /* JSOP_SETGVAR */
-    0,  /* JSOP_INCGVAR */
-    0,  /* JSOP_DECGVAR */
-    0,  /* JSOP_GVARINC */
-    0,  /* JSOP_GVARDEC */
-    0,  /* JSOP_REGEXP */
-    0,  /* JSOP_DEFXMLNS */
-    0,  /* JSOP_ANYNAME */
-    0,  /* JSOP_QNAMEPART */
-    0,  /* JSOP_QNAMECONST */
-    0,  /* JSOP_QNAME */
-    0,  /* JSOP_TOATTRNAME */
-    0,  /* JSOP_TOATTRVAL */
-    0,  /* JSOP_ADDATTRNAME */
-    0,  /* JSOP_ADDATTRVAL */
-    0,  /* JSOP_BINDXMLNAME */
-    0,  /* JSOP_SETXMLNAME */
-    0,  /* JSOP_XMLNAME */
-    0,  /* JSOP_DESCENDANTS */
-    0,  /* JSOP_FILTER */
-    0,  /* JSOP_ENDFILTER */
-    0,  /* JSOP_TOXML */
-    0,  /* JSOP_TOXMLLIST */
-    0,  /* JSOP_XMLTAGEXPR */
-    0,  /* JSOP_XMLELTEXPR */
-    0,  /* JSOP_XMLOBJECT */
-    0,  /* JSOP_XMLCDATA */
-    0,  /* JSOP_XMLCOMMENT */
-    0,  /* JSOP_XMLPI */
-    0,  /* JSOP_CALLPROP */
-    0,  /* JSOP_GETFUNNS */
-    0,  /* JSOP_GETUPVAR */
-    0,  /* JSOP_DELDESC */
-    0,  /* JSOP_UINT24 */
-    0,  /* JSOP_INDEXBASE */
-    0,  /* JSOP_RESETBASE */
-    0,  /* JSOP_RESETBASE0 */
-    0,  /* JSOP_STARTXML */
-    0,  /* JSOP_STARTXMLEXPR */
-    0,  /* JSOP_CALLELEM */
-    0,  /* JSOP_STOP */
-    0,  /* JSOP_GETXPROP */
-    0,  /* JSOP_CALLXMLNAME */
-    0,  /* JSOP_TYPEOFEXPR */
-    0,  /* JSOP_ENTERBLOCK */
-    0,  /* JSOP_LEAVEBLOCK */
-    0,  /* JSOP_UNUSED201 */
-    0,  /* JSOP_UNUSED202 */
-    0,  /* JSOP_UNUSED203 */
-    0,  /* JSOP_UNUSED204 */
-    0,  /* JSOP_UNUSED205 */
-    0,  /* JSOP_UNUSED206 */
-    0,  /* JSOP_UNUSED207 */
-    0,  /* JSOP_UNUSED208 */
-    0,  /* JSOP_UNUSED209 */
-    0,  /* JSOP_GENERATOR */
-    0,  /* JSOP_YIELD */
-    0,  /* JSOP_ARRAYPUSH */
-    0,  /* JSOP_CALLUPVAR */
-    0,  /* JSOP_ENUMCONSTELEM */
-    0,  /* JSOP_LEAVEBLOCKEXPR */
-    0,  /* JSOP_GETTHISPROP */
-    0,  /* JSOP_GETARGPROP */
-    0,  /* JSOP_GETLOCALPROP */
-    0,  /* JSOP_UNUSED219 */
-    0,  /* JSOP_INDEXBASE1 */
-    0,  /* JSOP_INDEXBASE2 */
-    0,  /* JSOP_INDEXBASE3 */
-    0,  /* JSOP_CALLGVAR */
-    0,  /* JSOP_CALLLOCAL */
-    0,  /* JSOP_CALLARG */
-    0,  /* JSOP_UNUSED226 */
-    0,  /* JSOP_INT8 */
-    0,  /* JSOP_INT32 */
-    0,  /* JSOP_LENGTH */
-    0,  /* JSOP_NEWARRAY */
-    0,  /* JSOP_HOLE */
-};
deleted file mode 100644
--- a/js/src/imacros.jsasm
+++ /dev/null
@@ -1,210 +0,0 @@
-# vim: set sw=4 ts=8 et tw=78 ft=asm:
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is the TraceMonkey IMacro Assembler.
-#
-# The Initial Developer of the Original Code is
-# Brendan Eich <brendan@mozilla.org>.
-# Portions created by the Initial Developer are Copyright (C) 2008
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-.igroup binary JSOP_BITOR-JSOP_MOD
-
-    .imacro any_obj                     # any obj
-        dup                             # any obj obj
-        dup                             # any obj obj obj
-        getprop valueOf                 # any obj obj valueOf
-        ifprimtop 1                     # any obj obj valueOf
-        swap                            # any obj valueOf obj
-        string number                   # any obj valueOf obj "number"
-        call 1                          # any obj rval
-        ifprimtop 3                     # any obj rval
-        goto 2
-1:      pop                             # any obj obj
-2:      pop                             # any obj
-        callprop toString               # any toString obj
-        call 0                          # any rval
-        goto 4                          # any rval
-3:      swap                            # any rval obj
-        pop                             # any rval
-4:      imacop                          # bval
-        stop
-    .end
-
-    .imacro obj_any                     # obj any
-        swap                            # any obj
-        dup                             # any obj obj
-        dup                             # any obj obj obj
-        getprop valueOf                 # any obj obj valueOf
-        ifprimtop 1                     # any obj obj valueOf
-        swap                            # any obj valueOf obj
-        string number                   # any obj valueOf obj "number"
-        call 1                          # any obj lval
-        ifprimtop 3                     # any obj lval
-        goto 2
-1:      pop                             # any obj obj
-2:      pop                             # any obj
-        callprop toString               # any toString obj
-        call 0                          # any lval
-        goto 4                          # any lval
-3:      swap                            # any lval obj
-        pop                             # any lval
-4:      swap                            # lval any
-        imacop                          # bval
-        stop
-    .end
-
-    .imacro obj_obj                     # obj1 obj2
-        swap                            # obj2 obj1
-        dup                             # obj2 obj1 obj1
-        dup                             # obj2 obj1 obj1 obj1
-        getprop valueOf                 # obj2 obj1 obj1 valueOf
-        ifprimtop 1                     # obj2 obj1 obj1 valueOf
-        swap                            # obj2 obj1 valueOf obj1
-        string number                   # obj2 obj1 valueOf obj1 "number"
-        call 1                          # obj2 obj1 lval
-        ifprimtop 3                     # obj2 obj1 lval
-        goto 2
-1:      pop                             # obj2 obj1 obj1
-2:      pop                             # obj2 obj1
-        callprop toString               # obj2 toString obj1
-        call 0                          # obj2 lval
-        goto 4                          # obj2 lval
-3:      swap                            # obj2 lval obj1
-        pop                             # obj2 lval
-4:      swap                            # lval obj2
-        dup                             # lval obj1 obj1
-        dup                             # lval obj obj obj
-        getprop valueOf                 # lval obj obj valueOf
-        ifprimtop 5                     # lval obj obj valueOf
-        swap                            # lval obj valueOf obj
-        string number                   # lval obj valueOf obj "number"
-        call 1                          # lval obj rval
-        ifprimtop 7                     # lval obj rval
-        goto 6
-5:      pop                             # lval obj obj
-6:      pop                             # lval obj
-        callprop toString               # lval toString obj
-        call 0                          # lval rval
-        goto 8                          # lval rval
-7:      swap                            # lval rval obj
-        pop                             # lval rval
-8:      imacop                          # bval
-        stop
-    .end
-
-.end
-
-.igroup add JSOP_ADD
-
-    .imacro any_obj                     # any obj
-        dup                             # any obj obj
-        dup                             # any obj obj obj
-        getprop valueOf                 # any obj obj valueOf
-        ifprimtop 1                     # any obj obj valueOf
-        swap                            # any obj valueOf obj
-        string void                     # lval obj valueOf obj "void"
-        call 1                          # any obj rval
-        ifprimtop 3                     # any obj rval
-        goto 2
-1:      pop                             # any obj obj
-2:      pop                             # any obj
-        callprop toString               # any toString obj
-        call 0                          # any rval
-        goto 4                          # any rval
-3:      swap                            # any rval obj
-        pop                             # any rval
-4:      add                             # aval
-        stop
-    .end
-
-    .imacro obj_any                     # obj any
-        swap                            # any obj
-        dup                             # any obj obj
-        dup                             # any obj obj obj
-        getprop valueOf                 # any obj obj valueOf
-        ifprimtop 1                     # any obj obj valueOf
-        swap                            # any obj valueOf obj
-        string void                     # lval obj valueOf obj "void"
-        call 1                          # any obj lval
-        ifprimtop 3                     # any obj lval
-        goto 2
-1:      pop                             # any obj obj
-2:      pop                             # any obj
-        callprop toString               # any toString obj
-        call 0                          # any lval
-        goto 4                          # any lval
-3:      swap                            # any lval obj
-        pop                             # any lval
-4:      swap                            # lval any
-        add                             # aval
-        stop
-    .end
-
-    .imacro obj_obj                     # obj1 obj2
-        swap                            # obj2 obj1
-        dup                             # obj2 obj1 obj1
-        dup                             # obj2 obj1 obj1 obj1
-        getprop valueOf                 # obj2 obj1 obj1 valueOf
-        ifprimtop 1                     # obj2 obj1 obj1 valueOf
-        swap                            # obj2 obj1 valueOf obj1
-        string void                     # lval obj valueOf obj "void"
-        call 1                          # obj2 obj1 lval
-        ifprimtop 3                     # obj2 obj1 lval
-        goto 2
-1:      pop                             # obj2 obj1 obj1
-2:      pop                             # obj2 obj1
-        callprop toString               # obj2 toString obj1
-        call 0                          # obj2 lval
-        goto 4                          # obj2 lval
-3:      swap                            # obj2 lval obj1
-        pop                             # obj2 lval
-4:      swap                            # lval obj2
-        dup                             # lval obj1 obj1
-        dup                             # lval obj obj obj
-        getprop valueOf                 # lval obj obj valueOf
-        ifprimtop 5                     # lval obj obj valueOf
-        swap                            # lval obj valueOf obj
-        string void                     # lval obj valueOf obj "void"
-        call 1                          # lval obj rval
-        ifprimtop 7                     # lval obj rval
-        goto 6
-5:      pop                             # lval obj obj
-6:      pop                             # lval obj
-        callprop toString               # lval toString obj
-        call 0                          # lval rval
-        goto 8                          # lval rval
-7:      swap                            # lval rval obj
-        pop                             # lval rval
-8:      add                             # aval
-        stop
-    .end
-
-.end
--- a/js/src/js.cpp
+++ b/js/src/js.cpp
@@ -305,28 +305,20 @@ Process(JSContext *cx, JSObject *obj, ch
             if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) {
                 hitEOF = JS_TRUE;
                 break;
             }
             bufp += strlen(bufp);
             lineno++;
         } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
 
-        /* Clear any pending exception from previous failed compiles. */
+        /* Clear any pending exception from previous failed compiles.  */
         JS_ClearPendingException(cx);
-
-        /* Even though we're interactive, we have a compile-n-go opportunity. */
-        oldopts = JS_GetOptions(cx);
-        if (!compileOnly)
-            JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO);
         script = JS_CompileScript(cx, obj, buffer, strlen(buffer), "typein",
                                   startline);
-        if (!compileOnly)
-            JS_SetOptions(cx, oldopts);
-
         if (script) {
             if (!compileOnly) {
                 ok = JS_ExecuteScript(cx, obj, script, &result);
                 if (ok && !JSVAL_IS_VOID(result)) {
                     str = JS_ValueToString(cx, result);
                     if (str)
                         fprintf(gOutFile, "%s\n", JS_GetStringBytes(str));
                     else
@@ -2904,141 +2896,16 @@ fail:
     goto out;
 }
 
 #endif
 
 JS_DEFINE_TRCINFO_1(Print, (2, (static, JSVAL_FAIL, Print_tn, CONTEXT, STRING, 0, 0)))
 JS_DEFINE_TRCINFO_1(ShapeOf, (1, (static, INT32, ShapeOf_tn, OBJECT, 0, 0)))
 
-#ifdef XP_UNIX
-
-#include <fcntl.h>
-#include <sys/stat.h>
-
-/*
- * Returns a JS_malloc'd string (that the caller needs to JS_free)
- * containing the directory (non-leaf) part of |from| prepended to |leaf|.
- * If |from| is empty or a leaf, MakeAbsolutePathname returns a copy of leaf.
- * Returns NULL to indicate an error.
- */
-static char *
-MakeAbsolutePathname(JSContext *cx, const char *from, const char *leaf)
-{
-    size_t dirlen;
-    char *dir;
-    const char *slash = NULL, *cp;
-
-    cp = from;
-    while (*cp) {
-        if (*cp == '/'
-#ifdef XP_WIN
-            || *cp == '\\'
-#endif
-           ) {
-            slash = cp;
-        }
-
-        ++cp;
-    }
-
-    if (!slash) {
-        /* We were given a leaf or |from| was empty. */
-        return JS_strdup(cx, leaf);
-    }
-
-    /* Else, we were given a real pathname, return that + the leaf. */
-    dirlen = slash - from + 1;
-    dir = (char*) JS_malloc(cx, dirlen + strlen(leaf) + 1);
-    if (!dir)
-        return NULL;
-
-    strncpy(dir, from, dirlen);
-    strcpy(dir + dirlen, leaf); /* Note: we can't use strcat here. */
-
-    return dir;
-}
-
-#endif // XP_UNIX
-
-static JSBool
-Snarf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-    JSString *str;
-    const char *filename;
-    char *pathname;
-    JSStackFrame *fp;
-    JSBool ok;
-    off_t cc, len;
-    char *buf;
-    FILE *file;
-
-    str = JS_ValueToString(cx, argv[0]);
-    if (!str)
-        return JS_FALSE;
-    filename = JS_GetStringBytes(str);
-
-    /* Get the currently executing script's name. */
-    fp = JS_GetScriptedCaller(cx, NULL);
-    JS_ASSERT(fp && fp->script->filename);
-#ifdef XP_UNIX
-    pathname = MakeAbsolutePathname(cx, fp->script->filename, filename);
-    if (!pathname)
-        return JS_FALSE;
-#else
-    pathname = filename;
-#endif
-
-    ok = JS_FALSE;
-    len = 0;
-    buf = NULL;
-    file = fopen(pathname, "rb");
-    if (!file) {
-        JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno));
-    } else {
-        if (fseek(file, 0, SEEK_END) == EOF) {
-            JS_ReportError(cx, "can't seek end of %s", pathname);
-        } else {
-            len = ftell(file);
-            if (len == -1 || fseek(file, 0, SEEK_SET) == EOF) {
-                JS_ReportError(cx, "can't seek start of %s", pathname);
-            } else {
-                buf = (char*) JS_malloc(cx, len + 1);
-                if (buf) {
-                    cc = fread(buf, 1, len, file);
-                    if (cc != len) {
-                        JS_free(cx, buf);
-                        JS_ReportError(cx, "can't read %s: %s", pathname,
-                                       (cc < 0) ? strerror(errno)
-                                                : "short read");
-                    } else {
-                        len = (size_t)cc;
-                        ok = JS_TRUE;
-                    }
-                }
-            }
-        }
-        fclose(file);
-    }
-    JS_free(cx, pathname);
-    if (!ok) {
-        JS_free(cx, buf);
-        return ok;
-    }
-
-    buf[len] = '\0';
-    str = JS_NewString(cx, buf, len);
-    if (!str) {
-        JS_free(cx, buf);
-        return JS_FALSE;
-    }
-    *rval = STRING_TO_JSVAL(str);
-    return JS_TRUE;
-}
-
 /* We use a mix of JS_FS and JS_FN to test both kinds of natives. */
 static JSFunctionSpec shell_functions[] = {
     JS_FS("version",        Version,        0,0,0),
     JS_FS("options",        Options,        0,0,0),
     JS_FS("load",           Load,           1,0,0),
     JS_FN("readline",       ReadLine,       0,0),
     JS_TN("print",          Print,          0,0, Print_trcinfo),
     JS_FS("help",           Help,           0,0,0),
@@ -3075,40 +2942,39 @@ static JSFunctionSpec shell_functions[] 
     JS_FS("clone",          Clone,          1,0,0),
     JS_FS("seal",           Seal,           1,0,1),
     JS_FN("getpda",         GetPDA,         1,0),
     JS_FN("getslx",         GetSLX,         1,0),
     JS_FN("toint32",        ToInt32,        1,0),
     JS_FS("evalcx",         EvalInContext,  1,0,0),
     JS_TN("shapeOf",        ShapeOf,        1,0, ShapeOf_trcinfo),
 #ifdef MOZ_SHARK
-    JS_FS("startShark",     js_StartShark,      0,0,0),
-    JS_FS("stopShark",      js_StopShark,       0,0,0),
-    JS_FS("connectShark",   js_ConnectShark,    0,0,0),
-    JS_FS("disconnectShark",js_DisconnectShark, 0,0,0),
+    JS_FS("startShark",      js_StartShark,      0,0,0),
+    JS_FS("stopShark",       js_StopShark,       0,0,0),
+    JS_FS("connectShark",    js_ConnectShark,    0,0,0),
+    JS_FS("disconnectShark", js_DisconnectShark, 0,0,0),
 #endif
 #ifdef MOZ_CALLGRIND
-    JS_FS("startCallgrind", js_StartCallgrind,  0,0,0),
-    JS_FS("stopCallgrind",  js_StopCallgrind,   0,0,0),
-    JS_FS("dumpCallgrind",  js_DumpCallgrind,   1,0,0),
+    JS_FS("startCallgrind",  js_StartCallgrind,  0,0,0),
+    JS_FS("stopCallgrind",   js_StopCallgrind,   0,0,0),
+    JS_FS("dumpCallgrind",   js_DumpCallgrind,   1,0,0),
 #endif
 #ifdef MOZ_VTUNE
-    JS_FS("startVtune",     js_StartVtune,  1,0,0),
-    JS_FS("stopVtune",      js_StopVtune,   0,0,0),
-    JS_FS("pauseVtune",     js_PauseVtune,  0,0,0),
-    JS_FS("resumeVtune",    js_ResumeVtune, 0,0,0),
+    JS_FS("startVtune",      js_StartVtune,    1,0,0),
+    JS_FS("stopVtune",       js_StopVtune,     0,0,0),
+    JS_FS("pauseVtune",      js_PauseVtune,    0,0,0),
+    JS_FS("resumeVtune",     js_ResumeVtune,   0,0,0),
 #endif
 #ifdef DEBUG_ARRAYS
-    JS_FS("arrayInfo",      js_ArrayInfo,   1,0,0),
+    JS_FS("arrayInfo",       js_ArrayInfo,       1,0,0),
 #endif
 #ifdef JS_THREADSAFE
     JS_FN("sleep",          Sleep_fn,       1,0),
     JS_FN("scatter",        Scatter,        1,0),
 #endif
-    JS_FS("snarf",          Snarf,        0,0,0),
     JS_FS_END
 };
 
 static const char shell_help_header[] =
 "Command                  Description\n"
 "=======                  ===========\n";
 
 static const char *const shell_help_messages[] = {
@@ -3186,17 +3052,16 @@ static const char *const shell_help_mess
 #endif
 #ifdef DEBUG_ARRAYS
 "arrayInfo(a1, a2, ...)   Report statistics about arrays.",
 #endif
 #ifdef JS_THREADSAFE
 "sleep(dt)                Sleep for dt seconds",
 "scatter(fns)             Call functions concurrently (ignoring errors)",
 #endif
-"snarf(filename)          Read filename into returned string"
 };
 
 /* Help messages must match shell functions. */
 JS_STATIC_ASSERT(JS_ARRAY_LENGTH(shell_help_messages) + 1 ==
                  JS_ARRAY_LENGTH(shell_functions));
 
 #ifdef DEBUG
 static void
@@ -3950,16 +3815,133 @@ Evaluate(JSContext *cx, JSObject *obj, u
     ok = JS_EvaluateUCScript(cx, obj, JS_GetStringChars(source),
                              JS_GetStringLength(source), filename,
                              lineno, rval);
     JS_SetOptions(cx, oldopts);
 
     return ok;
 }
 
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/*
+ * Returns a JS_malloc'd string (that the caller needs to JS_free)
+ * containing the directory (non-leaf) part of |from| prepended to |leaf|.
+ * If |from| is empty or a leaf, MakeAbsolutePathname returns a copy of leaf.
+ * Returns NULL to indicate an error.
+ */
+static char *
+MakeAbsolutePathname(JSContext *cx, const char *from, const char *leaf)
+{
+    size_t dirlen;
+    char *dir;
+    const char *slash = NULL, *cp;
+
+    cp = from;
+    while (*cp) {
+        if (*cp == '/'
+#ifdef XP_WIN
+            || *cp == '\\'
+#endif
+           ) {
+            slash = cp;
+        }
+
+        ++cp;
+    }
+
+    if (!slash) {
+        /* We were given a leaf or |from| was empty. */
+        return JS_strdup(cx, leaf);
+    }
+
+    /* Else, we were given a real pathname, return that + the leaf. */
+    dirlen = slash - from + 1;
+    dir = (char*) JS_malloc(cx, dirlen + strlen(leaf) + 1);
+    if (!dir)
+        return NULL;
+
+    strncpy(dir, from, dirlen);
+    strcpy(dir + dirlen, leaf); /* Note: we can't use strcat here. */
+
+    return dir;
+}
+
+static JSBool
+snarf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+    JSString *str;
+    const char *filename;
+    char *pathname;
+    JSStackFrame *fp;
+    JSBool ok;
+    off_t cc, len;
+    char *buf;
+    FILE *file;
+
+    str = JS_ValueToString(cx, argv[0]);
+    if (!str)
+        return JS_FALSE;
+    filename = JS_GetStringBytes(str);
+
+    /* Get the currently executing script's name. */
+    fp = JS_GetScriptedCaller(cx, NULL);
+    JS_ASSERT(fp && fp->script->filename);
+    pathname = MakeAbsolutePathname(cx, fp->script->filename, filename);
+    if (!pathname)
+        return JS_FALSE;
+
+    ok = JS_FALSE;
+    len = 0;
+    buf = NULL;
+    file = fopen(pathname, "rb");
+    if (!file) {
+        JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno));
+    } else {
+        if (fseek(file, 0, SEEK_END) == EOF) {
+            JS_ReportError(cx, "can't seek end of %s", pathname);
+        } else {
+            len = ftell(file);
+            if (len == -1 || fseek(file, 0, SEEK_SET) == EOF) {
+                JS_ReportError(cx, "can't seek start of %s", pathname);
+            } else {
+                buf = (char*) JS_malloc(cx, len + 1);
+                if (buf) {
+                    cc = fread(buf, 1, len, file);
+                    if (cc != len) {
+                        JS_free(cx, buf);
+                        JS_ReportError(cx, "can't read %s: %s", pathname,
+                                       (cc < 0) ? strerror(errno)
+                                                : "short read");
+                    } else {
+                        len = (size_t)cc;
+                        ok = JS_TRUE;
+                    }
+                }
+            }
+        }
+        fclose(file);
+    }
+    JS_free(cx, pathname);
+    if (!ok) {
+        JS_free(cx, buf);
+        return ok;
+    }
+
+    buf[len] = '\0';
+    str = JS_NewString(cx, buf, len);
+    if (!str) {
+        JS_free(cx, buf);
+        return JS_FALSE;
+    }
+    *rval = STRING_TO_JSVAL(str);
+    return JS_TRUE;
+}
+
 #endif /* NARCISSUS */
 
 static JSBool
 ContextCallback(JSContext *cx, uintN contextOp)
 {
     if (contextOp == JSCONTEXT_NEW) {
         JS_SetErrorReporter(cx, my_ErrorReporter);
         JS_SetVersion(cx, JSVERSION_LATEST);
@@ -4083,16 +4065,18 @@ main(int argc, char **argv, char **envp)
     if (!envobj || !JS_SetPrivate(cx, envobj, envp))
         return 1;
 
 #ifdef NARCISSUS
     {
         jsval v;
         static const char Object_prototype[] = "Object.prototype";
 
+        if (!JS_DefineFunction(cx, glob, "snarf", snarf, 1, 0))
+            return 1;
         if (!JS_DefineFunction(cx, glob, "evaluate", Evaluate, 3, 0))
             return 1;
 
         if (!JS_EvaluateScript(cx, glob,
                                Object_prototype, sizeof Object_prototype - 1,
                                NULL, 0, &v)) {
             return 1;
         }
--- a/js/src/jsbuiltins.cpp
+++ b/js/src/jsbuiltins.cpp
@@ -397,33 +397,33 @@ js_AddProperty(JSContext* cx, JSObject* 
     JS_UNLOCK_SCOPE(cx, scope);
     return JS_FALSE;
 }
 
 JSBool FASTCALL
 js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr)
 {
     jsid id;
-    if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
+    if (!obj || !js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
         return JSVAL_TO_BOOLEAN(JSVAL_VOID);
 
     JSObject* obj2;
     JSProperty* prop;
     if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
         return JSVAL_TO_BOOLEAN(JSVAL_VOID);
     if (prop)
         OBJ_DROP_PROPERTY(cx, obj2, prop);
     return prop != NULL;
 }
 
 JSBool FASTCALL
 js_HasNamedPropertyInt32(JSContext* cx, JSObject* obj, int32 index)
 {
     jsid id;
-    if (!js_Int32ToId(cx, index, &id))
+    if (!obj || !js_Int32ToId(cx, index, &id))
         return JSVAL_TO_BOOLEAN(JSVAL_VOID);
 
     JSObject* obj2;
     JSProperty* prop;
     if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
         return JSVAL_TO_BOOLEAN(JSVAL_VOID);
     if (prop)
         OBJ_DROP_PROPERTY(cx, obj2, prop);
@@ -466,16 +466,28 @@ js_BooleanOrUndefinedToNumber(JSContext*
 
 JSString* FASTCALL
 js_BooleanOrUndefinedToString(JSContext *cx, int32 unboxed)
 {
     JS_ASSERT(uint32(unboxed) <= 2);
     return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[unboxed]);
 }
 
+JSString* FASTCALL
+js_ObjectToString(JSContext* cx, JSObject* obj)
+{
+    if (!obj)
+        return ATOM_TO_STRING(cx->runtime->atomState.nullAtom);
+    jsval v;
+    if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, &v))
+        return NULL;
+    JS_ASSERT(JSVAL_IS_STRING(v));
+    return JSVAL_TO_STRING(v);
+}
+
 JSObject* FASTCALL
 js_Arguments(JSContext* cx)
 {
     return NULL;
 }
 
 #define BUILTIN1 JS_DEFINE_CALLINFO_1
 #define BUILTIN2 JS_DEFINE_CALLINFO_2
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -152,32 +152,28 @@ EmitCheck(JSContext *cx, JSCodeGenerator
 }
 
 static void
 UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target)
 {
     jsbytecode *pc;
     JSOp op;
     const JSCodeSpec *cs;
-    uintN extra, depth;
+    uintN depth;
     intN nuses, ndefs;
-    extern uint8 js_opcode2extra[];
 
     pc = CG_CODE(cg, target);
     op = (JSOp) *pc;
     cs = &js_CodeSpec[op];
-    extra = js_opcode2extra[op];
-    if ((cs->format & JOF_TMPSLOT_MASK) || extra) {
+    if (cs->format & JOF_TMPSLOT_MASK) {
         depth = (uintN) cg->stackDepth +
-                ((cs->format & JOF_TMPSLOT_MASK) >> JOF_TMPSLOT_SHIFT) +
-                extra;
+                ((cs->format & JOF_TMPSLOT_MASK) >> JOF_TMPSLOT_SHIFT);
         if (depth > cg->maxStackDepth)
             cg->maxStackDepth = depth;
     }
-
     nuses = cs->nuses;
     if (nuses < 0)
         nuses = js_GetVariableStackUseLength(op, pc);
     cg->stackDepth -= nuses;
     JS_ASSERT(cg->stackDepth >= 0);
     if (cg->stackDepth < 0) {
         char numBuf[12];
         JSTokenStream *ts;
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -226,18 +226,17 @@ js_FillPropertyCache(JSContext *cx, JSOb
                             pobj, LOCKED_OBJ_GET_CLASS(pobj)->name,
                             JSVAL_TO_OBJECT(v),
                             JS_GetFunctionName(GET_FUNCTION_PRIVATE(cx,
                                                  JSVAL_TO_OBJECT(v))),
                             kshape);
 #endif
                         SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
                         SCOPE_SET_BRANDED(scope);
-                        if (OBJ_SCOPE(obj) == scope)
-                            kshape = scope->shape;
+                        kshape = scope->shape;
                     }
                     vword = JSVAL_OBJECT_TO_PCVAL(v);
                     break;
                 }
             }
         }
 
         /* If getting a value via a stub getter, we can cache the slot. */
@@ -2643,19 +2642,17 @@ js_Interpret(JSContext *cx)
 #ifdef JS_TRACER
 
 #define MONITOR_BRANCH()                                                      \
     JS_BEGIN_MACRO                                                            \
         if (TRACING_ENABLED(cx)) {                                            \
             ENABLE_TRACER(js_MonitorLoopEdge(cx, inlineCallCount));           \
             fp = cx->fp;                                                      \
             script = fp->script;                                              \
-            atoms = fp->imacpc                                                \
-                    ? COMMON_ATOMS_START(&rt->atomState)                      \
-                    : script->atomMap.vector;                                 \
+            atoms = script->atomMap.vector;                                   \
             currentVersion = (JSVersion) script->version;                     \
             JS_ASSERT(fp->regs == &regs);                                     \
             if (cx->throwing)                                                 \
                 goto error;                                                   \
         }                                                                     \
     JS_END_MACRO
 
 #else /* !JS_TRACER */
@@ -3072,19 +3069,17 @@ js_Interpret(JSContext *cx)
                 /* Restore cx->fp and release the inline frame's space. */
                 cx->fp = fp = fp->down;
                 JS_ASSERT(fp->regs == &ifp->callerRegs);
                 fp->regs = &regs;
                 JS_ARENA_RELEASE(&cx->stackPool, ifp->mark);
 
                 /* Restore the calling script's interpreter registers. */
                 script = fp->script;
-                atoms = fp->imacpc
-                        ? COMMON_ATOMS_START(&rt->atomState)
-                        : script->atomMap.vector;
+                atoms = script->atomMap.vector;
 
                 /* Resume execution in the calling frame. */
                 inlineCallCount--;
                 if (JS_LIKELY(ok)) {
                     TRACE_0(LeaveFrame);
                     JS_ASSERT(js_CodeSpec[*regs.pc].length == JSOP_CALL_LENGTH);
                     len = JSOP_CALL_LENGTH;
                     DO_NEXT_OP(len);
@@ -6482,29 +6477,16 @@ js_Interpret(JSContext *cx)
              * the exception object.
              */
             JS_ASSERT((size_t) (regs.sp - StackBase(fp)) >= 2);
             slot = GET_UINT16(regs.pc);
             JS_ASSERT(slot + 1 < script->nslots);
             fp->slots[slot] = POP_OPND();
           END_CASE(JSOP_SETLOCALPOP)
 
-          BEGIN_CASE(JSOP_IFPRIMTOP)
-            /*
-             * If the top of stack is of primitive type, jump to our target.
-             * Otherwise advance to the next opcode.
-             */
-            JS_ASSERT(regs.sp > StackBase(fp));
-            rval = FETCH_OPND(-1);
-            if (JSVAL_IS_PRIMITIVE(rval)) {
-                len = GET_JUMP_OFFSET(regs.pc);
-                BRANCH(len);
-            }
-          END_CASE(JSOP_IFPRIMTOP)
-
           BEGIN_CASE(JSOP_INSTANCEOF)
             rval = FETCH_OPND(-1);
             if (JSVAL_IS_PRIMITIVE(rval) ||
                 !(obj = JSVAL_TO_OBJECT(rval))->map->ops->hasInstance) {
                 js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
                                     -1, rval, NULL);
                 goto error;
             }
@@ -6946,16 +6928,17 @@ js_Interpret(JSContext *cx)
           L_JSOP_TOATTRNAME:
           L_JSOP_QNAME:
           L_JSOP_QNAMECONST:
           L_JSOP_QNAMEPART:
           L_JSOP_ANYNAME:
           L_JSOP_DEFXMLNS:
 # endif
 
+          L_JSOP_UNUSED131:
           L_JSOP_UNUSED201:
           L_JSOP_UNUSED202:
           L_JSOP_UNUSED203:
           L_JSOP_UNUSED204:
           L_JSOP_UNUSED205:
           L_JSOP_UNUSED206:
           L_JSOP_UNUSED207:
           L_JSOP_UNUSED208:
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1077,24 +1077,16 @@ obj_toLocaleString(JSContext *cx, uintN 
 
 static JSBool
 obj_valueOf(JSContext *cx, uintN argc, jsval *vp)
 {
     *vp = JS_THIS(cx, vp);
     return !JSVAL_IS_NULL(*vp);
 }
 
-#ifdef JS_TRACER
-static jsval FASTCALL
-Object_p_valueOf(JSContext* cx, JSObject* obj, JSString *hint)
-{
-    return OBJECT_TO_JSVAL(obj);
-}
-#endif
-
 /*
  * Check whether principals subsumes scopeobj's principals, and return true
  * if so (or if scopeobj has no principals, for backward compatibility with
  * the JS API, which does not require principals), and false otherwise.
  */
 JSBool
 js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj,
                          JSPrincipals *principals, JSAtom *caller)
@@ -1813,31 +1805,28 @@ const char js_isPrototypeOf_str[] = "isP
 const char js_propertyIsEnumerable_str[] = "propertyIsEnumerable";
 #if JS_HAS_GETTER_SETTER
 const char js_defineGetter_str[] = "__defineGetter__";
 const char js_defineSetter_str[] = "__defineSetter__";
 const char js_lookupGetter_str[] = "__lookupGetter__";
 const char js_lookupSetter_str[] = "__lookupSetter__";
 #endif
 
-JS_DEFINE_TRCINFO_1(obj_valueOf,
-    (3, (static, JSVAL, Object_p_valueOf, CONTEXT, THIS, STRING,                  0, 0)))
 JS_DEFINE_TRCINFO_1(obj_hasOwnProperty,
     (3, (static, BOOL_FAIL, Object_p_hasOwnProperty, CONTEXT, THIS, STRING,       0, 0)))
 JS_DEFINE_TRCINFO_1(obj_propertyIsEnumerable,
     (3, (static, BOOL_FAIL, Object_p_propertyIsEnumerable, CONTEXT, THIS, STRING, 0, 0)))
 
 static JSFunctionSpec object_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,             obj_toSource,                0,0),
 #endif
     JS_FN(js_toString_str,             obj_toString,                0,0),
     JS_FN(js_toLocaleString_str,       obj_toLocaleString,          0,0),
-    JS_TN(js_valueOf_str,              obj_valueOf,                 0,0,
-          obj_valueOf_trcinfo),
+    JS_FN(js_valueOf_str,              obj_valueOf,                 0,0),
 #if JS_HAS_OBJ_WATCHPOINT
     JS_FN(js_watch_str,                obj_watch,                   2,0),
     JS_FN(js_unwatch_str,              obj_unwatch,                 1,0),
 #endif
     JS_TN(js_hasOwnProperty_str,       obj_hasOwnProperty,          1,0,
           obj_hasOwnProperty_trcinfo),
     JS_FN(js_isPrototypeOf_str,        obj_isPrototypeOf,           1,0),
     JS_TN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable,    1,0,
--- a/js/src/jsopcode.tbl
+++ b/js/src/jsopcode.tbl
@@ -122,33 +122,33 @@ OPDEF(JSOP_ARGUMENTS, 9, js_arguments_st
 /* ECMA-compliant for-in loop with argument or local loop control. */
 OPDEF(JSOP_FORARG,    10, "forarg",     NULL,         3,  2,  2, 19,  JOF_QARG|JOF_NAME|JOF_FOR)
 OPDEF(JSOP_FORLOCAL,  11, "forlocal",   NULL,         3,  2,  2, 19,  JOF_LOCAL|JOF_NAME|JOF_FOR)
 
 /* More longstanding bytecodes. */
 OPDEF(JSOP_DUP,       12, "dup",        NULL,         1,  1,  2,  0,  JOF_BYTE)
 OPDEF(JSOP_DUP2,      13, "dup2",       NULL,         1,  2,  4,  0,  JOF_BYTE)
 OPDEF(JSOP_SETCONST,  14, "setconst",   NULL,         3,  1,  1,  3,  JOF_ATOM|JOF_NAME|JOF_SET)
-OPDEF(JSOP_BITOR,     15, "bitor",      "|",          1,  2,  1,  7,  JOF_BYTE|JOF_LEFTASSOC)
-OPDEF(JSOP_BITXOR,    16, "bitxor",     "^",          1,  2,  1,  8,  JOF_BYTE|JOF_LEFTASSOC)
-OPDEF(JSOP_BITAND,    17, "bitand",     "&",          1,  2,  1,  9,  JOF_BYTE|JOF_LEFTASSOC)
+OPDEF(JSOP_BITOR,     15, "bitor",      "|",          1,  2,  1,  7,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_BITXOR,    16, "bitxor",     "^",          1,  2,  1,  8,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_BITAND,    17, "bitand",     "&",          1,  2,  1,  9,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
 OPDEF(JSOP_EQ,        18, "eq",         "==",         1,  2,  1,  10,  JOF_BYTE|JOF_LEFTASSOC|JOF_DETECTING)
 OPDEF(JSOP_NE,        19, "ne",         "!=",         1,  2,  1,  10,  JOF_BYTE|JOF_LEFTASSOC|JOF_DETECTING)
-OPDEF(JSOP_LT,        20, "lt",         "<",          1,  2,  1, 11,  JOF_BYTE|JOF_LEFTASSOC)
-OPDEF(JSOP_LE,        21, "le",         "<=",         1,  2,  1, 11,  JOF_BYTE|JOF_LEFTASSOC)
-OPDEF(JSOP_GT,        22, "gt",         ">",          1,  2,  1, 11,  JOF_BYTE|JOF_LEFTASSOC)
-OPDEF(JSOP_GE,        23, "ge",         ">=",         1,  2,  1, 11,  JOF_BYTE|JOF_LEFTASSOC)
-OPDEF(JSOP_LSH,       24, "lsh",        "<<",         1,  2,  1, 12,  JOF_BYTE|JOF_LEFTASSOC)
-OPDEF(JSOP_RSH,       25, "rsh",        ">>",         1,  2,  1, 12,  JOF_BYTE|JOF_LEFTASSOC)
-OPDEF(JSOP_URSH,      26, "ursh",       ">>>",        1,  2,  1, 12,  JOF_BYTE|JOF_LEFTASSOC)
-OPDEF(JSOP_ADD,       27, "add",        "+",          1,  2,  1, 13,  JOF_BYTE|JOF_LEFTASSOC)
-OPDEF(JSOP_SUB,       28, "sub",        "-",          1,  2,  1, 13,  JOF_BYTE|JOF_LEFTASSOC)
-OPDEF(JSOP_MUL,       29, "mul",        "*",          1,  2,  1, 14,  JOF_BYTE|JOF_LEFTASSOC)
-OPDEF(JSOP_DIV,       30, "div",        "/",          1,  2,  1, 14,  JOF_BYTE|JOF_LEFTASSOC)
-OPDEF(JSOP_MOD,       31, "mod",        "%",          1,  2,  1, 14,  JOF_BYTE|JOF_LEFTASSOC)
+OPDEF(JSOP_LT,        20, "lt",         "<",          1,  2,  1, 11,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_LE,        21, "le",         "<=",         1,  2,  1, 11,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_GT,        22, "gt",         ">",          1,  2,  1, 11,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_GE,        23, "ge",         ">=",         1,  2,  1, 11,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_LSH,       24, "lsh",        "<<",         1,  2,  1, 12,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_RSH,       25, "rsh",        ">>",         1,  2,  1, 12,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_URSH,      26, "ursh",       ">>>",        1,  2,  1, 12,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_ADD,       27, "add",        "+",          1,  2,  1, 13,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_SUB,       28, "sub",        "-",          1,  2,  1, 13,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_MUL,       29, "mul",        "*",          1,  2,  1, 14,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_DIV,       30, "div",        "/",          1,  2,  1, 14,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_MOD,       31, "mod",        "%",          1,  2,  1, 14,  JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
 OPDEF(JSOP_NOT,       32, "not",        "!",          1,  1,  1, 15,  JOF_BYTE|JOF_DETECTING)
 OPDEF(JSOP_BITNOT,    33, "bitnot",     "~",          1,  1,  1, 15,  JOF_BYTE)
 OPDEF(JSOP_NEG,       34, "neg",        "- ",         1,  1,  1, 15,  JOF_BYTE)
 OPDEF(JSOP_NEW,       35, js_new_str,   NULL,         3, -1,  1, 17,  JOF_UINT16|JOF_INVOKE)
 OPDEF(JSOP_DELNAME,   36, "delname",    NULL,         3,  0,  1, 15,  JOF_ATOM|JOF_NAME|JOF_DEL)
 OPDEF(JSOP_DELPROP,   37, "delprop",    NULL,         3,  1,  1, 15,  JOF_ATOM|JOF_PROP|JOF_DEL)
 OPDEF(JSOP_DELELEM,   38, "delelem",    NULL,         1,  2,  1, 15,  JOF_BYTE |JOF_ELEM|JOF_DEL)
 OPDEF(JSOP_TYPEOF,    39, js_typeof_str,NULL,         1,  1,  1, 15,  JOF_BYTE|JOF_DETECTING)
@@ -328,18 +328,18 @@ OPDEF(JSOP_ANONFUNOBJ,  128, "anonfunobj
 OPDEF(JSOP_NAMEDFUNOBJ, 129, "namedfunobj", NULL,     3,  0,  1, 19,  JOF_OBJECT)
 
 /*
  * Like JSOP_SETLOCAL, but specialized to avoid requiring JSOP_POP immediately
  * after to throw away the exception value.
  */
 OPDEF(JSOP_SETLOCALPOP, 130, "setlocalpop", NULL,     3,  1,  0,  3,  JOF_LOCAL|JOF_NAME|JOF_SET)
 
-/* Jump to target if top of stack value is of primitive type. */
-OPDEF(JSOP_IFPRIMTOP,   131, "ifprimtop",   NULL,     3,  1,  1,  0,  JOF_JUMP|JOF_DETECTING)
+/* Parenthesization opcode to help the decompiler. */
+OPDEF(JSOP_UNUSED131,   131, "unused131",   NULL,     1,  0,  0,  0,  JOF_BYTE)
 
 /*
  * Host object extension: given 'o.item(i) = j', the left-hand side compiles
  * JSOP_SETCALL, rather than JSOP_CALL.
  */
 OPDEF(JSOP_SETCALL,     132, "setcall",     NULL,     3, -1,  2, 18,  JOF_UINT16|JOF_SET)
 
 /*
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -65,34 +65,29 @@
 #include "jsregexp.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsdate.h"
 #include "jsstaticcheck.h"
 #include "jstracer.h"
 
 #include "jsautooplen.h"        // generated headers last
-#include "imacros.c.out"
 
 /* Never use JSVAL_IS_BOOLEAN because it restricts the value (true, false) and 
    the type. What you want to use is JSVAL_TAG(x) == JSVAL_BOOLEAN and then 
    handle the undefined case properly (bug 457363). */
 #undef JSVAL_IS_BOOLEAN
 #define JSVAL_IS_BOOLEAN(x) JS_STATIC_ASSERT(0) 
 
 /* Use a fake tag to represent boxed values, borrowing from the integer tag
    range since we only use JSVAL_INT to indicate integers. */
 #define JSVAL_BOXED 3
 
-/* Another fake jsval tag, used to distinguish null from object values. */
-#define JSVAL_TNULL 5
-
 /* Map to translate a type tag into a printable representation. */
-static const char typeChar[] = "OIDVSNB?";
-static const char tagChar[]  = "OIDISIBI";
+static const char typeChar[] = "OIDVS?B?";
 
 /* Number of iterations of a loop where we start tracing.  That is, we don't
    start tracing until the beginning of the HOTLOOP-th iteration. */
 #define HOTLOOP 2
 
 /* Number of times we wait to exit on a side exit before we try to extend the tree. */
 #define HOTEXIT 1
 
@@ -344,23 +339,23 @@ static inline bool isInt32(jsval v)
     jsdouble d = asNumber(v);
     jsint i;
     return JSDOUBLE_IS_INT(d, i);
 }
 
 /* Return JSVAL_DOUBLE for all numbers (int and double) and the tag otherwise. */
 static inline uint8 getPromotedType(jsval v) 
 {
-    return JSVAL_IS_INT(v) ? JSVAL_DOUBLE : JSVAL_IS_NULL(v) ? JSVAL_TNULL : uint8(JSVAL_TAG(v));
+    return JSVAL_IS_INT(v) ? JSVAL_DOUBLE : uint8(JSVAL_TAG(v));
 }
 
 /* Return JSVAL_INT for all whole numbers that fit into signed 32-bit and the tag otherwise. */
 static inline uint8 getCoercedType(jsval v)
 {
-    return isInt32(v) ? JSVAL_INT : JSVAL_IS_NULL(v) ? JSVAL_TNULL : uint8(JSVAL_TAG(v));
+    return isInt32(v) ? JSVAL_INT : (uint8) JSVAL_TAG(v);
 }
 
 /* 
  * Constant seed and accumulate step borrowed from the DJB hash.
  */
 
 #define ORACLE_MASK (ORACLE_SIZE - 1)
 
@@ -1283,20 +1278,16 @@ ValueToNative(JSContext* cx, jsval v, ui
         *(JSBool*)slot = JSVAL_TO_BOOLEAN(v);
         debug_only_v(printf("boolean<%d> ", *(JSBool*)slot);)
         return;
       case JSVAL_STRING:
         JS_ASSERT(tag == JSVAL_STRING);
         *(JSString**)slot = JSVAL_TO_STRING(v);
         debug_only_v(printf("string<%p> ", *(JSString**)slot);)
         return;
-      case JSVAL_TNULL:
-        JS_ASSERT(tag == JSVAL_OBJECT);
-        *(JSObject**)slot = NULL;
-        return;
       default:
         /* Note: we should never see JSVAL_BOXED in an entry type map. */
         JS_ASSERT(type == JSVAL_OBJECT);
         JS_ASSERT(tag == JSVAL_OBJECT);
         *(JSObject**)slot = JSVAL_TO_OBJECT(v);
         debug_only_v(printf("object<%p:%s> ", JSVAL_TO_OBJECT(v),
                             JSVAL_IS_NULL(v)
                             ? "null"
@@ -1401,21 +1392,16 @@ NativeToValue(JSContext* cx, jsval& v, u
         v = STRING_TO_JSVAL(*(JSString**)slot);
         JS_ASSERT(JSVAL_TAG(v) == JSVAL_STRING); /* if this fails the pointer was not aligned */
         debug_only_v(printf("string<%p> ", *(JSString**)slot);)
         break;
       case JSVAL_BOXED:
         v = *(jsval*)slot;
         debug_only_v(printf("box<%lx> ", v));
         break;
-      case JSVAL_TNULL:
-        JS_ASSERT(*(JSObject**)slot == NULL);
-        v = JSVAL_NULL;
-        debug_only_v(printf("null<%p> ", *(JSObject**)slot));
-        break;
       default:
         JS_ASSERT(type == JSVAL_OBJECT);
         v = OBJECT_TO_JSVAL(*(JSObject**)slot);
         JS_ASSERT(JSVAL_TAG(v) == JSVAL_OBJECT); /* if this fails the pointer was not aligned */
         debug_only_v(printf("object<%p:%s> ", JSVAL_TO_OBJECT(v),
                             JSVAL_IS_NULL(v)
                             ? "null"
                             : STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v))->name);)
@@ -1818,28 +1804,21 @@ TraceRecorder::adjustCallerTypes(Fragmen
 
 JS_REQUIRES_STACK uint8
 TraceRecorder::determineSlotType(jsval* vp) const
 {
     uint8 m;
     LIns* i = get(vp);
     m = isNumber(*vp)
         ? (isPromoteInt(i) ? JSVAL_INT : JSVAL_DOUBLE)
-        : JSVAL_IS_NULL(*vp)
-        ? JSVAL_TNULL
         : JSVAL_TAG(*vp);
     JS_ASSERT((m != JSVAL_INT) || isInt32(*vp));
     return m;
 }
 
-/*
- * Combine fp->imacpc and fp->regs->pc into one word, with 8 bits for the pc
- * adjustment from one byte before the imacro's start (so a 0 high byte means
- * we're not in an imacro), and 24 for the pc adjustment from script->code.
- */
 #define IMACRO_PC_ADJ_BITS   8
 #define SCRIPT_PC_ADJ_BITS   (32 - IMACRO_PC_ADJ_BITS)
 
 // The stored imacro_pc_adj byte offset is biased by 1.
 #define IMACRO_PC_ADJ_LIMIT  (JS_BIT(IMACRO_PC_ADJ_BITS) - 1)
 #define SCRIPT_PC_ADJ_LIMIT  JS_BIT(SCRIPT_PC_ADJ_BITS)
 
 #define IMACRO_PC_ADJ(ip)    ((uintptr_t)(ip) >> SCRIPT_PC_ADJ_BITS)
@@ -1865,19 +1844,16 @@ TraceRecorder::determineSlotType(jsval* 
                               ? (fp)->imacpc = (fp)->script->code +           \
                                                SCRIPT_PC_ADJ(ip),             \
                                 (fp)->regs->pc = imacro_code[*(fp)->imacpc] + \
                                                  IMACRO_PC_ADJ(ip)            \
                               : (fp)->regs->pc = (fp)->script->code + (ip))
 
 static jsbytecode* imacro_code[JSOP_LIMIT];
 
-JS_STATIC_ASSERT(sizeof(binary_imacros) < IMACRO_PC_ADJ_LIMIT);
-JS_STATIC_ASSERT(sizeof(add_imacros) < IMACRO_PC_ADJ_LIMIT);
-
 JS_REQUIRES_STACK LIns*
 TraceRecorder::snapshot(ExitType exitType)
 {
     JSStackFrame* fp = cx->fp;
     JSFrameRegs* regs = fp->regs;
     jsbytecode* pc = regs->pc;
     if (exitType == BRANCH_EXIT && js_IsLoopExit(pc, (jsbytecode*)fragment->root->ip))
         exitType = LOOP_EXIT;
@@ -2055,29 +2031,26 @@ TraceRecorder::checkType(jsval& v, uint8
            sure we promote back to double if at loop entry we want a double. */
         if (isPromoteInt(i)) {
             stage_val = &v;
             stage_ins = lir->ins1(LIR_i2f, i);
             stage_count++;
         }
         return true;
     }
-    if (t == JSVAL_TNULL && JSVAL_IS_NULL(v))
-        return true;
     /* for non-number types we expect a precise match of the type */
-    uint8 vt = getCoercedType(v);
 #ifdef DEBUG
-    if (vt != t) {
-        debug_only_v(printf("Type mismatch: val %c, map %c ", typeChar[vt],
+    if (JSVAL_TAG(v) != t) {
+        debug_only_v(printf("Type mismatch: val %c, map %c ", typeChar[JSVAL_TAG(v)],
                             typeChar[t]);)
     }
 #endif
-    debug_only_v(printf("checkType(vt=%d, t=%d) stage_count=%d\n",
-                        (int) vt, t, stage_count);)
-    return vt == t;
+    debug_only_v(printf("checkType(tag=%d, t=%d) stage_count=%d\n",
+                        (int) JSVAL_TAG(v), t, stage_count);)
+    return JSVAL_TAG(v) == t;
 }
 
 /**
  * Make sure that the current values in the given stack frame and all stack frames
  * up and including entryFrame are type-compatible with the entry map.
  *
  * @param root_peer         First fragment in peer list.
  * @param stable_peer       Outparam for first type stable peer.
@@ -2214,17 +2187,17 @@ checktype_fail_2:
             if (*m == JSVAL_INT) {
                 JS_ASSERT(isNumber(*vp));
                 if (!isPromoteInt(get(vp)))
                     ADD_UNDEMOTE_SLOT(demotes, unsigned(m - typemap));
             } else if (*m == JSVAL_DOUBLE) {
                 JS_ASSERT(isNumber(*vp));
                 ADD_UNDEMOTE_SLOT(demotes, unsigned(m - typemap));
             } else {
-                JS_ASSERT((*m == JSVAL_TNULL) ? JSVAL_IS_NULL(*vp) : *m == JSVAL_TAG(*vp));
+                JS_ASSERT(*m == JSVAL_TAG(*vp));
             }
             m++;
         );
         return true;
     }
 
     return false;
 }
@@ -2649,16 +2622,32 @@ TraceRecorder::hasMethod(JSObject* obj, 
         }
     }
 
     OBJ_DROP_PROPERTY(cx, pobj, prop);
     return found;
 }
 
 bool
+TraceRecorder::hasToStringMethod(JSObject* obj)
+{
+    JS_ASSERT(cx->fp->regs->sp + 1 <= cx->fp->slots + cx->fp->script->nslots);
+
+    return hasMethod(obj, ATOM_TO_JSID(cx->runtime->atomState.toStringAtom));
+}
+
+bool
+TraceRecorder::hasValueOfMethod(JSObject* obj)
+{
+    JS_ASSERT(cx->fp->regs->sp + 2 <= cx->fp->slots + cx->fp->script->nslots);
+
+    return hasMethod(obj, ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom));
+}
+
+bool
 TraceRecorder::hasIteratorMethod(JSObject* obj)
 {
     JS_ASSERT(cx->fp->regs->sp + 2 <= cx->fp->slots + cx->fp->script->nslots);
 
     return hasMethod(obj, ATOM_TO_JSID(cx->runtime->atomState.iteratorAtom));
 }
 
 int
@@ -3310,17 +3299,17 @@ js_RecordLoopEdge(JSContext* cx, TraceRe
     return false;
 }
 
 static bool
 js_IsEntryTypeCompatible(jsval* vp, uint8* m)
 {
     unsigned tag = JSVAL_TAG(*vp);
 
-    debug_only_v(printf("%c/%c ", tagChar[tag], typeChar[*m]);)
+    debug_only_v(printf("%c/%c ", "OIDISIBI"[tag], "OID?S?B?"[*m]);)
 
     switch (*m) {
       case JSVAL_INT:
         jsint i;
         if (JSVAL_IS_INT(*vp))
             return true;
         if ((tag == JSVAL_DOUBLE) && JSDOUBLE_IS_INT(*JSVAL_TO_DOUBLE(*vp), i))
             return true;
@@ -3336,21 +3325,19 @@ js_IsEntryTypeCompatible(jsval* vp, uint
             return true;
         debug_only_v(printf("bool != tag%u", tag);)
         return false;
       case JSVAL_STRING:
         if (tag == JSVAL_STRING)
             return true;
         debug_only_v(printf("string != tag%u", tag);)
         return false;
-      case JSVAL_TNULL:
-        return JSVAL_IS_NULL(*vp);
       default:
         JS_ASSERT(*m == JSVAL_OBJECT);
-        if (tag == JSVAL_OBJECT && !JSVAL_IS_NULL(*vp))
+        if (tag == JSVAL_OBJECT)
             return true;
         debug_only_v(printf("object != tag%u", tag);)
         return false;
     }
 }
 
 JS_REQUIRES_STACK Fragment*
 TraceRecorder::findNestedCompatiblePeer(Fragment* f, Fragment** empty)
@@ -4341,17 +4328,17 @@ TraceRecorder::ifop()
     LIns* x;
     /* no need to guard if condition is constant */
     if (v_ins->isconst() || v_ins->isconstq())
         return true;
     if (JSVAL_TAG(v) == JSVAL_BOOLEAN) {
         /* test for boolean is true, negate later if we are testing for false */
         cond = JSVAL_TO_BOOLEAN(v) == 1;
         x = lir->ins2i(LIR_eq, v_ins, 1);
-    } else if (JSVAL_TAG(v) == JSVAL_OBJECT) {
+    } else if (JSVAL_IS_OBJECT(v)) {
         cond = !JSVAL_IS_NULL(v);
         x = v_ins;
     } else if (isNumber(v)) {
         jsdouble d = asNumber(v);
         cond = !JSDOUBLE_IS_NaN(d) && d;
         jsdpun u;
         u.d = 0;
         x = lir->ins2(LIR_and, 
@@ -4529,16 +4516,55 @@ evalCmp(LOpcode op, double l, double r)
 static bool
 evalCmp(LOpcode op, JSString* l, JSString* r)
 {
     if (op == LIR_feq)
         return js_EqualStrings(l, r);
     return evalCmp(op, js_CompareStrings(l, r));
 }
 
+static struct {
+    jsbytecode obj_any[13];
+    jsbytecode any_obj[11];
+    jsbytecode obj_obj[22];
+} binary_imacros = {
+    {
+        JSOP_SWAP,
+        JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
+        JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
+        JSOP_CALL, 0, 1,
+        JSOP_SWAP,
+        JSOP_IMACOP,
+        JSOP_STOP
+    },
+
+    {
+        JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
+        JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
+        JSOP_CALL, 0, 1,
+        JSOP_IMACOP,
+        JSOP_STOP
+    },
+
+    {
+        JSOP_SWAP,
+        JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
+        JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
+        JSOP_CALL, 0, 1,
+        JSOP_SWAP,
+        JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
+        JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
+        JSOP_CALL, 0, 1,
+        JSOP_IMACOP,
+        JSOP_STOP
+    }
+};
+
+JS_STATIC_ASSERT(sizeof(binary_imacros) < IMACRO_PC_ADJ_LIMIT);
+
 JS_REQUIRES_STACK void
 TraceRecorder::strictEquality(bool equal)
 {
     jsval& r = stackval(-1);
     jsval& l = stackval(-2);
     LIns* l_ins = get(&l);
     LIns* r_ins = get(&r);
 
@@ -4629,17 +4655,17 @@ TraceRecorder::equality(int flags)
             // See above for the sob story.
             r_ins = lir->insCall(&js_BooleanOrUndefinedToNumber_ci, args);
         } else if (!isNumber(r)) {
             ABORT_TRACE("unsupported RHS type for cmp vs number");
         }
         jsdouble rnum = js_ValueToNumber(cx, &tmp[1]);
         cond = (lnum == rnum);
     } else if ((JSVAL_TAG(l) == JSVAL_BOOLEAN && JSVAL_TAG(r) == JSVAL_BOOLEAN) ||
-               (JSVAL_TAG(l) == JSVAL_OBJECT && JSVAL_TAG(r) == JSVAL_OBJECT)) {
+               (JSVAL_IS_OBJECT(l) && JSVAL_IS_OBJECT(r))) {
         cond = (l == r); 
     } else {
         ABORT_TRACE("unsupported operand types for cmp");
     }
 
     /* If we didn't generate a constant result yet, then emit the comparison now. */
     if (!x) {
         /* If the result is not a number or it's not a quad, we must use an integer compare. */
@@ -4688,23 +4714,25 @@ TraceRecorder::relational(LOpcode op, in
     bool fp = false;
     jsdouble lnum, rnum;
 
     /*
      * 11.8.5 if either argument is an object with a function-valued valueOf
      * property; if both arguments are objects with non-function-valued valueOf
      * properties, abort.
      */
-    if (!JSVAL_IS_PRIMITIVE(l)) {
-        if (!JSVAL_IS_PRIMITIVE(r))
+    if (JSVAL_IS_OBJECT(l) && hasValueOfMethod(l)) {
+        if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
             return call_imacro(binary_imacros.obj_obj);
         return call_imacro(binary_imacros.obj_any);
     }
-    if (!JSVAL_IS_PRIMITIVE(r))
+    if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
         return call_imacro(binary_imacros.any_obj);
+    if (JSVAL_IS_OBJECT(l) || JSVAL_IS_OBJECT(r))
+        ABORT_TRACE("comparing two objects with non-function valueOf");
 
     /* 11.8.5 steps 3, 16-21. */
     if (JSVAL_IS_STRING(l) && JSVAL_IS_STRING(r)) {
         LIns* args[] = { r_ins, l_ins };
         l_ins = lir->insCall(&js_CompareStrings_ci, args);
         r_ins = lir->insImm(0);
         cond = evalCmp(op, JSVAL_TO_STRING(l), JSVAL_TO_STRING(r));
         goto do_comparison;
@@ -4715,47 +4743,37 @@ TraceRecorder::relational(LOpcode op, in
         LIns* args[] = { l_ins, cx_ins };
         switch (JSVAL_TAG(l)) {
           case JSVAL_BOOLEAN:
             l_ins = lir->insCall(&js_BooleanOrUndefinedToNumber_ci, args);
             break;
           case JSVAL_STRING:
             l_ins = lir->insCall(&js_StringToNumber_ci, args);
             break;
-          case JSVAL_OBJECT:
-            if (JSVAL_IS_NULL(l)) {
-                l_ins = lir->insImmq(0);
-                break;
-            }
-            // FALL THROUGH
           case JSVAL_INT:
           case JSVAL_DOUBLE:
+          case JSVAL_OBJECT:
           default:
             JS_NOT_REACHED("JSVAL_IS_NUMBER if int/double, objects should "
                            "have been handled at start of method");
             ABORT_TRACE("safety belt");
         }
     }    
     if (!JSVAL_IS_NUMBER(r)) {
         LIns* args[] = { r_ins, cx_ins };
         switch (JSVAL_TAG(r)) {
           case JSVAL_BOOLEAN:
             r_ins = lir->insCall(&js_BooleanOrUndefinedToNumber_ci, args);
             break;
           case JSVAL_STRING:
             r_ins = lir->insCall(&js_StringToNumber_ci, args);
             break;
-          case JSVAL_OBJECT:
-            if (JSVAL_IS_NULL(r)) {
-                r_ins = lir->insImmq(0);
-                break;
-            }
-            // FALL THROUGH
           case JSVAL_INT:
           case JSVAL_DOUBLE:
+          case JSVAL_OBJECT:
           default:
             JS_NOT_REACHED("JSVAL_IS_NUMBER if int/double, objects should "
                            "have been handled at start of method");
             ABORT_TRACE("safety belt");
         }
     }
     {
         jsval tmp = JSVAL_NULL;
@@ -4815,22 +4833,22 @@ TraceRecorder::unary(LOpcode op)
 }
 
 JS_REQUIRES_STACK bool
 TraceRecorder::binary(LOpcode op)
 {
     jsval& r = stackval(-1);
     jsval& l = stackval(-2);
 
-    if (!JSVAL_IS_PRIMITIVE(l)) {
-        if (!JSVAL_IS_PRIMITIVE(r))
+    if (JSVAL_IS_OBJECT(l) && hasValueOfMethod(l)) {
+        if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
             return call_imacro(binary_imacros.obj_obj);
         return call_imacro(binary_imacros.obj_any);
     }
-    if (!JSVAL_IS_PRIMITIVE(r))
+    if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
         return call_imacro(binary_imacros.any_obj);
 
     bool intop = !(op & LIR64);
     LIns* a = get(&l);
     LIns* b = get(&r);
 
     bool leftIsNumber = isNumber(l);
     jsdouble lnum = leftIsNumber ? asNumber(l) : 0;
@@ -5016,17 +5034,17 @@ TraceRecorder::test_property_cache(JSObj
 #ifdef DEBUG
         JSOp op = JSOp(*pc);
         ptrdiff_t pcoff = (op == JSOP_GETARGPROP) ? ARGNO_LEN :
                           (op == JSOP_GETLOCALPROP) ? SLOTNO_LEN : 0;
         jsatomid index = js_GetIndexFromBytecode(cx, cx->fp->script, pc, pcoff);
         JS_ASSERT(entry->kpc == (jsbytecode*) atoms[index]);
         JS_ASSERT(entry->kshape == jsuword(aobj));
 #endif
-        if (aobj != globalObj && !obj_ins->isconstp()) {
+        if (aobj != globalObj) {
             guard(true, addName(lir->ins2i(LIR_eq, obj_ins, entry->kshape), "guard(kobj)"),
                   MISMATCH_EXIT);
         }
     }
 
     // For any hit that goes up the scope and/or proto chains, we will need to
     // guard on the shape of the object containing the property.
     if (PCVCAP_TAG(entry->vcap) >= 1) {
@@ -5211,30 +5229,22 @@ TraceRecorder::unbox_jsval(jsval v, LIns
       case JSVAL_BOOLEAN:
         guard(true,
               lir->ins2i(LIR_eq,
                          lir->ins2(LIR_piand, v_ins, INS_CONST(JSVAL_TAGMASK)),
                          JSVAL_BOOLEAN),
               MISMATCH_EXIT);
          v_ins = lir->ins2i(LIR_ush, v_ins, JSVAL_TAGBITS);
          return true;
-      case JSVAL_OBJECT:
-        if (JSVAL_IS_NULL(v)) {
-            // JSVAL_NULL maps to type JSVAL_TNULL, so insist that v_ins == 0 here.
-            guard(true, lir->ins_eq0(v_ins), MISMATCH_EXIT);
-        } else {
-            // We must guard that v_ins has JSVAL_OBJECT tag but is not JSVAL_NULL.
-            LIns* exit = snapshot(MISMATCH_EXIT);
-            guard(true,
-                  lir->ins2i(LIR_eq,
-                             lir->ins2(LIR_piand, v_ins, INS_CONST(JSVAL_TAGMASK)),
-                             JSVAL_OBJECT),
-                  exit);
-            guard(false, lir->ins_eq0(v_ins), exit);
-        }
+       case JSVAL_OBJECT:
+        guard(true,
+              lir->ins2i(LIR_eq,
+                         lir->ins2(LIR_piand, v_ins, INS_CONST(JSVAL_TAGMASK)),
+                         JSVAL_OBJECT),
+              MISMATCH_EXIT);
         return true;
       case JSVAL_STRING:
         guard(true,
               lir->ins2i(LIR_eq,
                         lir->ins2(LIR_piand, v_ins, INS_CONST(JSVAL_TAGMASK)),
                         JSVAL_STRING),
               MISMATCH_EXIT);
         v_ins = lir->ins2(LIR_piand, v_ins, INS_CONST(~JSVAL_TAGMASK));
@@ -5649,28 +5659,63 @@ TraceRecorder::record_JSOP_RSH()
 }
 
 JS_REQUIRES_STACK bool
 TraceRecorder::record_JSOP_URSH()
 {
     return binary(LIR_ush);
 }
 
+static struct {
+    jsbytecode obj_any[10];
+    jsbytecode any_obj[8];
+    jsbytecode obj_obj[16];
+} add_imacros = {
+    {
+        JSOP_SWAP,
+        JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
+        JSOP_CALL, 0, 0,
+        JSOP_SWAP,
+        JSOP_ADD,
+        JSOP_STOP
+    },
+
+    {
+        JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
+        JSOP_CALL, 0, 0,
+        JSOP_ADD,
+        JSOP_STOP
+    },
+
+    {
+        JSOP_SWAP,
+        JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
+        JSOP_CALL, 0, 0,
+        JSOP_SWAP,
+        JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
+        JSOP_CALL, 0, 0,
+        JSOP_ADD,
+        JSOP_STOP
+    }
+};
+
+JS_STATIC_ASSERT(sizeof(add_imacros) < IMACRO_PC_ADJ_LIMIT);
+
 JS_REQUIRES_STACK bool
 TraceRecorder::record_JSOP_ADD()
 {
     jsval& r = stackval(-1);
     jsval& l = stackval(-2);
 
-    if (!JSVAL_IS_PRIMITIVE(l)) {
-        if (!JSVAL_IS_PRIMITIVE(r))
+    if (JSVAL_IS_OBJECT(l) && hasToStringMethod(l)) {
+        if (JSVAL_IS_OBJECT(r) && hasToStringMethod(r))
             return call_imacro(add_imacros.obj_obj);
         return call_imacro(add_imacros.obj_any);
     }
-    if (!JSVAL_IS_PRIMITIVE(r))
+    if (JSVAL_IS_OBJECT(r) && hasToStringMethod(r))
         return call_imacro(add_imacros.any_obj);
 
     if (JSVAL_IS_STRING(l) || JSVAL_IS_STRING(r)) {
         LIns* args[] = { stringify(r), stringify(l), cx_ins };
         if (!args[0] || !args[1])
             ABORT_TRACE("can't stringify objects");
         LIns* concat = lir->insCall(&js_ConcatStrings_ci, args);
         guard(false, lir->ins_eq0(concat), OOM_EXIT);
@@ -5700,22 +5745,22 @@ TraceRecorder::record_JSOP_DIV()
 }
 
 JS_REQUIRES_STACK bool
 TraceRecorder::record_JSOP_MOD()
 {
     jsval& r = stackval(-1);
     jsval& l = stackval(-2);
 
-    if (!JSVAL_IS_PRIMITIVE(l)) {
-        if (!JSVAL_IS_PRIMITIVE(r))
+    if (JSVAL_IS_OBJECT(l) && hasValueOfMethod(l)) {
+        if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
             return call_imacro(binary_imacros.obj_obj);
         return call_imacro(binary_imacros.obj_any);
     }
-    if (!JSVAL_IS_PRIMITIVE(r))
+    if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
         return call_imacro(binary_imacros.any_obj);
 
     if (isNumber(l) && isNumber(r)) {
         LIns* l_ins = get(&l);
         LIns* r_ins = get(&r);
         LIns* x;
         /* We can't demote this in a filter since we need the actual values of l and r. */
         if (isPromote(l_ins) && isPromote(r_ins) && asNumber(l) >= 0 && asNumber(r) > 0) {
@@ -5742,17 +5787,17 @@ TraceRecorder::record_JSOP_NOT()
         return true;
     } 
     if (isNumber(v)) {
         LIns* v_ins = get(&v);
         set(&v, lir->ins2(LIR_or, lir->ins2(LIR_feq, v_ins, lir->insImmq(0)),
                                   lir->ins_eq0(lir->ins2(LIR_feq, v_ins, v_ins))));
         return true;
     } 
-    if (JSVAL_TAG(v) == JSVAL_OBJECT) {
+    if (JSVAL_IS_OBJECT(v)) {
         set(&v, lir->ins_eq0(get(&v)));
         return true;
     }
     JS_ASSERT(JSVAL_IS_STRING(v));
     set(&v, lir->ins_eq0(lir->ins2(LIR_piand, 
                                    lir->insLoad(LIR_ldp, get(&v), (int)offsetof(JSString, length)),
                                    INS_CONSTPTR(JSSTRING_LENGTH_MASK))));
     return true;
@@ -5808,17 +5853,17 @@ TraceRecorder::getClassPrototype(JSObjec
     jsval pval;
 
     if (!OBJ_GET_PROPERTY(cx, ctor,
                           ATOM_TO_JSID(cx->runtime->atomState
                                        .classPrototypeAtom),
                           &pval)) {
         ABORT_TRACE("error getting prototype from constructor");
     }
-    if (JSVAL_TAG(pval) != JSVAL_OBJECT)
+    if (!JSVAL_IS_OBJECT(pval))
         ABORT_TRACE("got primitive prototype from constructor");
     proto_ins = INS_CONSTPTR(JSVAL_TO_OBJECT(pval));
     return true;
 }
 
 bool
 TraceRecorder::newArray(JSObject *ctor, uint32 argc, jsval *argv, jsval *rval)
 {
@@ -5931,17 +5976,17 @@ TraceRecorder::functionCall(bool constru
 #endif
 
         uintN i;
         for (i = prefixc; i--; ) {
             argtype = known->prefix[i];
             if (argtype == 'C') {
                 *argp = cx_ins;
             } else if (argtype == 'T') {   /* this, as an object */
-                if (JSVAL_IS_PRIMITIVE(tval))
+                if (!JSVAL_IS_OBJECT(tval))
                     goto next_specialization;
                 *argp = this_ins;
             } else if (argtype == 'S') {   /* this, as a string */
                 if (!JSVAL_IS_STRING(tval))
                     goto next_specialization;
                 *argp = this_ins;
             } else if (argtype == 'f') {
                 *argp = INS_CONSTPTR(JSVAL_TO_OBJECT(fval));
@@ -5968,17 +6013,17 @@ TraceRecorder::functionCall(bool constru
 
             argtype = known->argtypes[i];
             if (argtype == 'd' || argtype == 'i') {
                 if (!isNumber(arg))
                     goto next_specialization;
                 if (argtype == 'i')
                     *argp = f2i(*argp);
             } else if (argtype == 'o') {
-                if (JSVAL_IS_PRIMITIVE(arg))
+                if (!JSVAL_IS_OBJECT(arg))
                     goto next_specialization;
             } else if (argtype == 's') {
                 if (!JSVAL_IS_STRING(arg))
                     goto next_specialization;
             } else if (argtype == 'r') {
                 if (!VALUE_IS_REGEXP(cx, arg))
                     goto next_specialization;
             } else if (argtype == 'f') {
@@ -6102,17 +6147,17 @@ TraceRecorder::record_JSOP_TYPEOF()
     } else {
         LIns* args[] = { get(&r), cx_ins };
         if (JSVAL_TAG(r) == JSVAL_BOOLEAN) {
             // We specialize identically for boolean and undefined. We must not have a hole here.
             // Pass the unboxed type here, since TypeOfBoolean knows how to handle it.
             JS_ASSERT(JSVAL_TO_BOOLEAN(r) <= 2);
             type = lir->insCall(&js_TypeOfBoolean_ci, args);
         } else {
-            JS_ASSERT(JSVAL_TAG(r) == JSVAL_OBJECT);
+            JS_ASSERT(JSVAL_IS_OBJECT(r));
             type = lir->insCall(&js_TypeOfObject_ci, args);
         }
     }
     set(&r, type);
     return true;
 }
 
 JS_REQUIRES_STACK bool
@@ -6474,23 +6519,23 @@ TraceRecorder::record_JSOP_CALLNAME()
     stack(0, INS_CONSTPTR(PCVAL_TO_OBJECT(pcval)));
     stack(1, obj_ins);
     return true;
 }
 
 JS_REQUIRES_STACK bool
 TraceRecorder::record_JSOP_GETUPVAR()
 {
-    return false;
+    ABORT_TRACE("GETUPVAR");
 }
 
 JS_REQUIRES_STACK bool
 TraceRecorder::record_JSOP_CALLUPVAR()
 {
-    return false;
+    ABORT_TRACE("CALLUPVAR");
 }
 
 JS_REQUIRES_STACK bool
 TraceRecorder::guardCallee(jsval& callee)
 {
     LIns* exit = snapshot(BRANCH_EXIT);
     JSObject* callee_obj = JSVAL_TO_OBJECT(callee);
     LIns* callee_ins = get(&callee);
@@ -7294,17 +7339,17 @@ JS_STATIC_ASSERT(sizeof(iter_imacros) < 
 
 JS_REQUIRES_STACK bool
 TraceRecorder::record_JSOP_ITER()
 {
     jsval& v = stackval(-1);
     if (!JSVAL_IS_PRIMITIVE(v)) {
         jsuint flags = cx->fp->regs->pc[1];
 
-        if (!hasIteratorMethod(JSVAL_TO_OBJECT(v))) {
+        if (!hasIteratorMethod(v)) {
             LIns* args[] = { get(&v), INS_CONST(flags), cx_ins };
             LIns* v_ins = lir->insCall(&js_FastValueToIterator_ci, args);
             guard(false, lir->ins_eq0(v_ins), MISMATCH_EXIT);
             set(&v, v_ins);
 
             LIns* void_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
             stack(0, void_ins);
             return true;
@@ -7655,26 +7700,16 @@ TraceRecorder::record_JSOP_NAMEDFUNOBJ()
 JS_REQUIRES_STACK bool
 TraceRecorder::record_JSOP_SETLOCALPOP()
 {
     var(GET_SLOTNO(cx->fp->regs->pc), stack(-1));
     return true;
 }
 
 JS_REQUIRES_STACK bool
-TraceRecorder::record_JSOP_IFPRIMTOP()
-{
-    // Traces are type-specialized, including null vs. object, so we need do
-    // nothing here. The upstream unbox_jsval called after valueOf or toString
-    // from an imacro (e.g.) will fork the trace for us, allowing us to just
-    // follow along mindlessly :-).
-    return true;
-}
-
-JS_REQUIRES_STACK bool
 TraceRecorder::record_JSOP_SETCALL()
 {
     return false;
 }
 
 JS_REQUIRES_STACK bool
 TraceRecorder::record_JSOP_TRY()
 {
@@ -8531,16 +8566,17 @@ InitIMacroCode()
     imacro_code[JSOP_ADD] = (jsbytecode*)&add_imacros - 1;
 
     imacro_code[JSOP_ITER] = (jsbytecode*)&iter_imacros - 1;
     imacro_code[JSOP_NEXTITER] = nextiter_imacro - 1;
 }
 
 #define UNUSED(n) JS_REQUIRES_STACK bool TraceRecorder::record_JSOP_UNUSED##n() { return false; }
 
+UNUSED(131)
 UNUSED(201)
 UNUSED(202)
 UNUSED(203)
 UNUSED(204)
 UNUSED(205)
 UNUSED(206)
 UNUSED(207)
 UNUSED(208)
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -415,17 +415,31 @@ class TraceRecorder : public avmplus::GC
                                                    bool constructing);
     JS_REQUIRES_STACK bool functionCall(bool constructing, uintN argc);
 
     JS_REQUIRES_STACK void trackCfgMerges(jsbytecode* pc);
     JS_REQUIRES_STACK void flipIf(jsbytecode* pc, bool& cond);
     JS_REQUIRES_STACK void fuseIf(jsbytecode* pc, bool cond, nanojit::LIns* x);
 
     bool hasMethod(JSObject* obj, jsid id);
+    bool hasToStringMethod(JSObject* obj);
+    bool hasToStringMethod(jsval v) {
+        JS_ASSERT(JSVAL_IS_OBJECT(v));
+        return hasToStringMethod(JSVAL_TO_OBJECT(v));
+    }
+    bool hasValueOfMethod(JSObject* obj);
+    bool hasValueOfMethod(jsval v) {
+        JS_ASSERT(JSVAL_IS_OBJECT(v));
+        return hasValueOfMethod(JSVAL_TO_OBJECT(v));
+    }
     bool hasIteratorMethod(JSObject* obj);
+    bool hasIteratorMethod(jsval v) {
+        JS_ASSERT(JSVAL_IS_OBJECT(v));
+        return hasIteratorMethod(JSVAL_TO_OBJECT(v));
+    }
 
 public:
     friend JS_REQUIRES_STACK bool js_MonitorRecording(TraceRecorder* tr);
 
     JS_REQUIRES_STACK
     TraceRecorder(JSContext* cx, VMSideExit*, nanojit::Fragment*, TreeInfo*,
                   unsigned ngslots, uint8* globalTypeMap, uint8* stackTypeMap, 
                   VMSideExit* expectedInnerExit, nanojit::Fragment* outerToBlacklist);
--- a/js/src/trace-test.js
+++ b/js/src/trace-test.js
@@ -2006,16 +2006,265 @@ function testBug466262() {
 		e = "";
 	  }
 	}
 	return true;
 }
 testBug466262.expected = true;
 test(testBug466262);
 
+// BEGIN MANDELBROT STUFF
+// XXXbz I would dearly like to wrap it up into a function to avoid polluting
+// the global scope, but the function ends up heavyweight, and then we lose on
+// the jit.
+load("mandelbrot-results.js");
+//function testMandelbrotAll() {
+  // Configuration options that affect which codepaths we follow.
+  var doImageData = true;
+  var avoidSparseArray = true;
+
+  // Control of iteration numbers and sizing.  We'll do
+  // scaler * colorNames.length iterations or so before deciding that we
+  // don't escape.
+  const scaler = 5;
+  const numRows = 600;
+  const numCols = 600;
+
+  // For now, avoid hitting memory pressure
+  gcparam("maxBytes", 1300000000); 
+  gcparam("maxMallocBytes", 1300000000); 
+
+  const colorNames = [
+    "black",
+    "green",
+    "blue",
+    "red",
+    "purple",
+    "orange",
+    "cyan",
+    "yellow",
+    "magenta",
+    "brown",
+    "pink",
+    "chartreuse",
+    "darkorange",
+    "crimson",
+    "gray",
+    "deeppink",
+    "firebrick",
+    "lavender",
+    "lawngreen",
+    "lightsalmon",
+    "lime",
+    "goldenrod"
+  ];
+  const threshold = (colorNames.length - 1) * scaler;
+
+  // Now set up our colors
+  var colors = [];
+  // 3-part for loop (iterators buggy, we will add a separate test for them)
+  for (var colorNameIdx = 0; colorNameIdx < colorNames.length; ++colorNameIdx) {
+  //for (var colorNameIdx in colorNames) {
+    colorNameIdx = parseInt(colorNameIdx);
+    colors.push([colorNameIdx, colorNameIdx, colorNameIdx, 0]);
+  }
+
+  // Storage for our point data
+  var points;
+
+  var scratch = {};
+  var scratchZ = {};
+  function complexMult(a, b) {
+    var newr = a.r * b.r - a.i * b.i;
+    var newi = a.r * b.i + a.i * b.r;
+    scratch.r = newr;
+    scratch.i = newi;
+    return scratch;
+  }
+  function complexAdd(a, b) {
+    scratch.r = a.r + b.r;
+    scratch.i = a.i + b.i;
+    return scratch;
+  }
+  function abs(a) {
+    return Math.sqrt(a.r * a.r + a.i * a.i);
+  }
+
+  function escapeAbsDiff(normZ, absC) {
+    var absZ = Math.sqrt(normZ);
+    return normZ > absZ + absC;
+  }
+
+  function escapeNorm2(normZ) {
+    return normZ > 4;
+  }
+
+  function fuzzyColors(i) {
+    return Math.floor(i / scaler) + 1;
+  }
+
+  function moddedColors(i) {
+    return (i % (colorNames.length - 1)) + 1;
+  }
+
+  function computeEscapeSpeedObjects(real, imag) {
+    var c = { r: real, i: imag }
+    scratchZ.r = scratchZ.i = 0;
+    var absC = abs(c);
+    for (var i = 0; i < threshold; ++i) {
+      scratchZ = complexAdd(c, complexMult(scratchZ, scratchZ));
+      if (escape(scratchZ.r * scratchZ.r + scratchZ.i * scratchZ.i,
+                 absC)) {
+        return colorMap(i);
+      }
+    }
+    return 0;
+  }
+
+  function computeEscapeSpeedOneObject(real, imag) {
+    // fold in the fact that we start with 0
+    var r = real;
+    var i = imag;
+    var absC = abs({r: real, i: imag});
+    for (var j = 0; j < threshold; ++j) {
+      var r2 = r * r;
+      var i2 = i * i;
+      if (escape(r2 + i2, absC)) {
+        return colorMap(j);
+      }
+      i = 2 * r * i + imag;
+      r = r2 - i2 + real;
+    }
+    return 0;
+  }
+
+  function computeEscapeSpeedDoubles(real, imag) {
+    // fold in the fact that we start with 0
+    var r = real;
+    var i = imag;
+    var absC = Math.sqrt(real * real + imag * imag);
+    for (var j = 0; j < threshold; ++j) {
+      var r2 = r * r;
+      var i2 = i * i;
+      if (escape(r2 + i2, absC)) {
+        return colorMap(j);
+      }
+      i = 2 * r * i + imag;
+      r = r2 - i2 + real;
+    }
+    return 0;
+  }
+
+  var computeEscapeSpeed = computeEscapeSpeedDoubles;
+  var escape = escapeNorm2;
+  var colorMap = fuzzyColors;
+
+  function addPointOrig(pointArray, n, i, j) {
+    if (!points[n]) {
+      points[n] = [];
+      points[n].push([i, j, 1, 1]);
+    } else {
+      var point = points[n][points[n].length-1];
+      if (point[0] == i && point[1] == j - point[3]) {
+        ++point[3];
+      } else {
+        points[n].push([i, j, 1, 1]);
+      }
+    }
+  }
+
+  function addPointImagedata(pointArray, n, col, row) {
+    var slotIdx = ((row * numCols) + col) * 4;
+    pointArray[slotIdx] = colors[n][0];
+    pointArray[slotIdx+1] = colors[n][1];
+    pointArray[slotIdx+2] = colors[n][2];
+    pointArray[slotIdx+3] = colors[n][3];
+  }
+
+  function createMandelSet() {
+    var realRange = { min: -2.1, max: 1 };
+    var imagRange = { min: -1.5, max: 1.5 };
+
+    var addPoint;
+    if (doImageData) {
+      addPoint = addPointImagedata;
+      points = new Array(4*numCols*numRows);
+      if (avoidSparseArray) {
+        for (var idx = 0; idx < 4*numCols*numRows; ++idx) {
+          points[idx] = 0;
+        }
+      }
+    } else {
+      addPoint = addPointOrig;
+      points = [];
+    }
+    var realStep = (realRange.max - realRange.min)/numCols;
+    var imagStep = (imagRange.min - imagRange.max)/numRows;
+    for (var i = 0, curReal = realRange.min;
+         i < numCols;
+         ++i, curReal += realStep) {
+      for (var j = 0, curImag = imagRange.max;
+           j < numRows;
+           ++j, curImag += imagStep) {
+        var n = computeEscapeSpeed(curReal, curImag);
+        addPoint(points, n, i, j)
+      }
+    }
+    var result;
+    if (doImageData) {
+      if (colorMap == fuzzyColors) {
+        result = mandelbrotImageDataFuzzyResult;
+      } else {
+        result = mandelbrotImageDataModdedResult;
+      }
+    } else {
+      result = mandelbrotNoImageDataResult;
+    }
+    return points.toSource() == result;
+  }
+
+  createMandelSet.expected = true;
+
+  const escapeTests = [ escapeAbsDiff ];
+  const colorMaps = [ fuzzyColors, moddedColors ];
+  const escapeComputations = [ computeEscapeSpeedObjects,
+                               computeEscapeSpeedOneObject,
+                               computeEscapeSpeedDoubles ];
+  // Test all possible escape-speed generation codepaths, using the
+  // imageData + sparse array avoidance storage.
+  doImageData = true;
+  avoidSparseArray = true;
+  for (var escapeIdx in escapeTests) {
+    escape = escapeTests[escapeIdx];
+    for (var colorMapIdx in colorMaps) {
+      colorMap = colorMaps[colorMapIdx];
+      for (var escapeComputationIdx in escapeComputations) {
+        computeEscapeSpeed = escapeComputations[escapeComputationIdx];
+        test(createMandelSet);
+      }
+    }
+  }
+
+  // Test all possible storage strategies. Note that we already tested
+  // doImageData == true with avoidSparseArray == true.
+  escape = escapeAbsDiff;
+  colorMap = fuzzyColors; // This part doesn't really matter too much here
+  computeEscapeSpeed = computeEscapeSpeedDoubles;
+
+  doImageData = true;
+  avoidSparseArray = false; 
+  test(createMandelSet);
+
+  escape = escapeNorm2;
+  doImageData = false;  // avoidSparseArray doesn't matter here
+  test(createMandelSet);
+//}
+//testMandelbrotAll();
+// END MANDELBROT STUFF
+
 function testNewDate()
 {
     // Accessing global.Date for the first time will change the global shape,
     // so do it before the loop starts; otherwise we have to loop an extra time
     // to pick things up.
     var start = new Date();
     var time = new Date();
     for (var j = 0; j < RUNLOOP; ++j) {
@@ -3472,265 +3721,16 @@ function testComparisons()
   if (failures.length == 0)
     return "no failures reported!";
 
   return "\n" + failures.join(",\n");
 }
 testComparisons.expected = "no failures reported!";
 test(testComparisons);
 
-// BEGIN MANDELBROT STUFF
-// XXXbz I would dearly like to wrap it up into a function to avoid polluting
-// the global scope, but the function ends up heavyweight, and then we lose on
-// the jit.
-load("mandelbrot-results.js");
-//function testMandelbrotAll() {
-  // Configuration options that affect which codepaths we follow.
-  var doImageData = true;
-  var avoidSparseArray = true;
-
-  // Control of iteration numbers and sizing.  We'll do
-  // scaler * colorNames.length iterations or so before deciding that we
-  // don't escape.
-  const scaler = 5;
-  const numRows = 600;
-  const numCols = 600;
-
-  // For now, avoid hitting memory pressure
-  gcparam("maxBytes", 1300000000); 
-  gcparam("maxMallocBytes", 1300000000); 
-
-  const colorNames = [
-    "black",
-    "green",
-    "blue",
-    "red",
-    "purple",
-    "orange",
-    "cyan",
-    "yellow",
-    "magenta",
-    "brown",
-    "pink",
-    "chartreuse",
-    "darkorange",
-    "crimson",
-    "gray",
-    "deeppink",
-    "firebrick",
-    "lavender",
-    "lawngreen",
-    "lightsalmon",
-    "lime",
-    "goldenrod"
-  ];
-  const threshold = (colorNames.length - 1) * scaler;
-
-  // Now set up our colors
-  var colors = [];
-  // 3-part for loop (iterators buggy, we will add a separate test for them)
-  for (var colorNameIdx = 0; colorNameIdx < colorNames.length; ++colorNameIdx) {
-  //for (var colorNameIdx in colorNames) {
-    colorNameIdx = parseInt(colorNameIdx);
-    colors.push([colorNameIdx, colorNameIdx, colorNameIdx, 0]);
-  }
-
-  // Storage for our point data
-  var points;
-
-  var scratch = {};
-  var scratchZ = {};
-  function complexMult(a, b) {
-    var newr = a.r * b.r - a.i * b.i;
-    var newi = a.r * b.i + a.i * b.r;
-    scratch.r = newr;
-    scratch.i = newi;
-    return scratch;
-  }
-  function complexAdd(a, b) {
-    scratch.r = a.r + b.r;
-    scratch.i = a.i + b.i;
-    return scratch;
-  }
-  function abs(a) {
-    return Math.sqrt(a.r * a.r + a.i * a.i);
-  }
-
-  function escapeAbsDiff(normZ, absC) {
-    var absZ = Math.sqrt(normZ);
-    return normZ > absZ + absC;
-  }
-
-  function escapeNorm2(normZ) {
-    return normZ > 4;
-  }
-
-  function fuzzyColors(i) {
-    return Math.floor(i / scaler) + 1;
-  }
-
-  function moddedColors(i) {
-    return (i % (colorNames.length - 1)) + 1;
-  }
-
-  function computeEscapeSpeedObjects(real, imag) {
-    var c = { r: real, i: imag }
-    scratchZ.r = scratchZ.i = 0;
-    var absC = abs(c);
-    for (var i = 0; i < threshold; ++i) {
-      scratchZ = complexAdd(c, complexMult(scratchZ, scratchZ));
-      if (escape(scratchZ.r * scratchZ.r + scratchZ.i * scratchZ.i,
-                 absC)) {
-        return colorMap(i);
-      }
-    }
-    return 0;
-  }
-
-  function computeEscapeSpeedOneObject(real, imag) {
-    // fold in the fact that we start with 0
-    var r = real;
-    var i = imag;
-    var absC = abs({r: real, i: imag});
-    for (var j = 0; j < threshold; ++j) {
-      var r2 = r * r;
-      var i2 = i * i;
-      if (escape(r2 + i2, absC)) {
-        return colorMap(j);
-      }
-      i = 2 * r * i + imag;
-      r = r2 - i2 + real;
-    }
-    return 0;
-  }
-
-  function computeEscapeSpeedDoubles(real, imag) {
-    // fold in the fact that we start with 0
-    var r = real;
-    var i = imag;
-    var absC = Math.sqrt(real * real + imag * imag);
-    for (var j = 0; j < threshold; ++j) {
-      var r2 = r * r;
-      var i2 = i * i;
-      if (escape(r2 + i2, absC)) {
-        return colorMap(j);
-      }
-      i = 2 * r * i + imag;
-      r = r2 - i2 + real;
-    }
-    return 0;
-  }
-
-  var computeEscapeSpeed = computeEscapeSpeedDoubles;
-  var escape = escapeNorm2;
-  var colorMap = fuzzyColors;
-
-  function addPointOrig(pointArray, n, i, j) {
-    if (!points[n]) {
-      points[n] = [];
-      points[n].push([i, j, 1, 1]);
-    } else {
-      var point = points[n][points[n].length-1];
-      if (point[0] == i && point[1] == j - point[3]) {
-        ++point[3];
-      } else {
-        points[n].push([i, j, 1, 1]);
-      }
-    }
-  }
-
-  function addPointImagedata(pointArray, n, col, row) {
-    var slotIdx = ((row * numCols) + col) * 4;
-    pointArray[slotIdx] = colors[n][0];
-    pointArray[slotIdx+1] = colors[n][1];
-    pointArray[slotIdx+2] = colors[n][2];
-    pointArray[slotIdx+3] = colors[n][3];
-  }
-
-  function createMandelSet() {
-    var realRange = { min: -2.1, max: 1 };
-    var imagRange = { min: -1.5, max: 1.5 };
-
-    var addPoint;
-    if (doImageData) {
-      addPoint = addPointImagedata;
-      points = new Array(4*numCols*numRows);
-      if (avoidSparseArray) {
-        for (var idx = 0; idx < 4*numCols*numRows; ++idx) {
-          points[idx] = 0;
-        }
-      }
-    } else {
-      addPoint = addPointOrig;
-      points = [];
-    }
-    var realStep = (realRange.max - realRange.min)/numCols;
-    var imagStep = (imagRange.min - imagRange.max)/numRows;
-    for (var i = 0, curReal = realRange.min;
-         i < numCols;
-         ++i, curReal += realStep) {
-      for (var j = 0, curImag = imagRange.max;
-           j < numRows;
-           ++j, curImag += imagStep) {
-        var n = computeEscapeSpeed(curReal, curImag);
-        addPoint(points, n, i, j)
-      }
-    }
-    var result;
-    if (doImageData) {
-      if (colorMap == fuzzyColors) {
-        result = mandelbrotImageDataFuzzyResult;
-      } else {
-        result = mandelbrotImageDataModdedResult;
-      }
-    } else {
-      result = mandelbrotNoImageDataResult;
-    }
-    return points.toSource() == result;
-  }
-
-  createMandelSet.expected = true;
-
-  const escapeTests = [ escapeAbsDiff ];
-  const colorMaps = [ fuzzyColors, moddedColors ];
-  const escapeComputations = [ computeEscapeSpeedObjects,
-                               computeEscapeSpeedOneObject,
-                               computeEscapeSpeedDoubles ];
-  // Test all possible escape-speed generation codepaths, using the
-  // imageData + sparse array avoidance storage.
-  doImageData = true;
-  avoidSparseArray = true;
-  for (var escapeIdx in escapeTests) {
-    escape = escapeTests[escapeIdx];
-    for (var colorMapIdx in colorMaps) {
-      colorMap = colorMaps[colorMapIdx];
-      for (var escapeComputationIdx in escapeComputations) {
-        computeEscapeSpeed = escapeComputations[escapeComputationIdx];
-        test(createMandelSet);
-      }
-    }
-  }
-
-  // Test all possible storage strategies. Note that we already tested
-  // doImageData == true with avoidSparseArray == true.
-  escape = escapeAbsDiff;
-  colorMap = fuzzyColors; // This part doesn't really matter too much here
-  computeEscapeSpeed = computeEscapeSpeedDoubles;
-
-  doImageData = true;
-  avoidSparseArray = false; 
-  test(createMandelSet);
-
-  escape = escapeNorm2;
-  doImageData = false;  // avoidSparseArray doesn't matter here
-  test(createMandelSet);
-//}
-//testMandelbrotAll();
-// END MANDELBROT STUFF
-
 /* NOTE: Keep this test last, since it screws up all for...in loops after it. */
 function testGlobalProtoAccess() {
     return "ok";
 }
 this.__proto__.a = 3; for (var j = 0; j < 4; ++j) { [a]; }
 testGlobalProtoAccess.expected = "ok";
 test(testGlobalProtoAccess);