Bug 603077: OOM safety for JM assembler buffer, r=dvander
authorDavid Mandelin <dmandelin@mozilla.com>
Thu, 14 Oct 2010 16:33:49 -0700
changeset 56037 67a041f5f13b6525051e21f79c7bc3bb5e8315a4
parent 56036 59b339eca10ffcfbd4d5114ddbdb50334770e42e
child 56038 b8fd0155fcd2c43a144570266aa2fbca75bbfb78
push id16371
push userrsayre@mozilla.com
push dateMon, 18 Oct 2010 17:04:27 +0000
treeherderautoland@eae6bdacf6d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs603077
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 603077: OOM safety for JM assembler buffer, r=dvander
js/src/assembler/assembler/ARMAssembler.cpp
js/src/assembler/assembler/ARMAssembler.h
js/src/assembler/assembler/ARMv7Assembler.h
js/src/assembler/assembler/AbstractMacroAssembler.h
js/src/assembler/assembler/AssemblerBuffer.h
js/src/assembler/assembler/X86Assembler.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/FastOps.cpp
js/src/yarr/yarr/RegexJIT.cpp
--- a/js/src/assembler/assembler/ARMAssembler.cpp
+++ b/js/src/assembler/assembler/ARMAssembler.cpp
@@ -411,26 +411,30 @@ inline void ARMAssembler::fixUpOffsets(v
 void* ARMAssembler::executableCopy(ExecutablePool* allocator)
 {
     // 64-bit alignment is required for next constant pool and JIT code as well
     m_buffer.flushWithoutBarrier(true);
     if (m_buffer.uncheckedSize() & 0x7)
         bkpt(0);
 
     void * data = m_buffer.executableCopy(allocator);
-    fixUpOffsets(data);
+    if (data)
+        fixUpOffsets(data);
     return data;
 }
 
 // This just dumps the code into the specified buffer, fixing up absolute
 // offsets and literal pool loads as it goes. The buffer is assumed to be large
 // enough to hold the code, and any pre-existing literal pool is assumed to
 // have been flushed.
 void* ARMAssembler::executableCopy(void * buffer)
 {
+    if (m_buffer.oom())
+        return NULL;
+
     ASSERT(m_buffer.sizeOfConstantPool() == 0);
 
     memcpy(buffer, m_buffer.data(), m_buffer.size());
     fixUpOffsets(buffer);
     return buffer;
 }
 
 } // namespace JSC
--- a/js/src/assembler/assembler/ARMAssembler.h
+++ b/js/src/assembler/assembler/ARMAssembler.h
@@ -141,16 +141,17 @@ namespace JSC {
 #endif
 
         typedef ARMRegisters::RegisterID RegisterID;
         typedef ARMRegisters::FPRegisterID FPRegisterID;
         typedef AssemblerBufferWithConstantPool<2048, 4, 4, ARMAssembler> ARMBuffer;
         typedef SegmentedVector<int, 64> Jumps;
 
         unsigned char *buffer() const { return m_buffer.buffer(); }
+        bool oom() const { return m_buffer.oom(); }
 
         // ARM conditional constants
         typedef enum {
             EQ = 0x00000000, // Zero
             NE = 0x10000000, // Non-zero
             CS = 0x20000000,
             CC = 0x30000000,
             MI = 0x40000000,
--- a/js/src/assembler/assembler/ARMv7Assembler.h
+++ b/js/src/assembler/assembler/ARMv7Assembler.h
@@ -1900,16 +1900,17 @@ private:
 
 
         // Administrative methods:
 
         size_t size() const { return m_buffer.size(); }
         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
         void* data() const { return m_buffer.data(); }
         void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
+        bool oom() const { return m_buffer.oom(); }
 
     private:
         AssemblerBuffer m_buffer;
     } m_formatter;
 
     Vector<LinkRecord> m_jumpsToLink;
 };
 
--- a/js/src/assembler/assembler/AbstractMacroAssembler.h
+++ b/js/src/assembler/assembler/AbstractMacroAssembler.h
@@ -441,16 +441,21 @@ public:
         return m_assembler.size();
     }
 
     unsigned char *buffer()
     {
         return m_assembler.buffer();
     }
 
+    bool oom()
+    {
+        return m_assembler.oom();
+    }
+
     void* executableCopy(void* buffer)
     {
         return m_assembler.executableCopy(buffer);
     }
 
     Label label()
     {
         return Label(this);
--- a/js/src/assembler/assembler/AssemblerBuffer.h
+++ b/js/src/assembler/assembler/AssemblerBuffer.h
@@ -43,16 +43,17 @@ namespace JSC {
 
     class AssemblerBuffer {
         static const int inlineCapacity = 256;
     public:
         AssemblerBuffer()
             : m_buffer(m_inlineBuffer)
             , m_capacity(inlineCapacity)
             , m_size(0)
+            , m_oom(false)
         {
         }
 
         ~AssemblerBuffer()
         {
             if (m_buffer != m_inlineBuffer)
                 free(m_buffer);
         }
@@ -122,59 +123,106 @@ namespace JSC {
             return m_buffer;
         }
 
         int size() const
         {
             return m_size;
         }
 
+        bool oom() const
+        {
+            return m_oom;
+        }
+
+        /*
+         * The user must check for a NULL return value, which means
+         * no code was generated, or there was an OOM.
+         */
         void* executableCopy(ExecutablePool* allocator)
         {
+            if (m_oom)
+                return 0;
+
             if (!m_size)
                 return 0;
 
             void* result = allocator->alloc(m_size);
 
             if (!result)
                 return 0;
 
             ExecutableAllocator::makeWritable(result, m_size);
 
             return memcpy(result, m_buffer, m_size);
         }
 
         unsigned char *buffer() const {
+            ASSERT(!m_oom);
             return reinterpret_cast<unsigned char *>(m_buffer);
         }
 
     protected:
         void append(const char* data, int size)
         {
             if (m_size > m_capacity - size)
                 grow(size);
 
+            // If we OOM and size > inlineCapacity, this would crash.
+            if (m_oom)
+                return;
             memcpy(m_buffer + m_size, data, size);
             m_size += size;
         }
 
+        /*
+         * OOM handling: This class can OOM in the grow() method trying to
+         * allocate a new buffer. In response to an OOM, we need to avoid
+         * crashing and report the error. We also want to make it so that
+         * users of this class need to check for OOM only at certain points
+         * and not after every operation.
+         *
+         * Our strategy for handling an OOM is to set m_oom, and then set
+         * m_size to 0, preserving the current buffer. This way, the user
+         * can continue assembling into the buffer, deferring OOM checking
+         * until the user wants to read code out of the buffer.
+         *
+         * See also the |executableCopy| and |buffer| methods.
+         */
+
         void grow(int extraCapacity = 0)
         {
-            m_capacity += m_capacity / 2 + extraCapacity;
+            int newCapacity = m_capacity + m_capacity / 2 + extraCapacity;
+            char* newBuffer;
 
             if (m_buffer == m_inlineBuffer) {
-                char* newBuffer = static_cast<char*>(malloc(m_capacity));
-                m_buffer = static_cast<char*>(memcpy(newBuffer, m_buffer, m_size));
-            } else
-                m_buffer = static_cast<char*>(realloc(m_buffer, m_capacity));
+                newBuffer = static_cast<char*>(malloc(newCapacity));
+                if (!newBuffer) {
+                    m_size = 0;
+                    m_oom = true;
+                    return;
+                }
+                memcpy(newBuffer, m_buffer, m_size);
+            } else {
+                newBuffer = static_cast<char*>(realloc(m_buffer, newCapacity));
+                if (!newBuffer) {
+                    m_size = 0;
+                    m_oom = true;
+                    return;
+                }
+            }
+
+            m_buffer = newBuffer;
+            m_capacity = newCapacity;
         }
 
         char m_inlineBuffer[inlineCapacity];
         char* m_buffer;
         int m_capacity;
         int m_size;
+        bool m_oom;
     };
 
 } // namespace JSC
 
 #endif // ENABLE(ASSEMBLER)
 
 #endif // AssemblerBuffer_h
--- a/js/src/assembler/assembler/X86Assembler.h
+++ b/js/src/assembler/assembler/X86Assembler.h
@@ -358,16 +358,17 @@ public:
 #ifdef JS_METHODJIT_SPEW
       : isOOLPath(false)
 #endif
     {
     }
 
     size_t size() const { return m_formatter.size(); }
     unsigned char *buffer() const { return m_formatter.buffer(); }
+    bool oom() const { return m_formatter.oom(); }
 
     // Stack operations:
 
     void push_r(RegisterID reg)
     {
         js::JaegerSpew(js::JSpew_Insns,
                        IPFX "push       %s\n", MAYBE_PAD, nameIReg(reg));
         m_formatter.oneByteOp(OP_PUSH_EAX, reg);
@@ -2217,22 +2218,23 @@ public:
     static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
     {
         return dst.m_offset - src.m_offset;
     }
     
     void* executableCopy(ExecutablePool* allocator)
     {
         void* copy = m_formatter.executableCopy(allocator);
-        ASSERT(copy);
         return copy;
     }
 
     void* executableCopy(void* buffer)
     {
+        if (m_formatter.oom())
+            return NULL;
         return memcpy(buffer, m_formatter.buffer(), size());
     }
 
 private:
 
     static void setPointer(void* where, void* value)
     {
         js::JaegerSpew(js::JSpew_Insns,
@@ -2536,16 +2538,17 @@ private:
             m_buffer.putIntUnchecked(0);
             return JmpSrc(m_buffer.size());
         }
 
         // Administrative methods:
 
         size_t size() const { return m_buffer.size(); }
         unsigned char *buffer() const { return m_buffer.buffer(); }
+        bool oom() const { return m_buffer.oom(); }
         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
         void* data() const { return m_buffer.data(); }
         void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
 
     private:
 
         // Internals; ModRm and REX formatters.
 
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -62,16 +62,24 @@
 using namespace js;
 using namespace js::mjit;
 #if defined JS_POLYIC
 using namespace js::mjit::ic;
 #endif
 
 #define ADD_CALLSITE(stub) if (debugMode) addCallSite(__LINE__, (stub))
 
+#define RETURN_IF_OOM(retval)                    \
+    JS_BEGIN_MACRO                               \
+        if (masm.oom() || stubcc.masm.oom()) {   \
+            js_ReportOutOfMemory(cx);            \
+            return retval;                       \
+        }                                        \
+    JS_END_MACRO
+
 #if defined(JS_METHODJIT_SPEW)
 static const char *OpcodeNames[] = {
 # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) #name,
 # include "jsopcode.tbl"
 # undef OPDEF
 };
 #endif
 
@@ -314,16 +322,18 @@ CompileStatus
 mjit::Compiler::generateEpilogue()
 {
     return Compile_Okay;
 }
 
 CompileStatus
 mjit::Compiler::finishThisUp(JITScript **jitp)
 {
+    RETURN_IF_OOM(Compile_Error);
+
     for (size_t i = 0; i < branchPatches.length(); i++) {
         Label label = labelOf(branchPatches[i].pc);
         branchPatches[i].jump.linkTo(label, &masm);
     }
 
 #ifdef JS_CPU_ARM
     masm.forceFlushConstantPool();
     stubcc.masm.forceFlushConstantPool();
@@ -337,17 +347,17 @@ mjit::Compiler::finishThisUp(JITScript *
     JSC::ExecutablePool *execPool = getExecPool(totalSize);
     if (!execPool)
         return Compile_Abort;
 
     uint8 *result = (uint8 *)execPool->alloc(totalSize);
     JSC::ExecutableAllocator::makeWritable(result, totalSize);
     masm.executableCopy(result);
     stubcc.masm.executableCopy(result + masm.size());
-
+    
     JSC::LinkBuffer fullCode(result, totalSize);
     JSC::LinkBuffer stubCode(result + masm.size(), stubcc.size());
 
     size_t totalBytes = sizeof(JITScript) +
                         sizeof(void *) * script->length +
 #if defined JS_MONOIC
                         sizeof(ic::MICInfo) * mics.length() +
                         sizeof(ic::CallICInfo) * callICs.length() +
@@ -950,118 +960,132 @@ mjit::Compiler::generateMethod()
           END_CASE(JSOP_TYPEOF)
 
           BEGIN_CASE(JSOP_VOID)
             frame.pop();
             frame.push(UndefinedValue());
           END_CASE(JSOP_VOID)
 
           BEGIN_CASE(JSOP_INCNAME)
-            jsop_nameinc(op, STRICT_VARIANT(stubs::IncName), fullAtomIndex(PC));
+            if (!jsop_nameinc(op, STRICT_VARIANT(stubs::IncName), fullAtomIndex(PC)))
+                return Compile_Error;
             break;
           END_CASE(JSOP_INCNAME)
 
           BEGIN_CASE(JSOP_INCGNAME)
             jsop_gnameinc(op, STRICT_VARIANT(stubs::IncGlobalName), fullAtomIndex(PC));
             break;
           END_CASE(JSOP_INCGNAME)
 
           BEGIN_CASE(JSOP_INCPROP)
-            jsop_propinc(op, STRICT_VARIANT(stubs::IncProp), fullAtomIndex(PC));
+            if (!jsop_propinc(op, STRICT_VARIANT(stubs::IncProp), fullAtomIndex(PC)))
+                return Compile_Error;
             break;
           END_CASE(JSOP_INCPROP)
 
           BEGIN_CASE(JSOP_INCELEM)
             jsop_eleminc(op, STRICT_VARIANT(stubs::IncElem));
           END_CASE(JSOP_INCELEM)
 
           BEGIN_CASE(JSOP_DECNAME)
-            jsop_nameinc(op, STRICT_VARIANT(stubs::DecName), fullAtomIndex(PC));
+            if (!jsop_nameinc(op, STRICT_VARIANT(stubs::DecName), fullAtomIndex(PC)))
+                return Compile_Error;
             break;
           END_CASE(JSOP_DECNAME)
 
           BEGIN_CASE(JSOP_DECGNAME)
             jsop_gnameinc(op, STRICT_VARIANT(stubs::DecGlobalName), fullAtomIndex(PC));
             break;
           END_CASE(JSOP_DECGNAME)
 
           BEGIN_CASE(JSOP_DECPROP)
-            jsop_propinc(op, STRICT_VARIANT(stubs::DecProp), fullAtomIndex(PC));
+            if (!jsop_propinc(op, STRICT_VARIANT(stubs::DecProp), fullAtomIndex(PC)))
+                return Compile_Error;
             break;
           END_CASE(JSOP_DECPROP)
 
           BEGIN_CASE(JSOP_DECELEM)
             jsop_eleminc(op, STRICT_VARIANT(stubs::DecElem));
           END_CASE(JSOP_DECELEM)
 
           BEGIN_CASE(JSOP_NAMEINC)
-            jsop_nameinc(op, STRICT_VARIANT(stubs::NameInc), fullAtomIndex(PC));
+            if (!jsop_nameinc(op, STRICT_VARIANT(stubs::NameInc), fullAtomIndex(PC)))
+                return Compile_Error;
             break;
           END_CASE(JSOP_NAMEINC)
 
           BEGIN_CASE(JSOP_GNAMEINC)
             jsop_gnameinc(op, STRICT_VARIANT(stubs::GlobalNameInc), fullAtomIndex(PC));
             break;
           END_CASE(JSOP_GNAMEINC)
 
           BEGIN_CASE(JSOP_PROPINC)
-            jsop_propinc(op, STRICT_VARIANT(stubs::PropInc), fullAtomIndex(PC));
+            if (!jsop_propinc(op, STRICT_VARIANT(stubs::PropInc), fullAtomIndex(PC)))
+                return Compile_Error;
             break;
           END_CASE(JSOP_PROPINC)
 
           BEGIN_CASE(JSOP_ELEMINC)
             jsop_eleminc(op, STRICT_VARIANT(stubs::ElemInc));
           END_CASE(JSOP_ELEMINC)
 
           BEGIN_CASE(JSOP_NAMEDEC)
-            jsop_nameinc(op, STRICT_VARIANT(stubs::NameDec), fullAtomIndex(PC));
+            if (!jsop_nameinc(op, STRICT_VARIANT(stubs::NameDec), fullAtomIndex(PC)))
+                return Compile_Error;
             break;
           END_CASE(JSOP_NAMEDEC)
 
           BEGIN_CASE(JSOP_GNAMEDEC)
             jsop_gnameinc(op, STRICT_VARIANT(stubs::GlobalNameDec), fullAtomIndex(PC));
             break;
           END_CASE(JSOP_GNAMEDEC)
 
           BEGIN_CASE(JSOP_PROPDEC)
-            jsop_propinc(op, STRICT_VARIANT(stubs::PropDec), fullAtomIndex(PC));
+            if (!jsop_propinc(op, STRICT_VARIANT(stubs::PropDec), fullAtomIndex(PC)))
+                return Compile_Error;
             break;
           END_CASE(JSOP_PROPDEC)
 
           BEGIN_CASE(JSOP_ELEMDEC)
             jsop_eleminc(op, STRICT_VARIANT(stubs::ElemDec));
           END_CASE(JSOP_ELEMDEC)
 
           BEGIN_CASE(JSOP_GETTHISPROP)
             /* Push thisv onto stack. */
             jsop_this();
-            jsop_getprop(script->getAtom(fullAtomIndex(PC)));
+            if (!jsop_getprop(script->getAtom(fullAtomIndex(PC))))
+                return Compile_Error;
           END_CASE(JSOP_GETTHISPROP);
 
           BEGIN_CASE(JSOP_GETARGPROP)
             /* Push arg onto stack. */
             jsop_getarg(GET_SLOTNO(PC));
-            jsop_getprop(script->getAtom(fullAtomIndex(&PC[ARGNO_LEN])));
+            if (!jsop_getprop(script->getAtom(fullAtomIndex(&PC[ARGNO_LEN]))))
+                return Compile_Error;
           END_CASE(JSOP_GETARGPROP)
 
           BEGIN_CASE(JSOP_GETLOCALPROP)
             frame.pushLocal(GET_SLOTNO(PC));
-            jsop_getprop(script->getAtom(fullAtomIndex(&PC[SLOTNO_LEN])));
+            if (!jsop_getprop(script->getAtom(fullAtomIndex(&PC[SLOTNO_LEN]))))
+                return Compile_Error;
           END_CASE(JSOP_GETLOCALPROP)
 
           BEGIN_CASE(JSOP_GETPROP)
-            jsop_getprop(script->getAtom(fullAtomIndex(PC)));
+            if (!jsop_getprop(script->getAtom(fullAtomIndex(PC))))
+                return Compile_Error;
           END_CASE(JSOP_GETPROP)
 
           BEGIN_CASE(JSOP_LENGTH)
-            jsop_length();
+            if (!jsop_length())
+                return Compile_Error;
           END_CASE(JSOP_LENGTH)
 
           BEGIN_CASE(JSOP_GETELEM)
-            jsop_getelem();
+            if (!jsop_getelem())
+                return Compile_Error;
           END_CASE(JSOP_GETELEM)
 
           BEGIN_CASE(JSOP_SETELEM)
             jsop_setelem();
           END_CASE(JSOP_SETELEM);
 
           BEGIN_CASE(JSOP_CALLNAME)
             prepareStubCall(Uses(0));
@@ -1342,22 +1366,24 @@ mjit::Compiler::generateMethod()
           }
           END_CASE(JSOP_LOCALDEC)
 
           BEGIN_CASE(JSOP_BINDNAME)
             jsop_bindname(fullAtomIndex(PC));
           END_CASE(JSOP_BINDNAME)
 
           BEGIN_CASE(JSOP_SETPROP)
-            jsop_setprop(script->getAtom(fullAtomIndex(PC)));
+            if (!jsop_setprop(script->getAtom(fullAtomIndex(PC))))
+                return Compile_Error;
           END_CASE(JSOP_SETPROP)
 
           BEGIN_CASE(JSOP_SETNAME)
           BEGIN_CASE(JSOP_SETMETHOD)
-            jsop_setprop(script->getAtom(fullAtomIndex(PC)));
+            if (!jsop_setprop(script->getAtom(fullAtomIndex(PC))))
+                return Compile_Error;
           END_CASE(JSOP_SETNAME)
 
           BEGIN_CASE(JSOP_THROW)
             prepareStubCall(Uses(1));
             stubCall(stubs::Throw);
             frame.pop();
           END_CASE(JSOP_THROW)
 
@@ -1365,17 +1391,18 @@ mjit::Compiler::generateMethod()
             prepareStubCall(Uses(2));
             stubCall(stubs::In);
             frame.popn(2);
             frame.takeReg(Registers::ReturnReg);
             frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, Registers::ReturnReg);
           END_CASE(JSOP_IN)
 
           BEGIN_CASE(JSOP_INSTANCEOF)
-            jsop_instanceof();
+            if (!jsop_instanceof())
+                return Compile_Error;
           END_CASE(JSOP_INSTANCEOF)
 
           BEGIN_CASE(JSOP_EXCEPTION)
           {
             JS_STATIC_ASSERT(sizeof(cx->throwing) == 4);
             RegisterID reg = frame.allocReg();
             masm.loadPtr(FrameAddress(offsetof(VMFrame, cx)), reg);
             masm.store32(Imm32(JS_FALSE), Address(reg, offsetof(JSContext, throwing)));
@@ -1593,17 +1620,18 @@ mjit::Compiler::generateMethod()
 
           BEGIN_CASE(JSOP_STOP)
             /* Safe point! */
             emitReturn(NULL);
             goto done;
           END_CASE(JSOP_STOP)
 
           BEGIN_CASE(JSOP_GETXPROP)
-            jsop_xname(script->getAtom(fullAtomIndex(PC)));
+            if (!jsop_xname(script->getAtom(fullAtomIndex(PC))))
+                return Compile_Error;
           END_CASE(JSOP_GETXPROP)
 
           BEGIN_CASE(JSOP_ENTERBLOCK)
             enterBlock(script->getObject(fullAtomIndex(PC)));
           END_CASE(JSOP_ENTERBLOCK);
 
           BEGIN_CASE(JSOP_LEAVEBLOCK)
             leaveBlock();
@@ -1698,18 +1726,20 @@ mjit::Compiler::generateMethod()
           BEGIN_CASE(JSOP_GLOBALINC)
           BEGIN_CASE(JSOP_GLOBALDEC)
             /* Advances PC automatically. */
             jsop_globalinc(op, GET_SLOTNO(PC));
             break;
           END_CASE(JSOP_GLOBALINC)
 
           BEGIN_CASE(JSOP_BEGIN)
-            if (isConstructing)
-                constructThis();
+            if (isConstructing) {
+                if (!constructThis())
+                    return Compile_Error;
+            }
           END_CASE(JSOP_BEGIN)
 
           default:
            /* Sorry, this opcode isn't implemented yet. */
 #ifdef JS_METHODJIT_SPEW
             JaegerSpew(JSpew_Abort, "opcode %s not handled yet (%s line %d)\n", OpcodeNames[op],
                        script->filename, js_PCToLineNumber(cx, script, PC));
 #endif
@@ -2387,17 +2417,17 @@ mjit::Compiler::jsop_callprop_slow(JSAto
     masm.move(ImmPtr(atom), Registers::ArgReg1);
     stubCall(stubs::CallProp);
     frame.pop();
     frame.pushSynced();
     frame.pushSynced();
     return true;
 }
 
-void
+bool
 mjit::Compiler::jsop_length()
 {
     FrameEntry *top = frame.peek(-1);
 
     if (top->isTypeKnown() && top->getKnownType() == JSVAL_TYPE_STRING) {
         if (top->isConstant()) {
             JSString *str = top->getValue().toString();
             Value v;
@@ -2406,26 +2436,27 @@ mjit::Compiler::jsop_length()
             frame.push(v);
         } else {
             RegisterID str = frame.ownRegForData(top);
             masm.loadPtr(Address(str, offsetof(JSString, mLengthAndFlags)), str);
             masm.rshiftPtr(Imm32(JSString::FLAGS_LENGTH_SHIFT), str);
             frame.pop();
             frame.pushTypedPayload(JSVAL_TYPE_INT32, str);
         }
-        return;
+        return true;
     }
 
 #if defined JS_POLYIC
-    jsop_getprop(cx->runtime->atomState.lengthAtom);
+    return jsop_getprop(cx->runtime->atomState.lengthAtom);
 #else
     prepareStubCall(Uses(1));
     stubCall(stubs::Length);
     frame.pop();
     frame.pushSynced();
+    return true;
 #endif
 }
 
 #ifdef JS_MONOIC
 void
 mjit::Compiler::passMICAddress(MICGenInfo &mic)
 {
     mic.addrLabel = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
@@ -2434,27 +2465,27 @@ mjit::Compiler::passMICAddress(MICGenInf
 
 #if defined JS_POLYIC
 void
 mjit::Compiler::passPICAddress(PICGenInfo &pic)
 {
     pic.addrLabel = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
 }
 
-void
+bool
 mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck)
 {
     FrameEntry *top = frame.peek(-1);
 
     /* If the incoming type will never PIC, take slow path. */
     if (top->isTypeKnown() && top->getKnownType() != JSVAL_TYPE_OBJECT) {
         JS_ASSERT_IF(atom == cx->runtime->atomState.lengthAtom,
                      top->getKnownType() != JSVAL_TYPE_STRING);
         jsop_getprop_slow();
-        return;
+        return true;
     }
 
     /*
      * These two must be loaded first. The objReg because the string path
      * wants to read it, and the shapeReg because it could cause a spill that
      * the string path wouldn't sink back.
      */
     RegisterID objReg = Registers::ReturnReg;
@@ -2472,16 +2503,17 @@ mjit::Compiler::jsop_getprop(JSAtom *ato
         RegisterID reg = frame.tempRegForType(top);
         pic.typeReg = reg;
 
         /* Start the hot path where it's easy to patch it. */
         pic.fastPathStart = masm.label();
         Jump j = masm.testObject(Assembler::NotEqual, reg);
 
         /* GETPROP_INLINE_TYPE_GUARD is used to patch the jmp, not cmp. */
+        RETURN_IF_OOM(false);
         JS_ASSERT(masm.differenceBetween(pic.fastPathStart, masm.label()) == GETPROP_INLINE_TYPE_GUARD);
 
         pic.typeCheck = stubcc.linkExit(j, Uses(1));
         pic.hasTypeCheck = true;
     } else {
         pic.fastPathStart = masm.label();
         pic.hasTypeCheck = false;
         pic.typeReg = Registers::ReturnReg;
@@ -2531,18 +2563,18 @@ mjit::Compiler::jsop_getprop(JSAtom *ato
     masm.loadPayload(slot, objReg);
     DBGLABEL(dbgDataLoad);
 #elif defined JS_PUNBOX64
     Label inlineValueLoadLabel =
         masm.loadValueAsComponents(slot, shapeReg, objReg);
 #endif
     pic.storeBack = masm.label();
 
-
     /* Assert correctness of hardcoded offsets. */
+    RETURN_IF_OOM(false);
 #if defined JS_NUNBOX32
     JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD);
     JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgTypeLoad) == GETPROP_TYPE_LOAD);
     JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDataLoad) == GETPROP_DATA_LOAD);
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel) == GETPROP_INLINE_SHAPE_OFFSET);
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
 #elif defined JS_PUNBOX64
     pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.storeBack, dslotsLoadLabel);
@@ -2559,20 +2591,21 @@ mjit::Compiler::jsop_getprop(JSAtom *ato
     /* GETPROP_INLINE_TYPE_GUARD's validity is asserted above. */
 
     pic.objReg = objReg;
     frame.pushRegs(shapeReg, objReg);
 
     stubcc.rejoin(Changes(1));
 
     pics.append(pic);
+    return true;
 }
 
 #ifdef JS_POLYIC
-void
+bool
 mjit::Compiler::jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg,
                                  RegisterID idReg, RegisterID shapeReg)
 {
     PICGenInfo pic(ic::PICInfo::GETELEM);
 
     pic.objRemat = frame.dataRematInfo(obj);
     pic.idRemat = frame.dataRematInfo(id);
     pic.shapeReg = shapeReg;
@@ -2632,16 +2665,17 @@ mjit::Compiler::jsop_getelem_pic(FrameEn
     Label inlineValueOffsetLabel =
         masm.loadValueAsComponents(slot, shapeReg, objReg);
 #endif
     pic.storeBack = masm.label();
 
     pic.objReg = objReg;
     pic.idReg = idReg;
 
+    RETURN_IF_OOM(false);
 #if defined JS_NUNBOX32
     JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslotsLoad) == GETELEM_DSLOTS_LOAD);
     JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgTypeLoad) == GETELEM_TYPE_LOAD);
     JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDataLoad) == GETELEM_DATA_LOAD);
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineAtomOffsetLabel) == GETELEM_INLINE_ATOM_OFFSET);
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineAtomJump) == GETELEM_INLINE_ATOM_JUMP);
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel) == GETELEM_INLINE_SHAPE_OFFSET);
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETELEM_INLINE_SHAPE_JUMP);
@@ -2663,16 +2697,17 @@ mjit::Compiler::jsop_getelem_pic(FrameEn
               pic.labels.getelem.inlineAtomOffset + GETELEM_INLINE_ATOM_JUMP);
 #endif
 
     JS_ASSERT(pic.idReg != pic.objReg);
     JS_ASSERT(pic.idReg != pic.shapeReg);
     JS_ASSERT(pic.objReg != pic.shapeReg);
 
     pics.append(pic);
+    return true;
 }
 #endif
 
 bool
 mjit::Compiler::jsop_callprop_generic(JSAtom *atom)
 {
     FrameEntry *top = frame.peek(-1);
 
@@ -2763,16 +2798,17 @@ mjit::Compiler::jsop_callprop_generic(JS
     DBGLABEL(dbgDataLoad);
 #elif defined JS_PUNBOX64
     Label inlineValueLoadLabel =
         masm.loadValueAsComponents(slot, shapeReg, objReg);
 #endif
     pic.storeBack = masm.label();
 
     /* Assert correctness of hardcoded offsets. */
+    RETURN_IF_OOM(false);
     JS_ASSERT(masm.differenceBetween(pic.fastPathStart, dbgInlineTypeGuard) == GETPROP_INLINE_TYPE_GUARD);
 #if defined JS_NUNBOX32
     JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD);
     JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgTypeLoad) == GETPROP_TYPE_LOAD);
     JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDataLoad) == GETPROP_DATA_LOAD);
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel) == GETPROP_INLINE_SHAPE_OFFSET);
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
 #elif defined JS_PUNBOX64
@@ -2809,17 +2845,18 @@ mjit::Compiler::jsop_callprop_str(JSAtom
 
     /* Force into a register because getprop won't expect a constant. */
     RegisterID reg = frame.allocReg();
 
     masm.move(ImmPtr(obj), reg);
     frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
 
     /* Get the property. */
-    jsop_getprop(atom);
+    if (!jsop_getprop(atom))
+        return false;
 
     /* Perform a swap. */
     frame.dup2();
     frame.shift(-3);
     frame.shift(-1);
 
     /* 4) Test if the function can take a primitive. */
 #ifdef DEBUG
@@ -2921,16 +2958,17 @@ mjit::Compiler::jsop_callprop_obj(JSAtom
     frame.dup();
     frame.pushRegs(shapeReg, objReg);
     frame.shift(-2);
 
     /* 
      * Assert correctness of hardcoded offsets.
      * No type guard: type is asserted.
      */
+    RETURN_IF_OOM(false);
 #if defined JS_NUNBOX32
     JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD);
     JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgTypeLoad) == GETPROP_TYPE_LOAD);
     JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDataLoad) == GETPROP_DATA_LOAD);
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel) == GETPROP_INLINE_SHAPE_OFFSET);
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
 #elif defined JS_PUNBOX64
     pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.storeBack, dslotsLoadLabel);
@@ -2963,26 +3001,26 @@ mjit::Compiler::jsop_callprop(JSAtom *at
         return jsop_callprop_slow(atom);
     }
 
     if (top->isTypeKnown())
         return jsop_callprop_obj(atom);
     return jsop_callprop_generic(atom);
 }
 
-void
+bool
 mjit::Compiler::jsop_setprop(JSAtom *atom)
 {
     FrameEntry *lhs = frame.peek(-2);
     FrameEntry *rhs = frame.peek(-1);
 
     /* If the incoming type will never PIC, take slow path. */
     if (lhs->isTypeKnown() && lhs->getKnownType() != JSVAL_TYPE_OBJECT) {
         jsop_setprop_slow(atom);
-        return;
+        return true;
     }
 
     JSOp op = JSOp(*PC);
 
     PICGenInfo pic(op == JSOP_SETMETHOD ? ic::PICInfo::SETMETHOD : ic::PICInfo::SET);
     pic.atom = atom;
 
     /* Guard that the type is an object. */
@@ -3078,16 +3116,17 @@ mjit::Compiler::jsop_setprop(JSAtom *ato
 
     /* Finish slow path. */
     {
         if (pic.hasTypeCheck)
             typeCheck.linkTo(stubcc.masm.label(), &stubcc.masm);
         stubcc.rejoin(Changes(1));
     }
 
+    RETURN_IF_OOM(false);
 #if defined JS_PUNBOX64
     pic.labels.setprop.dslotsLoadOffset = masm.differenceBetween(pic.storeBack, dslotsLoadLabel);
     pic.labels.setprop.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel);
     JS_ASSERT(masm.differenceBetween(inlineShapeOffsetLabel, dbgInlineShapeJump) == SETPROP_INLINE_SHAPE_JUMP);
     JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgAfterValueStore) == SETPROP_INLINE_STORE_VALUE);
 #elif defined JS_NUNBOX32
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel) == SETPROP_INLINE_SHAPE_OFFSET);
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == SETPROP_INLINE_SHAPE_JUMP);
@@ -3103,16 +3142,17 @@ mjit::Compiler::jsop_setprop(JSAtom *ato
     } else {
         JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgInlineStoreType) == SETPROP_INLINE_STORE_DYN_TYPE);
         JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgAfterValueStore) == SETPROP_INLINE_STORE_DYN_DATA);
         JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslots) == SETPROP_DSLOTS_BEFORE_DYNAMIC);
     }
 #endif
 
     pics.append(pic);
+    return true;
 }
 
 void
 mjit::Compiler::jsop_name(JSAtom *atom)
 {
     PICGenInfo pic(ic::PICInfo::NAME);
 
     pic.shapeReg = frame.allocReg();
@@ -3137,25 +3177,24 @@ mjit::Compiler::jsop_name(JSAtom *atom)
 
     JS_ASSERT(masm.differenceBetween(pic.fastPathStart, dbgJumpOffset) == SCOPENAME_JUMP_OFFSET);
 
     stubcc.rejoin(Changes(1));
 
     pics.append(pic);
 }
 
-void
+bool
 mjit::Compiler::jsop_xname(JSAtom *atom)
 {
     PICGenInfo pic(ic::PICInfo::XNAME);
 
     FrameEntry *fe = frame.peek(-1);
     if (fe->isNotType(JSVAL_TYPE_OBJECT)) {
-        jsop_getprop(atom);
-        return;
+        return jsop_getprop(atom);
     }
 
     if (!fe->isTypeKnown()) {
         Jump notObject = frame.testObject(Assembler::NotEqual, fe);
         stubcc.linkExit(notObject, Uses(1));
     }
 
     pic.shapeReg = frame.allocReg();
@@ -3179,16 +3218,17 @@ mjit::Compiler::jsop_xname(JSAtom *atom)
     frame.pop();
     frame.pushRegs(pic.shapeReg, pic.objReg);
 
     JS_ASSERT(masm.differenceBetween(pic.fastPathStart, dbgJumpOffset) == SCOPENAME_JUMP_OFFSET);
 
     stubcc.rejoin(Changes(1));
 
     pics.append(pic);
+    return true;
 }
 
 void
 mjit::Compiler::jsop_bindname(uint32 index)
 {
     PICGenInfo pic(ic::PICInfo::BIND);
 
     pic.shapeReg = frame.allocReg();
@@ -3238,38 +3278,40 @@ mjit::Compiler::jsop_bindname(uint32 ind
 void
 mjit::Compiler::jsop_name(JSAtom *atom)
 {
     prepareStubCall(Uses(0));
     stubCall(stubs::Name);
     frame.pushSynced();
 }
 
-void
+bool
 mjit::Compiler::jsop_xname(JSAtom *atom)
 {
-    jsop_getprop(atom);
+    return jsop_getprop(atom);
 }
 
-void
+bool
 mjit::Compiler::jsop_getprop(JSAtom *atom, bool typecheck)
 {
     jsop_getprop_slow();
+    return true;
 }
 
 bool
 mjit::Compiler::jsop_callprop(JSAtom *atom)
 {
     return jsop_callprop_slow(atom);
 }
 
-void
+bool
 mjit::Compiler::jsop_setprop(JSAtom *atom)
 {
     jsop_setprop_slow(atom);
+    return true;
 }
 
 void
 mjit::Compiler::jsop_bindname(uint32 index)
 {
     RegisterID reg = frame.allocReg();
     Address scopeChain(JSFrameReg, JSStackFrame::offsetOfScopeChain());
     masm.loadPtr(scopeChain, reg);
@@ -3396,17 +3438,17 @@ mjit::Compiler::jsop_gnameinc(JSOp op, V
     masm.move(ImmPtr(atom), Registers::ArgReg1);
     stubCall(stub);
     frame.pushSynced();
 #endif
 
     PC += JSOP_GNAMEINC_LENGTH;
 }
 
-void
+bool
 mjit::Compiler::jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index)
 {
     JSAtom *atom = script->getAtom(index);
 #if defined JS_POLYIC
     jsbytecode *next = &PC[JSOP_NAMEINC_LENGTH];
     bool pop = (JSOp(*next) == JSOP_POP) && !analysis[next].nincoming;
     int amt = (op == JSOP_NAMEINC || op == JSOP_INCNAME) ? -1 : 1;
 
@@ -3430,17 +3472,18 @@ mjit::Compiler::jsop_nameinc(JSOp op, Vo
         // V+1 OBJ V+1 OBJ
 
         frame.shift(-3);
         // OBJ OBJ V+1
 
         frame.shift(-1);
         // OBJ V+1
 
-        jsop_setprop(atom);
+        if (!jsop_setprop(atom))
+            return false;
         // V+1
 
         if (pop)
             frame.pop();
     } else {
         /* The pre-value is observed, making this more tricky. */
 
         jsop_name(atom);
@@ -3465,74 +3508,79 @@ mjit::Compiler::jsop_nameinc(JSOp op, Vo
         // N N+1 OBJ N+1 OBJ
 
         frame.shift(-3);
         // N OBJ OBJ N+1
 
         frame.shift(-1);
         // N OBJ N+1
 
-        jsop_setprop(atom);
+        if (!jsop_setprop(atom))
+            return false;
         // N N+1
 
         frame.pop();
         // N
     }
 
     if (pop)
         PC += JSOP_POP_LENGTH;
 #else
     prepareStubCall(Uses(0));
     masm.move(ImmPtr(atom), Registers::ArgReg1);
     stubCall(stub);
     frame.pushSynced();
 #endif
 
     PC += JSOP_NAMEINC_LENGTH;
+    return true;
 }
 
-void
+bool
 mjit::Compiler::jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index)
 {
     JSAtom *atom = script->getAtom(index);
 #if defined JS_POLYIC
     FrameEntry *objFe = frame.peek(-1);
     if (!objFe->isTypeKnown() || objFe->getKnownType() == JSVAL_TYPE_OBJECT) {
         jsbytecode *next = &PC[JSOP_PROPINC_LENGTH];
         bool pop = (JSOp(*next) == JSOP_POP) && !analysis[next].nincoming;
         int amt = (op == JSOP_PROPINC || op == JSOP_INCPROP) ? -1 : 1;
 
         if (pop || (op == JSOP_INCPROP || op == JSOP_DECPROP)) {
             /* These cases are easy, the original value is not observed. */
 
             frame.dup();
             // OBJ OBJ
 
-            jsop_getprop(atom);
+            if (!jsop_getprop(atom))
+                return false;
             // OBJ V
 
             frame.push(Int32Value(amt));
             // OBJ V 1
 
             /* Use sub since it calls ValueToNumber instead of string concat. */
             jsop_binary(JSOP_SUB, stubs::Sub);
             // OBJ V+1
 
-            jsop_setprop(atom);
+            if (!jsop_setprop(atom))
+                return false;
             // V+1
 
             if (pop)
                 frame.pop();
         } else {
             /* The pre-value is observed, making this more tricky. */
 
             frame.dup();
             // OBJ OBJ 
 
-            jsop_getprop(atom);
+            if (!jsop_getprop(atom))
+                return false;
             // OBJ V
 
             jsop_pos();
             // OBJ N
 
             frame.dup();
             // OBJ N N
 
@@ -3543,17 +3591,18 @@ mjit::Compiler::jsop_propinc(JSOp op, Vo
             // OBJ N N+1
 
             frame.dupAt(-3);
             // OBJ N N+1 OBJ
 
             frame.dupAt(-2);
             // OBJ N N+1 OBJ N+1
 
-            jsop_setprop(atom);
+            if (!jsop_setprop(atom))
+                return false;
             // OBJ N N+1 N+1
 
             frame.popn(2);
             // OBJ N
 
             frame.shimmy(1);
             // N
         }
@@ -3565,16 +3614,17 @@ mjit::Compiler::jsop_propinc(JSOp op, Vo
         prepareStubCall(Uses(1));
         masm.move(ImmPtr(atom), Registers::ArgReg1);
         stubCall(stub);
         frame.pop();
         frame.pushSynced();
     }
 
     PC += JSOP_PROPINC_LENGTH;
+    return true;
 }
 
 void
 mjit::Compiler::iter(uintN flags)
 {
     FrameEntry *fe = frame.peek(-1);
 
     /*
@@ -4119,30 +4169,30 @@ mjit::Compiler::jsop_getelem_slow()
 
 void
 mjit::Compiler::jsop_unbrand()
 {
     prepareStubCall(Uses(1));
     stubCall(stubs::Unbrand);
 }
 
-void
+bool
 mjit::Compiler::jsop_instanceof()
 {
     FrameEntry *lhs = frame.peek(-2);
     FrameEntry *rhs = frame.peek(-1);
 
     // The fast path applies only when both operands are objects.
     if (rhs->isNotType(JSVAL_TYPE_OBJECT) || lhs->isNotType(JSVAL_TYPE_OBJECT)) {
         prepareStubCall(Uses(2));
         stubCall(stubs::InstanceOf);
         frame.popn(2);
         frame.takeReg(Registers::ReturnReg);
         frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, Registers::ReturnReg);
-        return;
+        return true;
     }
 
     MaybeJump firstSlow;
     if (!rhs->isTypeKnown()) {
         Jump j = frame.testObject(Assembler::NotEqual, rhs);
         stubcc.linkExit(j, Uses(2));
         RegisterID reg = frame.tempRegForData(rhs);
         j = masm.testFunction(Assembler::NotEqual, reg);
@@ -4159,17 +4209,18 @@ mjit::Compiler::jsop_instanceof()
         stubcc.call(stubs::InstanceOf);
         firstSlow = stubcc.masm.jump();
     }
     
 
     /* This is sadly necessary because the error case needs the object. */
     frame.dup();
 
-    jsop_getprop(cx->runtime->atomState.classPrototypeAtom, false);
+    if (!jsop_getprop(cx->runtime->atomState.classPrototypeAtom, false))
+        return false;
 
     /* Primitive prototypes are invalid. */
     rhs = frame.peek(-1);
     Jump j = frame.testPrimitive(Assembler::Equal, rhs);
     stubcc.linkExit(j, Uses(3));
 
     /* Allocate registers up front, because of branchiness. */
     obj = frame.copyDataIntoReg(lhs);
@@ -4211,16 +4262,17 @@ mjit::Compiler::jsop_instanceof()
     stubcc.call(stubs::FastInstanceOf);
 
     frame.popn(3);
     frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, temp);
 
     if (firstSlow.isSet())
         firstSlow.getJump().linkTo(stubcc.masm.label(), &stubcc.masm);
     stubcc.rejoin(Changes(1));
+    return true;
 }
 
 /*
  * Note: This function emits tracer hooks into the OOL path. This means if
  * it is used in the middle of an in-progress slow path, the stream will be
  * hopelessly corrupted. Take care to only call this before linkExits() and
  * after rejoin()s.
  */
@@ -4336,29 +4388,30 @@ mjit::Compiler::leaveBlock()
 // Creates the new object expected for constructors, and places it in |thisv|.
 // It is broken down into the following operations:
 //   CALLEE
 //   GETPROP "prototype"
 //   IFPRIMTOP:
 //       NULL
 //   call js_CreateThisFromFunctionWithProto(...)
 //
-void
+bool
 mjit::Compiler::constructThis()
 {
     JS_ASSERT(isConstructing);
 
     // Load the callee.
     Address callee(JSFrameReg, JSStackFrame::offsetOfCallee(fun));
     RegisterID calleeReg = frame.allocReg();
     masm.loadPayload(callee, calleeReg);
     frame.pushTypedPayload(JSVAL_TYPE_OBJECT, calleeReg);
 
     // Get callee.prototype.
-    jsop_getprop(cx->runtime->atomState.classPrototypeAtom);
+    if (!jsop_getprop(cx->runtime->atomState.classPrototypeAtom))
+        return false;
 
     // Reach into the proto Value and grab a register for its data.
     FrameEntry *protoFe = frame.peek(-1);
     RegisterID protoReg = frame.ownRegForData(protoFe);
 
     // Now, get the type. If it's not an object, set protoReg to NULL.
     Jump isNotObject = frame.testObject(Assembler::NotEqual, protoFe);
     stubcc.linkExitDirect(isNotObject, stubcc.masm.label());
@@ -4368,10 +4421,11 @@ mjit::Compiler::constructThis()
     // Done with the protoFe.
     frame.pop();
 
     prepareStubCall(Uses(0));
     if (protoReg != Registers::ArgReg1)
         masm.move(protoReg, Registers::ArgReg1);
     stubCall(stubs::CreateThis);
     frame.freeReg(protoReg);
+    return true;
 }
 
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -266,17 +266,17 @@ class Compiler : public BaseCompiler
     void iterEnd();
     MaybeJump loadDouble(FrameEntry *fe, FPRegisterID fpReg);
 #ifdef JS_POLYIC
     void passPICAddress(PICGenInfo &pic);
 #endif
 #ifdef JS_MONOIC
     void passMICAddress(MICGenInfo &mic);
 #endif
-    void constructThis();
+    bool constructThis();
 
     /* Opcode handlers. */
     void jumpAndTrace(Jump j, jsbytecode *target, Jump *slowOne = NULL, Jump *slowTwo = NULL);
     void jsop_bindname(uint32 index);
     void jsop_setglobal(uint32 index);
     void jsop_getglobal(uint32 index);
     void jsop_getprop_slow();
     void jsop_getarg(uint32 index);
@@ -286,39 +286,39 @@ class Compiler : public BaseCompiler
     void loadReturnValue(Assembler *masm, FrameEntry *fe);
     void emitReturnValue(Assembler *masm, FrameEntry *fe);
     void dispatchCall(VoidPtrStubUInt32 stub, uint32 argc);
     void interruptCheckHelper();
     void emitUncachedCall(uint32 argc, bool callingNew);
     void inlineCallHelper(uint32 argc, bool callingNew);
     void fixPrimitiveReturn(Assembler *masm, FrameEntry *fe);
     void jsop_gnameinc(JSOp op, VoidStubAtom stub, uint32 index);
-    void jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index);
-    void jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index);
+    bool jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index);
+    bool jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index);
     void jsop_eleminc(JSOp op, VoidStub);
     void jsop_getgname(uint32 index);
     void jsop_getgname_slow(uint32 index);
     void jsop_setgname(uint32 index);
     void jsop_setgname_slow(uint32 index);
     void jsop_bindgname();
     void jsop_setelem_slow();
     void jsop_getelem_slow();
     void jsop_unbrand();
-    void jsop_getprop(JSAtom *atom, bool typeCheck = true);
-    void jsop_length();
-    void jsop_setprop(JSAtom *atom);
+    bool jsop_getprop(JSAtom *atom, bool typeCheck = true);
+    bool jsop_length();
+    bool jsop_setprop(JSAtom *atom);
     void jsop_setprop_slow(JSAtom *atom);
     bool jsop_callprop_slow(JSAtom *atom);
     bool jsop_callprop(JSAtom *atom);
     bool jsop_callprop_obj(JSAtom *atom);
     bool jsop_callprop_str(JSAtom *atom);
     bool jsop_callprop_generic(JSAtom *atom);
-    void jsop_instanceof();
+    bool jsop_instanceof();
     void jsop_name(JSAtom *atom);
-    void jsop_xname(JSAtom *atom);
+    bool jsop_xname(JSAtom *atom);
     void enterBlock(JSObject *obj);
     void leaveBlock();
 
     /* Fast arithmetic. */
     void jsop_binary(JSOp op, VoidStub stub);
     void jsop_binary_full(FrameEntry *lhs, FrameEntry *rhs, JSOp op, VoidStub stub);
     void jsop_binary_full_simple(FrameEntry *fe, JSOp op, VoidStub stub);
     void jsop_binary_double(FrameEntry *lhs, FrameEntry *rhs, JSOp op, VoidStub stub);
@@ -360,21 +360,21 @@ class Compiler : public BaseCompiler
     void jsop_not();
     void jsop_typeof();
     void booleanJumpScript(JSOp op, jsbytecode *target);
     void jsop_ifneq(JSOp op, jsbytecode *target);
     void jsop_andor(JSOp op, jsbytecode *target);
     void jsop_arginc(JSOp op, uint32 slot, bool popped);
     void jsop_localinc(JSOp op, uint32 slot, bool popped);
     void jsop_setelem();
-    void jsop_getelem();
-    void jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
-    void jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
+    bool jsop_getelem();
+    bool jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
+    bool jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
     void jsop_getelem_nopic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
-    void jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg, RegisterID idReg,
+    bool jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg, RegisterID idReg,
                           RegisterID shapeReg);
     void jsop_getelem_dense(FrameEntry *obj, FrameEntry *id, RegisterID objReg,
                             MaybeRegisterID &idReg, RegisterID shapeReg);
     void jsop_stricteq(JSOp op);
     void jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
     void jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
     void jsop_pos();
 
--- a/js/src/methodjit/FastOps.cpp
+++ b/js/src/methodjit/FastOps.cpp
@@ -1393,17 +1393,17 @@ mjit::Compiler::jsop_getelem_dense(Frame
 #endif
         stubcc.linkExit(notHole, Uses(2));
     }
     /* Postcondition: type must be in tmpReg, data must be in objReg. */
 
     /* Note: linkExits will be hooked up to a leave() after this method completes. */
 }
 
-void
+bool
 mjit::Compiler::jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg)
 {
     switch (id->getKnownType()) {
       case JSVAL_TYPE_INT32:
       {
         /* Prologue. */
         RegisterID objReg = frame.copyDataIntoReg(obj);
         MaybeRegisterID idReg;
@@ -1416,43 +1416,45 @@ mjit::Compiler::jsop_getelem_known_type(
         stubcc.call(stubs::GetElem);
 
         /* Epilogue. */
         if (idReg.isSet())
             frame.freeReg(idReg.reg());
         frame.popn(2);
         frame.pushRegs(tmpReg, objReg);
         stubcc.rejoin(Changes(1));
-        return;
+        break;
       }
 #ifdef JS_POLYIC
       case JSVAL_TYPE_STRING:
       {
         /* Prologue. */
         RegisterID objReg = frame.copyDataIntoReg(obj);
         RegisterID idReg = frame.copyDataIntoReg(id);
 
         /* Meat. */
-        jsop_getelem_pic(obj, id, objReg, idReg, tmpReg);
+        if (!jsop_getelem_pic(obj, id, objReg, idReg, tmpReg))
+            return false;
 
         /* Epilogue. */
         frame.popn(2);
         frame.pushRegs(tmpReg, objReg);
         frame.freeReg(idReg);
         stubcc.rejoin(Changes(1));
-        return;
+        break;
       }
 #endif
       default:
         JS_NOT_REACHED("Invalid known id type.");
     }
+    return true;
 }
 
 #ifdef JS_POLYIC
-void
+bool
 mjit::Compiler::jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg)
 {
     JS_ASSERT(!id->isTypeKnown());
     RegisterID objReg = frame.copyDataIntoReg(obj);
     MaybeRegisterID idReg(frame.copyDataIntoReg(id));
 
     RegisterID typeReg = frame.tempRegForType(id, tmpReg);
     Jump intGuard = masm.testInt32(Assembler::NotEqual, typeReg);
@@ -1467,23 +1469,25 @@ mjit::Compiler::jsop_getelem_with_pic(Fr
     intGuard.linkTo(masm.label(), &masm);
     Jump stringGuard = masm.testString(Assembler::NotEqual, typeReg);
     stubcc.linkExit(stringGuard, Uses(2)); /* Neither int nor string at this point. */
 
     stubcc.leave();
     stubcc.call(stubs::GetElem);
     Jump toFinalMerge = stubcc.masm.jump();
 
-    jsop_getelem_pic(obj, id, objReg, idReg.reg(), tmpReg);
+    if (!jsop_getelem_pic(obj, id, objReg, idReg.reg(), tmpReg))
+        return false;
     performedDense.linkTo(masm.label(), &masm);
     frame.popn(2);
     frame.pushRegs(tmpReg, objReg);
     frame.freeReg(idReg.reg());
     toFinalMerge.linkTo(stubcc.masm.label(), &stubcc.masm);
     stubcc.rejoin(Changes(1));
+    return true;
 }
 #endif
 
 void
 mjit::Compiler::jsop_getelem_nopic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg)
 {
     /* Only handle the int32 case. */
     RegisterID objReg = frame.copyDataIntoReg(obj);
@@ -1499,47 +1503,47 @@ mjit::Compiler::jsop_getelem_nopic(Frame
 
     /* Epilogue. */
     frame.freeReg(idReg.reg());
     frame.popn(2);
     frame.pushRegs(tmpReg, objReg);
     stubcc.rejoin(Changes(1));
 }
 
-void
+bool
 mjit::Compiler::jsop_getelem()
 {
     FrameEntry *obj = frame.peek(-2);
     FrameEntry *id = frame.peek(-1);
 
     if (obj->isTypeKnown() && obj->getKnownType() != JSVAL_TYPE_OBJECT) {
         jsop_getelem_slow();
-        return;
+        return true;
     }
 
     if (id->isTypeKnown() &&
         !(id->getKnownType() == JSVAL_TYPE_INT32
 #ifdef JS_POLYIC
           || id->getKnownType() == JSVAL_TYPE_STRING
 #endif
          )) {
         jsop_getelem_slow();
-        return;
+        return true;
     }
 
     if (id->isTypeKnown() && id->getKnownType() == JSVAL_TYPE_INT32 && id->isConstant() &&
         id->getValue().toInt32() < 0) {
         jsop_getelem_slow();
-        return;
+        return true;
     }
 
     if (id->isTypeKnown() && id->getKnownType() == JSVAL_TYPE_STRING && id->isConstant()) {
         /* Never happens, or I'd optimize it. */
         jsop_getelem_slow();
-        return;
+        return true;
     }
 
     RegisterID tmpReg;
     if (obj->isTypeKnown()) {
         tmpReg = frame.allocReg();
     } else {
         tmpReg = frame.copyTypeIntoReg(obj);
         Jump objGuard = masm.testObject(Assembler::NotEqual, tmpReg);
@@ -1547,17 +1551,18 @@ mjit::Compiler::jsop_getelem()
     }
 
     if (id->isTypeKnown())
         return jsop_getelem_known_type(obj, id, tmpReg);
 
 #ifdef JS_POLYIC
     return jsop_getelem_with_pic(obj, id, tmpReg);
 #else
-    return jsop_getelem_nopic(obj, id, tmpReg);
+    jsop_getelem_nopic(obj, id, tmpReg);
+    return true;
 #endif
 }
 
 static inline bool
 ReallySimpleStrictTest(FrameEntry *fe)
 {
     if (!fe->isTypeKnown())
         return false;
--- a/js/src/yarr/yarr/RegexJIT.cpp
+++ b/js/src/yarr/yarr/RegexJIT.cpp
@@ -1518,16 +1518,21 @@ public:
 
         generateDisjunction(m_pattern.m_body);
     }
 
     void compile(ExecutableAllocator& allocator, RegexCodeBlock& jitObject)
     {
         generate();
 
+        if (oom()) {
+            m_shouldFallBack = true;
+            return;
+        }
+
         ExecutablePool *executablePool = allocator.poolForSize(size());
         if (!executablePool) {
             m_shouldFallBack = true;
             return;
         }
 
         LinkBuffer patchBuffer(this, executablePool);