Index: JavaScriptCore/kjs/JSValue.h
===================================================================
--- JavaScriptCore/kjs/JSValue.h	(revision 34737)
+++ JavaScriptCore/kjs/JSValue.h	(working copy)
@@ -129,6 +129,7 @@
     void put(ExecState*, const Identifier& propertyName, JSValue*);
     void put(ExecState*, unsigned propertyName, JSValue*);
     JSObject* toThisObject(ExecState*) const;
+    static JSValue* isJSNumberCell(JSValue* value);
 
 private:
     bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
@@ -204,6 +205,7 @@
 class JSNumberCell : public JSCell {
     friend JSValue* jsNumberCell(ExecState*, double);
 public:
+    enum { NumberCacheSize = 32 };
     double value() const { return val; }
 
     virtual JSType type() const;
@@ -216,8 +218,19 @@
     virtual JSObject* toObject(ExecState*) const;
     virtual JSObject* toThisObject(ExecState*) const;
 
+    static void ClearNumberStack() { numberStackPtr = 0; lastAllocatedNumber = 0; }
+    static void storeFreeNumberCell(JSValue** value, JSValue* newValue)
+    {
+        if (UNLIKELY((long)*value) && numberStackPtr < NumberCacheSize)
+            numberStack[numberStackPtr++] = *value;
+        *value = newValue;
+    }
+    static JSValue* isLastJSNumberCell(JSValue* value);
+
     void* operator new(size_t size, ExecState* exec)
     {
+        if (UNLIKELY(numberStackPtr > 0))
+            return numberStack[--numberStackPtr];
 #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
         return exec->heap()->inlineAllocateNumber(size);
 #else
@@ -229,12 +242,17 @@
     JSNumberCell(double v)
         : val(v)
     {
+        lastAllocatedNumber = (JSValue*)this;
     }
 
     virtual bool getUInt32(uint32_t&) const;
     virtual bool getTruncatedInt32(int32_t&) const;
     virtual bool getTruncatedUInt32(uint32_t&) const;
 
+    static int numberStackPtr;
+    static JSValue* numberStack[NumberCacheSize];
+    static JSValue* lastAllocatedNumber;
+
     double val;
 };
 
@@ -590,6 +608,16 @@
     return asCell()->toThisObject(exec);
 }
 
+inline JSValue* JSValue::isJSNumberCell(JSValue* value)
+{
+    return (JSImmediate::isImmediate(value) || UNLIKELY(!value->asCell()->isNumber())) ? 0 : value;
+}
+
+inline JSValue* JSNumberCell::isLastJSNumberCell(JSValue* value)
+{
+    return (value != lastAllocatedNumber) ? 0 : value;
+}
+
 } // namespace KJS
 
 #endif // JSValue_h
Index: JavaScriptCore/kjs/collector.cpp
===================================================================
--- JavaScriptCore/kjs/collector.cpp	(revision 34737)
+++ JavaScriptCore/kjs/collector.cpp	(working copy)
@@ -973,6 +973,7 @@
 
     // MARK: first mark all referenced objects recursively starting out from the set of root objects
 
+    JSNumberCell::ClearNumberStack();
     markStackObjectsConservatively();
     markProtectedObjects();
     if (m_markListSet && m_markListSet->size())
Index: JavaScriptCore/kjs/JSValue.cpp
===================================================================
--- JavaScriptCore/kjs/JSValue.cpp	(revision 34737)
+++ JavaScriptCore/kjs/JSValue.cpp	(working copy)
@@ -275,4 +275,8 @@
     return s.isNull() ? new (exec) JSString("", JSString::HasOtherOwner) : new (exec) JSString(s, JSString::HasOtherOwner);
 }
 
+int JSNumberCell::numberStackPtr;
+JSValue* JSNumberCell::numberStack[JSNumberCell::NumberCacheSize];
+JSValue* JSNumberCell::lastAllocatedNumber;
+
 } // namespace KJS
Index: JavaScriptCore/VM/Machine.cpp
===================================================================
--- JavaScriptCore/VM/Machine.cpp	(revision 34737)
+++ JavaScriptCore/VM/Machine.cpp	(working copy)
@@ -891,6 +891,7 @@
     Instruction* handlerVPC = 0;
 
     Register** registerBase = registerFile->basePointer();
+    void** cache = registerFile->updateCachePointer(r);
     Instruction* vPC = codeBlock->instructions.begin();
     JSValue** k = codeBlock->jsValues.data();
     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
@@ -985,6 +986,8 @@
         int dst = (++vPC)->u.operand;
         int src = (++vPC)->u.operand;
         r[dst] = r[src];
+        JSNumberCell::storeFreeNumberCell((JSValue**)(cache + dst), 0);
+        cache[src] = 0;
 
         ++vPC;
         NEXT_OPCODE;
@@ -1207,6 +1210,7 @@
         VM_CHECK_EXCEPTION();
 
         r[dst].u.jsValue = result;
+        JSNumberCell::storeFreeNumberCell((JSValue**)(cache + dst), JSNumberCell::isLastJSNumberCell(result));
 
         ++vPC;
         NEXT_OPCODE;
@@ -1222,6 +1226,7 @@
         JSValue* result = jsNumber(exec, -r[src].u.jsValue->toNumber(exec));
         VM_CHECK_EXCEPTION();
         r[dst].u.jsValue = result;
+        JSNumberCell::storeFreeNumberCell((JSValue**)(cache + dst), JSNumberCell::isLastJSNumberCell(result));
 
         ++vPC;
         NEXT_OPCODE;
@@ -1234,6 +1239,7 @@
            numeric add, depending on the types of the operands.)
         */
         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
+        JSValue** cacheDst = (JSValue**)(cache + vPC->u.operand);
         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
         JSValue* result;
@@ -1243,7 +1249,9 @@
             result = jsAdd(exec, src1, src2);
             VM_CHECK_EXCEPTION();
         }
+        //if (!registerFile->testCachePointer(cache, r)) fprintf(stderr, "WARNING cache!\n");
         dst = result;
+        JSNumberCell::storeFreeNumberCell(cacheDst, JSNumberCell::isLastJSNumberCell(result));
         ++vPC;
         NEXT_OPCODE;
     }
@@ -1254,11 +1262,13 @@
            numbers), and puts the product in register dst.
         */
         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
+        JSValue** cacheDst = (JSValue**)(cache + vPC->u.operand);
         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
         JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
         VM_CHECK_EXCEPTION();
         dst = result;
+        JSNumberCell::storeFreeNumberCell(cacheDst, JSNumberCell::isLastJSNumberCell(result));
 
         ++vPC;
         NEXT_OPCODE;
@@ -1276,6 +1286,7 @@
         JSValue* result = jsNumber(exec, r[dividend].u.jsValue->toNumber(exec) / r[divisor].u.jsValue->toNumber(exec));
         VM_CHECK_EXCEPTION();
         r[dst].u.jsValue = result;
+        JSNumberCell::storeFreeNumberCell((JSValue**)(cache + dst), JSNumberCell::isLastJSNumberCell(result));
         ++vPC;
         NEXT_OPCODE;
     }
@@ -1293,6 +1304,7 @@
         JSValue* result = jsNumber(exec, fmod(d, r[divisor].u.jsValue->toNumber(exec)));
         VM_CHECK_EXCEPTION();
         r[dst].u.jsValue = result;
+        JSNumberCell::storeFreeNumberCell((JSValue**)(cache + dst), JSNumberCell::isLastJSNumberCell(result));
         ++vPC;
         NEXT_OPCODE;
     }
@@ -1304,6 +1316,7 @@
            register dst.
         */
         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
+        JSValue** cacheDst = (JSValue**)(cache + vPC->u.operand);
         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
         JSValue* result;
@@ -1314,6 +1327,7 @@
             VM_CHECK_EXCEPTION();
         }
         dst = result;
+        JSNumberCell::storeFreeNumberCell(cacheDst, JSNumberCell::isLastJSNumberCell(result));
         ++vPC;
         NEXT_OPCODE;
     }
@@ -1391,6 +1405,7 @@
            in register dst.
         */
         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
+        JSValue** cacheDst = (JSValue**)(cache + vPC->u.operand);
         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
         JSValue* result;
@@ -1401,6 +1416,7 @@
             VM_CHECK_EXCEPTION();
         }
         dst = result;
+        JSNumberCell::storeFreeNumberCell(cacheDst, JSNumberCell::isLastJSNumberCell(result));
 
         ++vPC;
         NEXT_OPCODE;
@@ -1413,6 +1429,7 @@
            in register dst.
         */
         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
+        JSValue** cacheDst = (JSValue**)(cache + vPC->u.operand);
         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
         JSValue* result;
@@ -1423,6 +1440,7 @@
             VM_CHECK_EXCEPTION();
         }
         dst = result;
+        JSNumberCell::storeFreeNumberCell(cacheDst, JSNumberCell::isLastJSNumberCell(result));
 
         ++vPC;
         NEXT_OPCODE;
@@ -1435,6 +1453,7 @@
            result in register dst.
         */
         JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
+        JSValue** cacheDst = (JSValue**)(cache + vPC->u.operand);
         JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
         JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
         JSValue* result;
@@ -1445,6 +1464,7 @@
             VM_CHECK_EXCEPTION();
         }
         dst = result;
+        JSNumberCell::storeFreeNumberCell(cacheDst, JSNumberCell::isLastJSNumberCell(result));
 
         ++vPC;
         NEXT_OPCODE;
@@ -1460,6 +1480,7 @@
         JSValue* result = jsNumber(exec, ~r[src].u.jsValue->toInt32(exec));
         VM_CHECK_EXCEPTION();
         r[dst].u.jsValue = result;
+        JSNumberCell::storeFreeNumberCell((JSValue**)(cache + dst), JSNumberCell::isLastJSNumberCell(result));
 
         ++vPC;
         NEXT_OPCODE;
@@ -1607,6 +1628,7 @@
         int index = (++vPC)->u.operand;
         int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
         int value = (++vPC)->u.operand;
+        cache[value] = 0;
 
         ScopeChainIterator iter = scopeChain->begin();
         ScopeChainIterator end = scopeChain->end();
@@ -1708,6 +1730,7 @@
         int base = (++vPC)->u.operand;
         int property = (++vPC)->u.operand;
         int value = (++vPC)->u.operand;
+        cache[value] = 0;
 #ifndef NDEBUG
         int registerOffset = r - (*registerBase);
 #endif
@@ -1793,6 +1816,7 @@
         int base = (++vPC)->u.operand;
         int property = (++vPC)->u.operand;
         int value = (++vPC)->u.operand;
+        cache[value] = 0;
 
         JSValue* baseValue = r[base].u.jsValue;
 
@@ -1866,6 +1890,7 @@
         int base = (++vPC)->u.operand;
         unsigned property = (++vPC)->u.operand;
         int value = (++vPC)->u.operand;
+        cache[value] = 0;
 
         r[base].u.jsObject->put(exec, property, r[value].u.jsValue);
 
@@ -1990,6 +2015,7 @@
         int thisVal = (++vPC)->u.operand;
         int firstArg = (++vPC)->u.operand;
         int argCount = (++vPC)->u.operand;
+        memset(cache + firstArg, 0, argCount * sizeof(void*));
 
         JSValue* funcVal = r[func].u.jsValue;
         JSValue* baseVal = r[thisVal].u.jsValue;
@@ -2005,6 +2031,7 @@
 
             registerFile->setSafeForReentry(false);
             r = (*registerBase) + registerOffset;
+            cache = registerFile->updateCachePointer(r);
 
             if (exceptionValue)
                 goto vm_throw;
@@ -2071,6 +2098,7 @@
         int thisVal = (++vPC)->u.operand;
         int firstArg = (++vPC)->u.operand;
         int argCount = (++vPC)->u.operand;
+        memset(cache + firstArg, 0, argCount * sizeof(void*));
 
         JSValue* v = r[func].u.jsValue;
 
@@ -2092,6 +2120,7 @@
 
             CodeBlock* newCodeBlock = &functionBodyNode->code(callDataScopeChain);
             r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, registerOffset, firstArg, argCount, exceptionValue);
+            cache = registerFile->updateCachePointer(r);
             if (UNLIKELY(exceptionValue != 0))
                 goto vm_throw;
 
@@ -2123,6 +2152,7 @@
             registerFile->setSafeForReentry(false);
 
             r = (*registerBase) + registerOffset;
+            cache = registerFile->updateCachePointer(r);
             r[dst].u.jsValue = returnValue;
 
             if (*enabledProfilerReference)
@@ -2154,6 +2184,7 @@
 
         Register* callFrame = r - oldCodeBlock->numLocals - CallFrameHeaderSize;
         JSValue* returnValue = r[result].u.jsValue;
+        cache[result] = 0;
 
         if (JSActivation* activation = static_cast<JSActivation*>(callFrame[OptionalCalleeActivation].u.jsValue)) {
             ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
@@ -2181,6 +2212,7 @@
         setScopeChain(exec, scopeChain, callFrame[CallerScopeChain].u.scopeChain);
         int callerRegisterOffset = callFrame[CallerRegisterOffset].u.i;
         r = (*registerBase) + callerRegisterOffset;
+        cache = registerFile->updateCachePointer(r);
         exec->m_callFrameOffset = callerRegisterOffset - codeBlock->numLocals - CallFrameHeaderSize;
         int dst = callFrame[ReturnValueRegister].u.i;
         r[dst].u.jsValue = returnValue;
@@ -2202,6 +2234,7 @@
         int constr = (++vPC)->u.operand;
         int firstArg = (++vPC)->u.operand;
         int argCount = (++vPC)->u.operand;
+        memset(cache + firstArg, 0, argCount * sizeof(void*));
 
         JSValue* constrVal = r[constr].u.jsValue;
 
@@ -2235,6 +2268,7 @@
 
             CodeBlock* newCodeBlock = &functionBodyNode->code(callDataScopeChain);
             r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, registerOffset, firstArg, argCount, exceptionValue);
+            cache = registerFile->updateCachePointer(r);
             if (exceptionValue)
                 goto vm_throw;
 
@@ -2260,6 +2294,7 @@
             registerFile->setSafeForReentry(false);
 
             r = (*registerBase) + registerOffset;
+            cache = registerFile->updateCachePointer(r);
             VM_CHECK_EXCEPTION();
             r[dst].u.jsValue = returnValue;
 
@@ -2388,6 +2423,7 @@
         int ex = (++vPC)->u.operand;
         exceptionValue = r[ex].u.jsValue;
         handlerVPC = throwException(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r);
+        cache = registerFile->updateCachePointer(r);
         if (!handlerVPC) {
             *exception = exceptionValue;
             return jsNull();
@@ -2434,6 +2470,7 @@
             scopeChain->deref();
         }
         int result = (++vPC)->u.operand;
+        cache[result] = 0;
         return r[result].u.jsValue;
     }
     BEGIN_OPCODE(op_put_getter) {
@@ -2520,6 +2557,7 @@
         debug(exec, vPC, codeBlock, scopeChain, registerBase, r);
         registerFile->setSafeForReentry(false);
         r = (*registerBase) + registerOffset;
+        cache = registerFile->updateCachePointer(r);
 
         vPC += 4;
         NEXT_OPCODE;
@@ -2527,6 +2565,7 @@
     vm_throw: {
         exec->clearException();
         handlerVPC = throwException(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r);
+        cache = registerFile->updateCachePointer(r);
         if (!handlerVPC) {
             *exception = exceptionValue;
             return jsNull();
Index: JavaScriptCore/VM/RegisterFile.cpp
===================================================================
--- JavaScriptCore/VM/RegisterFile.cpp	(revision 34737)
+++ JavaScriptCore/VM/RegisterFile.cpp	(working copy)
@@ -40,11 +40,14 @@
 {
     capacity = (max(minCapacity, min(maxSize, max<size_t>(16, capacity + capacity / 4 + 1))));
     Register* newBuffer = static_cast<Register*>(fastCalloc(capacity, sizeof(Register))); // zero-filled memory
+    void** newCache = static_cast<void**>(fastCalloc(capacity, sizeof(void*))); // zero-filled memory
 
     if (m_buffer)
         memcpy(newBuffer + offset, m_buffer, size * sizeof(Register));
+    if (m_cache)
+        memcpy(newCache + offset, m_cache, size * sizeof(void*));
 
-    setBuffer(newBuffer);
+    setBuffer(newBuffer, newCache);
     return capacity;
 }
 
@@ -75,9 +78,10 @@
     size_t capacity = m_capacity + numGlobalSlots;
     size_t minCapacity = size + count;
 
-    if (minCapacity < capacity)
+    if (minCapacity < capacity) {
         memmove(m_buffer + count, m_buffer, size * sizeof(Register));
-    else
+        memmove(m_cache + count, m_cache, size * sizeof(void*));
+    } else
         capacity = newBuffer(size, capacity, minCapacity, m_maxSize, count);
 
     numGlobalSlots += count;
@@ -93,6 +97,9 @@
     if (!numSlotsToCopy)
         return;
     memcpy(m_buffer, src->m_buffer, numSlotsToCopy * sizeof(Register));
+    // Since the links are doubled, we should empty the cache
+    memset(m_cache, 0, numSlotsToCopy * sizeof(void*));
+    memset(src->m_cache, 0, numSlotsToCopy * sizeof(void*));
 }
 
 void RegisterFile::setBase(Register* base)
Index: JavaScriptCore/VM/RegisterFile.h
===================================================================
--- JavaScriptCore/VM/RegisterFile.h	(revision 34737)
+++ JavaScriptCore/VM/RegisterFile.h	(working copy)
@@ -95,17 +95,21 @@
             , m_maxSize(maxSize)
             , m_base(0)
             , m_buffer(0)
+            , m_cache(0)
             , m_baseObserver(m_baseObserver)
         {
         }
 
         ~RegisterFile()
         {
-            setBuffer(0);
+            setBuffer(0, 0);
         }
 
         // Pointer to a value that holds the base of this register file.
         Register** basePointer() { return &m_base; }
+        void** updateCachePointer(Register* r) { return m_cache + (r - m_buffer); }
+        // For testing
+        bool testCachePointer(void** cache, Register* r) { return cache == m_cache + (r - m_buffer); }
 
         void shrink(size_t size)
         {
@@ -139,6 +143,7 @@
         void mark(Heap* heap)
         {
             heap->markStackObjectsConservatively(m_buffer, m_base + m_size);
+            memset(m_cache, 0, ((m_base - m_buffer) + m_size) * sizeof(void*));
         }
 
         bool isGlobal() { return !!m_baseObserver; }
@@ -149,12 +154,16 @@
     private:
         size_t newBuffer(size_t size, size_t capacity, size_t minCapacity, size_t maxSize, size_t offset);
         bool growBuffer(size_t minCapacity, size_t maxSize);
-        void setBuffer(Register* buffer)
+        void setBuffer(Register* buffer, void** cache)
         {
             if (m_buffer)
                 fastFree(m_buffer);
 
+            if (m_cache)
+                fastFree(m_cache);
+
             m_buffer = buffer;
+            m_cache = cache;
         }
 
         void setBase(Register*);
@@ -165,6 +174,7 @@
         size_t m_maxSize;
         Register* m_base;
         Register* m_buffer;
+        void** m_cache;
         RegisterFileStack* m_baseObserver;
     };
 
