2008-06-30 Geoffrey Garen <ggaren@apple.com>
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 1 Jul 2008 05:45:21 +0000 (05:45 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 1 Jul 2008 05:45:21 +0000 (05:45 +0000)
        Reviewed by Oliver Hunt.

        Removed the "registerBase" abstraction. Since the register file never
        reallocates, we can keep direct pointers into it, instead of
        <registerBase, offset> tuples.

        SunSpider says 0.8% faster.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@34906 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/VM/Machine.cpp
JavaScriptCore/VM/Machine.h
JavaScriptCore/VM/RegisterFile.h
JavaScriptCore/kjs/DebuggerCallFrame.cpp
JavaScriptCore/kjs/DebuggerCallFrame.h
JavaScriptCore/kjs/ExecState.cpp
JavaScriptCore/kjs/ExecState.h
JavaScriptCore/kjs/JSActivation.cpp
JavaScriptCore/kjs/JSActivation.h
JavaScriptCore/kjs/JSGlobalObject.cpp
JavaScriptCore/kjs/JSGlobalObject.h
JavaScriptCore/kjs/JSVariableObject.cpp
JavaScriptCore/kjs/JSVariableObject.h
JavaScriptCore/kjs/list.cpp
JavaScriptCore/kjs/list.h

index fb5a67e..b68c719 100644 (file)
@@ -1,3 +1,13 @@
+2008-06-30  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Oliver Hunt.
+        
+        Removed the "registerBase" abstraction. Since the register file never
+        reallocates, we can keep direct pointers into it, instead of
+        <registerBase, offset> tuples.
+        
+        SunSpider says 0.8% faster.
+        
 2008-06-30  Oliver Hunt  <oliver@apple.com>
 
         Reviewed by NOBODY (build fix).
index 0d2fba0..4d96023 100644 (file)
@@ -353,12 +353,12 @@ static bool NEVER_INLINE resolveBaseAndFunc(ExecState* exec, Instruction* vPC, R
     return false;
 }
 
-ALWAYS_INLINE void initializeCallFrame(Register* callFrame, CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, int registerOffset, int returnValueRegister, int argv, int argc, int calledAsConstructor, JSValue* function)
+ALWAYS_INLINE void initializeCallFrame(Register* callFrame, CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, Register* r, int returnValueRegister, int argv, int argc, int calledAsConstructor, JSValue* function)
 {
     callFrame[RegisterFile::CallerCodeBlock].u.codeBlock = codeBlock;
     callFrame[RegisterFile::ReturnVPC].u.vPC = vPC + 1;
     callFrame[RegisterFile::CallerScopeChain].u.scopeChain = scopeChain;
-    callFrame[RegisterFile::CallerRegisterOffset].u.i = registerOffset;
+    callFrame[RegisterFile::CallerRegisters].u.r = r;
     callFrame[RegisterFile::ReturnValueRegister].u.i = returnValueRegister;
     callFrame[RegisterFile::ArgumentStartRegister].u.i = argv; // original argument vector (for the sake of the "arguments" object)
     callFrame[RegisterFile::ArgumentCount].u.i = argc; // original argument count (for the sake of the "arguments" object)
@@ -367,25 +367,23 @@ ALWAYS_INLINE void initializeCallFrame(Register* callFrame, CodeBlock* codeBlock
     callFrame[RegisterFile::OptionalCalleeActivation].u.jsValue = 0;
 }
 
-ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* newCodeBlock, RegisterFile* registerFile, Register** registerBase, int registerOffset, int argv, int argc, JSValue*& exceptionValue)
+ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* newCodeBlock, RegisterFile* registerFile, Register* registerBase, Register* r, int argv, int argc, JSValue*& exceptionValue)
 {
-    Register* r = 0;
-    int oldOffset = registerOffset;
-    registerOffset += argv + newCodeBlock->numLocals;
-    size_t size = registerOffset + newCodeBlock->numTemporaries;
+    size_t registerOffset = argv + newCodeBlock->numLocals;
+    size_t size = r - registerBase + registerOffset + newCodeBlock->numTemporaries;
 
     if (argc == newCodeBlock->numParameters) { // correct number of arguments
         if (!registerFile->grow(size)) {
             exceptionValue = createStackOverflowError(exec);
-            return *registerBase + oldOffset;
+            return r;
         }
-        r = (*registerBase) + registerOffset;
+        r += registerOffset;
     } else if (argc < newCodeBlock->numParameters) { // too few arguments -- fill in the blanks
         if (!registerFile->grow(size)) {
             exceptionValue = createStackOverflowError(exec);
-            return *registerBase + oldOffset;
+            return r;
         }
-        r = (*registerBase) + registerOffset;
+        r += registerOffset;
 
         int omittedArgCount = newCodeBlock->numParameters - argc;
         Register* endOfParams = r - newCodeBlock->numVars;
@@ -398,9 +396,9 @@ ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* n
 
         if (!registerFile->grow(size)) {
             exceptionValue = createStackOverflowError(exec);
-            return *registerBase + oldOffset;
+            return r;
         }
-        r = (*registerBase) + registerOffset;
+        r += registerOffset;
 
         Register* it = r - newCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize - shift;
         Register* end = it + RegisterFile::CallFrameHeaderSize + newCodeBlock->numParameters;
@@ -415,10 +413,10 @@ ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* n
     return r;
 }
 
-ALWAYS_INLINE ScopeChainNode* scopeChainForCall(ExecState* exec, FunctionBodyNode* functionBodyNode, CodeBlock* newCodeBlock, ScopeChainNode* callDataScopeChain, Register** registerBase, Register* r)
+ALWAYS_INLINE ScopeChainNode* scopeChainForCall(ExecState* exec, FunctionBodyNode* functionBodyNode, CodeBlock* newCodeBlock, ScopeChainNode* callDataScopeChain, Register* r)
 {
     if (newCodeBlock->needsFullScopeChain) {
-        JSActivation* activation = new (exec) JSActivation(functionBodyNode, registerBase, r - (*registerBase));
+        JSActivation* activation = new (exec) JSActivation(functionBodyNode, r);
         r[RegisterFile::OptionalCalleeActivation - RegisterFile::CallFrameHeaderSize - newCodeBlock->numLocals].u.jsValue = activation;
 
         return callDataScopeChain->copy()->push(activation);
@@ -461,7 +459,7 @@ NEVER_INLINE JSValue* callEval(ExecState* exec, JSObject* thisObj, ScopeChainNod
         return 0;
     }
 
-    JSValue* result = exec->globalData().machine->execute(evalNode.get(), exec, thisObj, r - (*registerFile->basePointer()) + argv + argc, scopeChain, &exceptionValue);
+    JSValue* result = exec->globalData().machine->execute(evalNode.get(), exec, thisObj, r - registerFile->base() + argv + argc, scopeChain, &exceptionValue);
 
     if (*profiler)
         (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
@@ -562,13 +560,13 @@ bool Machine::isOpcode(Opcode opcode)
 #endif
 }
 
-NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, Register** registerBase, const Instruction*& vPC, CodeBlock*& codeBlock, JSValue**& k, ScopeChainNode*& scopeChain, Register*& r)
+NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, const Instruction*& vPC, CodeBlock*& codeBlock, JSValue**& k, ScopeChainNode*& scopeChain, Register*& r)
 {
     CodeBlock* oldCodeBlock = codeBlock;
     Register* callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
 
     if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
-        DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, exceptionValue, registerBase, r - *registerBase);
+        DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
         if (callFrame[RegisterFile::Callee].u.jsObject)
             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
         else
@@ -597,15 +595,14 @@ NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionVa
 
     k = codeBlock->jsValues.data();
     scopeChain = callFrame[RegisterFile::CallerScopeChain].u.scopeChain;
-    int callerRegisterOffset = callFrame[RegisterFile::CallerRegisterOffset].u.i;
-    r = (*registerBase) + callerRegisterOffset;
-    exec->m_callFrameOffset = callerRegisterOffset - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
+    r = callFrame[RegisterFile::CallerRegisters].u.r;
+    exec->m_callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
     vPC = callFrame[RegisterFile::ReturnVPC].u.vPC;
 
     return true;
 }
 
-NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue* exceptionValue, Register** registerBase, const Instruction* vPC, CodeBlock*& codeBlock, JSValue**& k, ScopeChainNode*& scopeChain, Register*& r)
+NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue* exceptionValue, const Instruction* vPC, CodeBlock*& codeBlock, JSValue**& k, ScopeChainNode*& scopeChain, Register*& r)
 {
     // Set up the exception object
 
@@ -617,7 +614,7 @@ NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue* exce
         }
 
         if (exception->isWatchdogException()) {
-            while (unwindCallFrame(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r)) {
+            while (unwindCallFrame(exec, exceptionValue, vPC, codeBlock, k, scopeChain, r)) {
                  // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
             }
             return 0;
@@ -625,7 +622,7 @@ NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue* exce
     }
 
     if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
-        DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, exceptionValue, registerBase, r - *registerBase);
+        DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
         debugger->exception(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->lineNumberForVPC(vPC));
     }
 
@@ -635,7 +632,7 @@ NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue* exce
     Instruction* handlerVPC;
 
     while (!codeBlock->getHandlerForVPC(vPC, handlerVPC, scopeDepth)) {
-        if (!unwindCallFrame(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r))
+        if (!unwindCallFrame(exec, exceptionValue, vPC, codeBlock, k, scopeChain, r))
             return 0;
     }
 
@@ -671,7 +668,7 @@ JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainN
     JSGlobalObject* globalObject = exec->dynamicGlobalObject();
     globalObject->copyGlobalsTo(m_registerFile);
 
-    Register* callFrame = *m_registerFile.basePointer() + oldSize;
+    Register* callFrame = m_registerFile.base() + oldSize;
 
     // a 0 codeBlock indicates a built-in caller
     initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -682,7 +679,7 @@ JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainN
     if (codeBlock->needsFullScopeChain)
         scopeChain = scopeChain->copy();
 
-    ExecState newExec(exec, &m_registerFile, scopeChain, -1);
+    ExecState newExec(exec, &m_registerFile, scopeChain, 0);
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
@@ -721,10 +718,7 @@ JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, J
         return 0;
     }
 
-    Register** registerBase = m_registerFile.basePointer();
-    int registerOffset = oldSize;
-    int callFrameOffset = registerOffset;
-    Register* callFrame = (*registerBase) + callFrameOffset;
+    Register* callFrame = m_registerFile.base() + oldSize;
 
     // put args in place, including "this"
     Register* dst = callFrame + RegisterFile::CallFrameHeaderSize;
@@ -735,18 +729,18 @@ JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, J
         (*++dst).u.jsValue = *it;
 
     // a 0 codeBlock indicates a built-in caller
-    initializeCallFrame(callFrame, 0, 0, 0, registerOffset, 0, argv, argc, 0, function);
+    initializeCallFrame(callFrame, 0, 0, 0, callFrame, 0, argv, argc, 0, function);
 
     CodeBlock* newCodeBlock = &functionBodyNode->code(scopeChain);
-    Register* r = slideRegisterWindowForCall(exec, newCodeBlock, &m_registerFile, registerBase, registerOffset, argv, argc, *exception);
+    Register* r = slideRegisterWindowForCall(exec, newCodeBlock, &m_registerFile, m_registerFile.base(), callFrame, argv, argc, *exception);
     if (*exception) {
         m_registerFile.shrink(oldSize);
         return 0;
     }
 
-    scopeChain = scopeChainForCall(exec, functionBodyNode, newCodeBlock, scopeChain, registerBase, r);
+    scopeChain = scopeChainForCall(exec, functionBodyNode, newCodeBlock, scopeChain, r);
 
-    ExecState newExec(exec, &m_registerFile, scopeChain, callFrameOffset);
+    ExecState newExec(exec, &m_registerFile, scopeChain, callFrame);
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
@@ -801,10 +795,10 @@ JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj
         return 0;
     }
 
-    Register* callFrame = *m_registerFile.basePointer() + registerOffset;
+    Register* callFrame = m_registerFile.base() + registerOffset;
 
     // a 0 codeBlock indicates a built-in caller
-    initializeCallFrame(callFrame, 0, 0, 0, registerOffset, 0, 0, 0, 0, 0);
+    initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
     Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
     r[codeBlock->thisRegister].u.jsValue = thisObj;
@@ -812,7 +806,7 @@ JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj
     if (codeBlock->needsFullScopeChain)
         scopeChain = scopeChain->copy();
 
-    ExecState newExec(exec, &m_registerFile, scopeChain, -1);
+    ExecState newExec(exec, &m_registerFile, scopeChain, 0);
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
@@ -838,7 +832,7 @@ ALWAYS_INLINE void Machine::setScopeChain(ExecState* exec, ScopeChainNode*& scop
     exec->m_scopeChain = newScopeChain;
 }
 
-NEVER_INLINE void Machine::debug(ExecState* exec, const Instruction* vPC, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register** registerBase, Register* r)
+NEVER_INLINE void Machine::debug(ExecState* exec, const Instruction* vPC, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register* r)
 {
     int debugHookID = (++vPC)->u.operand;
     int firstLine = (++vPC)->u.operand;
@@ -848,7 +842,7 @@ NEVER_INLINE void Machine::debug(ExecState* exec, const Instruction* vPC, const
     if (!debugger)
         return;
 
-    DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, 0, registerBase, r - *registerBase);
+    DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, r, 0);
 
     switch((DebugHookID)debugHookID) {
     case DidEnterCallFrame: {
@@ -967,7 +961,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
     JSValue* exceptionValue = 0;
     Instruction* handlerVPC = 0;
 
-    Register* registerBase = *registerFile->basePointer();
+    Register* registerBase = registerFile->base();
     Instruction* vPC = codeBlock->instructions.begin();
     JSValue** k = codeBlock->jsValues.data();
     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
@@ -1046,7 +1040,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         int dst = (++vPC)->u.operand;
         int firstArg = (++vPC)->u.operand;
         int argCount = (++vPC)->u.operand;
-        ArgList args(reinterpret_cast<JSValue***>(&registerBase), r - registerBase + firstArg, argCount);
+        ArgList args(reinterpret_cast<JSValue**>(r) + firstArg, argCount);
         r[dst].u.jsValue = constructArray(exec, args);
 
         ++vPC;
@@ -2238,24 +2232,23 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         if (callType == CallTypeJS) {
             if (*enabledProfilerReference)
                 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
-            int registerOffset = r - registerBase;
-            Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
-            int callFrameOffset = registerOffset + firstArg - RegisterFile::CallFrameHeaderSize;
-
-            r[firstArg].u.jsValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].u.jsValue;
-            initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, registerOffset, dst, firstArg, argCount, 0, v);
 
             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
             FunctionBodyNode* functionBodyNode = callData.js.functionBody;
-
             CodeBlock* newCodeBlock = &functionBodyNode->code(callDataScopeChain);
-            r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, &registerBase, registerOffset, firstArg, argCount, exceptionValue);
+
+            r[firstArg].u.jsValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].u.jsValue;
+
+            Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
+            initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, 0, v);
+            exec->m_callFrame = callFrame;
+
+            r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
             if (UNLIKELY(exceptionValue != 0))
                 goto vm_throw;
 
             codeBlock = newCodeBlock;
-            exec->m_callFrameOffset = callFrameOffset;
-            setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, &registerBase, r));
+            setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
             k = codeBlock->jsValues.data();
             vPC = codeBlock->instructions.begin();
 
@@ -2269,11 +2262,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         if (callType == CallTypeNative) {
             if (*enabledProfilerReference)
                 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
-            int registerOffset = r - registerBase;
 
             JSValue* thisValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].u.jsValue;
-
-            ArgList args(reinterpret_cast<JSValue***>(&registerBase), registerOffset + firstArg + 1, argCount - 1);
+            ArgList args(reinterpret_cast<JSValue**>(r) + firstArg + 1, argCount - 1);
 
             JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(v), thisValue, args);
             VM_CHECK_EXCEPTION();
@@ -2304,11 +2295,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
            
         int result = (++vPC)->u.operand;
 
-        CodeBlock* oldCodeBlock = codeBlock;
-
-        Register* callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
-        JSValue* returnValue = r[result].u.jsValue;
-
+        Register* callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
         if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].u.jsValue)) {
             ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
             ASSERT(activation->isActivationObject());
@@ -2321,6 +2308,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         if (codeBlock->needsFullScopeChain)
             scopeChain->deref();
 
+        JSValue* returnValue = r[result].u.jsValue;
         if (callFrame[RegisterFile::CalledAsConstructor].u.i && !returnValue->isObject()) {
             JSValue* thisObject = callFrame[RegisterFile::CallFrameHeaderSize].u.jsValue;
             returnValue = thisObject;
@@ -2333,9 +2321,8 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         k = codeBlock->jsValues.data();
         vPC = callFrame[RegisterFile::ReturnVPC].u.vPC;
         setScopeChain(exec, scopeChain, callFrame[RegisterFile::CallerScopeChain].u.scopeChain);
-        int callerRegisterOffset = callFrame[RegisterFile::CallerRegisterOffset].u.i;
-        r = registerBase + callerRegisterOffset;
-        exec->m_callFrameOffset = callerRegisterOffset - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
+        r = callFrame[RegisterFile::CallerRegisters].u.r;
+        exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
         int dst = callFrame[RegisterFile::ReturnValueRegister].u.i;
         r[dst].u.jsValue = returnValue;
 
@@ -2369,10 +2356,6 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
             if (*enabledProfilerReference)
                 (*enabledProfilerReference)->willExecute(exec, constructor);
 
-            int registerOffset = r - registerBase;
-            Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
-            int callFrameOffset = registerOffset + firstArg - RegisterFile::CallFrameHeaderSize;
-
             JSObject* prototype;
             JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
             if (p->isObject())
@@ -2380,21 +2363,23 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
             else
                 prototype = scopeChain->globalObject()->objectPrototype();
             JSObject* newObject = new (exec) JSObject(prototype);
-            r[firstArg].u.jsValue = newObject; // "this" value
-
-            initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, registerOffset, dst, firstArg, argCount, 1, constructor);
 
             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
             FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
-
             CodeBlock* newCodeBlock = &functionBodyNode->code(callDataScopeChain);
-            r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, &registerBase, registerOffset, firstArg, argCount, exceptionValue);
+
+            r[firstArg].u.jsValue = newObject; // "this" value
+
+            Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
+            initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, 1, constructor);
+            exec->m_callFrame = callFrame;
+
+            r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
             if (exceptionValue)
                 goto vm_throw;
 
             codeBlock = newCodeBlock;
-            exec->m_callFrameOffset = callFrameOffset;
-            setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, &registerBase, r));
+            setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
             k = codeBlock->jsValues.data();
             vPC = codeBlock->instructions.begin();
 
@@ -2405,8 +2390,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
             if (*enabledProfilerReference)
                 (*enabledProfilerReference)->willExecute(exec, constructor);
 
-            int registerOffset = r - registerBase;
-            ArgList args(reinterpret_cast<JSValue***>(&registerBase), registerOffset + firstArg + 1, argCount - 1);
+            ArgList args(reinterpret_cast<JSValue**>(r) + firstArg + 1, argCount - 1);
             JSValue* returnValue = constructData.native.function(exec, constructor, args);
 
             VM_CHECK_EXCEPTION();
@@ -2537,7 +2521,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
 
         int ex = (++vPC)->u.operand;
         exceptionValue = r[ex].u.jsValue;
-        handlerVPC = throwException(exec, exceptionValue, &registerBase, vPC, codeBlock, k, scopeChain, r);
+        handlerVPC = throwException(exec, exceptionValue, vPC, codeBlock, k, scopeChain, r);
         if (!handlerVPC) {
             *exception = exceptionValue;
             return jsNull();
@@ -2665,7 +2649,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
          is only generated while the debugger is attached.
         */
 
-        debug(exec, vPC, codeBlock, scopeChain, &registerBase, r);
+        debug(exec, vPC, codeBlock, scopeChain, r);
 
         vPC += 4;
         NEXT_OPCODE;
@@ -2677,7 +2661,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
             // cannot fathom if we don't assign to the exceptionValue before branching)
             exceptionValue = createInterruptedExecutionException(exec);
         }
-        handlerVPC = throwException(exec, exceptionValue, &registerBase, vPC, codeBlock, k, scopeChain, r);
+        handlerVPC = throwException(exec, exceptionValue, vPC, codeBlock, k, scopeChain, r);
         if (!handlerVPC) {
             *exception = exceptionValue;
             return jsNull();
@@ -2693,17 +2677,14 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
 
 JSValue* Machine::retrieveArguments(ExecState* exec, JSFunction* function) const
 {
-    Register** registerBase;
-    int callFrameOffset;
-
-    if (!getCallFrame(exec, function, registerBase, callFrameOffset))
+    Register* callFrame = this->callFrame(exec, function);
+    if (!callFrame)
         return jsNull();
 
-    Register* callFrame = (*registerBase) + callFrameOffset;
     JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].u.jsValue);
     if (!activation) {
         CodeBlock* codeBlock = &function->body->generatedCode();
-        activation = new (exec) JSActivation(function->body, registerBase, callFrameOffset + RegisterFile::CallFrameHeaderSize + codeBlock->numLocals);
+        activation = new (exec) JSActivation(function->body, callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numLocals);
         callFrame[RegisterFile::OptionalCalleeActivation].u.jsValue = activation;
     }
 
@@ -2712,59 +2693,53 @@ JSValue* Machine::retrieveArguments(ExecState* exec, JSFunction* function) const
 
 JSValue* Machine::retrieveCaller(ExecState* exec, JSFunction* function) const
 {
-    Register** registerBase;
-    int callFrameOffset;
-    if (!getCallFrame(exec, function, registerBase, callFrameOffset))
+    Register* callFrame = this->callFrame(exec, function);
+    if (!callFrame)
         return jsNull();
 
-    Register* callFrame = (*registerBase) + callFrameOffset;
     CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].u.codeBlock;
     if (!callerCodeBlock)
         return jsNull();
 
-    int callerCallFrameOffset = callFrame[RegisterFile::CallerRegisterOffset].u.i - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
-    Register* callerCallFrame = (*registerBase) + callerCallFrameOffset;
-
+    Register* callerCallFrame = callFrame[RegisterFile::CallerRegisters].u.r - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
     if (JSValue* caller = callerCallFrame[RegisterFile::Callee].u.jsValue)
         return caller;
 
     return jsNull();
 }
 
-bool Machine::getCallFrame(ExecState* exec, JSFunction* function, Register**& registerBase, int& callFrameOffset) const
+Register* Machine::callFrame(ExecState* exec, JSFunction* function) const
 {
-    callFrameOffset = exec->m_callFrameOffset;
+    Register* callFrame = exec->m_callFrame;
 
     while (1) {
-        while (callFrameOffset == -1) {
+        while (!callFrame) {
             exec = exec->m_prev;
             if (!exec)
-                return false;
-            callFrameOffset = exec->m_callFrameOffset;
+                return 0;
+            callFrame = exec->m_callFrame;
         }
 
-        registerBase = exec->m_registerFile->basePointer();
-        Register* callFrame = (*registerBase) + callFrameOffset;
         if (callFrame[RegisterFile::Callee].u.jsValue == function)
-            return true;
+            return callFrame;
 
         CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].u.codeBlock;
         if (!callerCodeBlock) {
-            callFrameOffset = -1;
+            callFrame = 0;
             continue;
         }
         
-        callFrameOffset = callFrame[RegisterFile::CallerRegisterOffset].u.i - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
+        callFrame = callFrame[RegisterFile::CallerRegisters].u.r - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
     }
 }
 
-void Machine::getFunctionAndArguments(Register** registerBase, Register* callFrame, JSFunction*& function, Register*& argv, int& argc)
+void Machine::getArgumentsData(Register* callFrame, JSFunction*& function, Register*& argv, int& argc)
 {
     function = static_cast<JSFunction*>(callFrame[RegisterFile::Callee].u.jsValue);
     ASSERT(function->inherits(&JSFunction::info));
 
-    argv = (*registerBase) + callFrame[RegisterFile::CallerRegisterOffset].u.i + callFrame[RegisterFile::ArgumentStartRegister].u.i + 1; // skip "this"
-    argc = callFrame[RegisterFile::ArgumentCount].u.i - 1; // skip "this"
+    argv = callFrame[RegisterFile::CallerRegisters].u.r + callFrame[RegisterFile::ArgumentStartRegister].u.i + 1; //  + 1 to skip "this"
+    argc = callFrame[RegisterFile::ArgumentCount].u.i - 1; // - 1 to skip "this"
 }
 
 } // namespace KJS
index e32c5ae..174ed52 100644 (file)
@@ -95,7 +95,7 @@ namespace KJS {
         JSValue* retrieveArguments(ExecState*, JSFunction*) const;
         JSValue* retrieveCaller(ExecState*, JSFunction*) const;
 
-        void getFunctionAndArguments(Register** registerBase, Register* callFrame, JSFunction*&, Register*& argv, int& argc);
+        void getArgumentsData(Register* callFrame, JSFunction*&, Register*& argv, int& argc);
         void setTimeoutTime(unsigned timeoutTime) { m_timeoutTime = timeoutTime; }
         
         void startTimeoutCheck()
@@ -126,12 +126,12 @@ namespace KJS {
         JSValue* execute(EvalNode*, ExecState*, JSObject* thisObj, int registerOffset, ScopeChainNode*, JSValue** exception);
 
         ALWAYS_INLINE void setScopeChain(ExecState* exec, ScopeChainNode*&, ScopeChainNode*);
-        NEVER_INLINE void debug(ExecState*, const Instruction*, const CodeBlock*, ScopeChainNode*, Register**, Register*);
+        NEVER_INLINE void debug(ExecState*, const Instruction*, const CodeBlock*, ScopeChainNode*, Register*);
 
-        NEVER_INLINE bool unwindCallFrame(ExecState*, JSValue*, Register**, const Instruction*&, CodeBlock*&, JSValue**&, ScopeChainNode*&, Register*&);
-        NEVER_INLINE Instruction* throwException(ExecState*, JSValue*, Register**, const Instruction*, CodeBlock*&, JSValue**&, ScopeChainNode*&, Register*&);
+        NEVER_INLINE bool unwindCallFrame(ExecState*, JSValue*, const Instruction*&, CodeBlock*&, JSValue**&, ScopeChainNode*&, Register*&);
+        NEVER_INLINE Instruction* throwException(ExecState*, JSValue*, const Instruction*, CodeBlock*&, JSValue**&, ScopeChainNode*&, Register*&);
 
-        bool getCallFrame(ExecState*, JSFunction*, Register**& registerBase, int& callFrameOffset) const;
+        Register* callFrame(ExecState*, JSFunction*) const;
 
         JSValue* privateExecute(ExecutionFlag, ExecState* = 0, RegisterFile* = 0, Register* = 0, ScopeChainNode* = 0, CodeBlock* = 0, JSValue** exception = 0);
 
index fbaaec7..bdfe76b 100644 (file)
@@ -93,7 +93,7 @@ namespace KJS {
             CallerCodeBlock = 0,
             ReturnVPC,
             CallerScopeChain,
-            CallerRegisterOffset,
+            CallerRegisters,
             ReturnValueRegister,
             ArgumentStartRegister,
             ArgumentCount,
@@ -133,8 +133,7 @@ namespace KJS {
 
         ~RegisterFile();
 
-        // Pointer to a value that holds the base of this register file.
-        Register** basePointer() { return &m_base; }
+        Register* base() const { return m_base; }
         
         void setGlobalObject(JSGlobalObject* globalObject) { m_globalObject = globalObject; }
         JSGlobalObject* globalObject() { return m_globalObject; }
index 26cb209..7f19898 100644 (file)
 
 namespace KJS {
 
-Register* DebuggerCallFrame::r() const
-{
-    return *m_registerBase + m_registerOffset;
-}
-
 Register* DebuggerCallFrame::callFrame() const
 {
-    return r() - m_codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
+    return m_registers - m_codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
 }
 
 const UString* DebuggerCallFrame::functionName() const
@@ -70,7 +65,7 @@ JSObject* DebuggerCallFrame::thisObject() const
     if (!m_codeBlock)
         return 0;
 
-    return static_cast<JSObject*>(r()[m_codeBlock->thisRegister].u.jsValue);
+    return static_cast<JSObject*>(m_registers[m_codeBlock->thisRegister].u.jsValue);
 }
 
 JSValue* DebuggerCallFrame::evaluate(const UString& script, JSValue*& exception) const
index ed9ee67..778318d 100644 (file)
@@ -47,13 +47,12 @@ namespace KJS {
             FunctionType
         } Type;
 
-        DebuggerCallFrame(JSGlobalObject* dynamicGlobalObject, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, JSValue* exception, Register** registerBase, int registerOffset)
+        DebuggerCallFrame(JSGlobalObject* dynamicGlobalObject, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register* r, JSValue* exception)
             : m_dynamicGlobalObject(dynamicGlobalObject)
             , m_codeBlock(codeBlock)
             , m_scopeChain(scopeChain)
+            , m_registers(r)
             , m_exception(exception)
-            , m_registerBase(registerBase)
-            , m_registerOffset(registerOffset)
         {
         }
 
@@ -66,15 +65,13 @@ namespace KJS {
         JSValue* exception() const { return m_exception; }
 
     private:
-        Register* r() const;
         Register* callFrame() const;
 
         JSGlobalObject* m_dynamicGlobalObject;
         const CodeBlock* m_codeBlock;
         ScopeChainNode* m_scopeChain;
+        Register* m_registers;
         JSValue* m_exception;
-        Register** m_registerBase;
-        int m_registerOffset;
     };
 
 } // namespace KJS
index 09a8812..55bf414 100644 (file)
@@ -39,11 +39,11 @@ ExecState::ExecState(JSGlobalObject* globalObject, JSObject* globalThisValue, Sc
     , m_prev(0)
     , m_registerFile(0)
     , m_scopeChain(globalScopeChain)
-    , m_callFrameOffset(-1)
+    , m_callFrame(0)
 {
 }
 
-ExecState::ExecState(ExecState* exec, RegisterFile* registerFile, ScopeChainNode* scopeChain, int callFrameOffset)
+ExecState::ExecState(ExecState* exec, RegisterFile* registerFile, ScopeChainNode* scopeChain, Register* callFrame)
     : m_globalObject(exec->m_globalObject)
     , m_globalThisValue(exec->m_globalThisValue)
     , m_exception(0)
@@ -51,7 +51,7 @@ ExecState::ExecState(ExecState* exec, RegisterFile* registerFile, ScopeChainNode
     , m_prev(exec)
     , m_registerFile(registerFile)
     , m_scopeChain(scopeChain)
-    , m_callFrameOffset(callFrameOffset)
+    , m_callFrame(callFrame)
 {
     ASSERT(!exec->m_exception);
 }
index cc65b53..1106cab 100644 (file)
@@ -38,6 +38,7 @@ namespace KJS  {
     class JSVariableObject;
     class Machine;
     class ProgramNode;
+    class Register;
     class RegisterFile;
     class ScopeNode;
 
@@ -93,7 +94,7 @@ namespace KJS  {
         // Default constructor required for gcc 3.
         ExecState() { }
 
-        ExecState(ExecState*, RegisterFile*, ScopeChainNode*, int callFrameOffset);
+        ExecState(ExecState*, RegisterFile*, ScopeChainNode*, Register* callFrame);
 
         bool isGlobalObject(JSObject*) const;
 
@@ -108,7 +109,7 @@ namespace KJS  {
         ExecState* m_prev;
         RegisterFile* m_registerFile;
         ScopeChainNode* m_scopeChain;
-        int m_callFrameOffset; // A negative offset indicates a non-function scope.
+        Register* m_callFrame; // The most recent call frame.
     };
 
     enum CodeType { GlobalCode, EvalCode, FunctionCode };
index aed5f90..1334ee6 100644 (file)
@@ -38,8 +38,8 @@ namespace KJS {
 
 const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 };
 
-JSActivation::JSActivation(PassRefPtr<FunctionBodyNode> functionBody, Register** registerBase, int registerOffset)
-    : Base(new JSActivationData(functionBody, registerBase, registerOffset))
+JSActivation::JSActivation(PassRefPtr<FunctionBodyNode> functionBody, Register* registers)
+    : Base(new JSActivationData(functionBody, registers))
 {
 }
 
@@ -54,7 +54,7 @@ void JSActivation::copyRegisters()
     if (!numLocals)
         return;
 
-    copyRegisterArray(registers() - numLocals, numLocals);
+    copyRegisterArray(d()->registers - numLocals, numLocals);
 }
 
 bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -155,13 +155,14 @@ PropertySlot::GetValueFunc JSActivation::getArgumentsGetter()
 
 JSObject* JSActivation::createArgumentsObject(ExecState* exec)
 {
-    Register* callFrame = registers() - d()->functionBody->generatedCode().numLocals - RegisterFile::CallFrameHeaderSize;
+    Register* callFrame = d()->registers - d()->functionBody->generatedCode().numLocals - RegisterFile::CallFrameHeaderSize;
 
     JSFunction* function;
     Register* argv;
     int argc;
-    exec->machine()->getFunctionAndArguments(registerBase(), callFrame, function, argv, argc);
-    ArgList args(reinterpret_cast<JSValue***>(registerBase()), argv - *registerBase(), argc);
+    exec->machine()->getArgumentsData(callFrame, function, argv, argc);
+
+    ArgList args(reinterpret_cast<JSValue**>(argv), argc);
     return new (exec) Arguments(exec, function, args, this);
 }
 
index 9db36e0..694102b 100644 (file)
@@ -40,7 +40,7 @@ namespace KJS {
     class JSActivation : public JSVariableObject {
     typedef JSVariableObject Base;
     public:
-        JSActivation(PassRefPtr<FunctionBodyNode>, Register**, int registerOffset);
+        JSActivation(PassRefPtr<FunctionBodyNode>, Register*);
         virtual ~JSActivation();
         
         virtual bool isActivationObject() const;
@@ -63,8 +63,8 @@ namespace KJS {
 
     private:
         struct JSActivationData : public JSVariableObjectData {
-            JSActivationData(PassRefPtr<FunctionBodyNode> functionBody_, Register** registerBase, int registerOffset)
-                : JSVariableObjectData(&functionBody_->symbolTable(), registerBase, registerOffset)
+            JSActivationData(PassRefPtr<FunctionBodyNode> functionBody_, Register* registers)
+                : JSVariableObjectData(&functionBody_->symbolTable(), registers)
                 , functionBody(functionBody_)
                 , argumentsObject(0)
             {
index 7965b4b..10e5322 100644 (file)
@@ -394,11 +394,11 @@ bool JSGlobalObject::isDynamicScope() const
 void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile)
 {
     ASSERT(!d()->registerArray);
+    ASSERT(!d()->registerArraySize);
 
     int numGlobals = registerFile.numGlobals();
     if (!numGlobals) {
-        ASSERT(!d()->registerOffset);
-        d()->registerBase = 0;
+        d()->registers = 0;
         return;
     }
     copyRegisterArray(registerFile.lastGlobal(), numGlobals);
@@ -414,12 +414,11 @@ void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile)
     registerFile.setNumGlobals(symbolTable().size());
 
     if (d()->registerArray) {
-        memcpy(*registerFile.basePointer() - d()->registerOffset, d()->registerArray, d()->registerOffset * sizeof(Register));
+        memcpy(registerFile.base() - d()->registerArraySize, d()->registerArray.get(), d()->registerArraySize * sizeof(Register));
         setRegisterArray(0, 0);
     }
 
-    d()->registerBase = registerFile.basePointer();
-    d()->registerOffset = 0;
+    d()->registers = registerFile.base();
 }
 
 void* JSGlobalObject::operator new(size_t size)
index 3f91218..c52217b 100644 (file)
@@ -74,7 +74,7 @@ namespace KJS {
 
         struct JSGlobalObjectData : public JSVariableObjectData {
             JSGlobalObjectData(JSGlobalObject* globalObject, JSObject* thisValue)
-                : JSVariableObjectData(&symbolTable, 0, 0)
+                : JSVariableObjectData(&symbolTable, 0)
                 , globalScopeChain(globalObject, thisValue)
             {
             }
@@ -258,13 +258,13 @@ namespace KJS {
 
     inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
     {
-        int numGlobals = d()->registerOffset;
-        Register* registerArray = static_cast<Register*>(fastMalloc((numGlobals + count) * sizeof(Register)));
+        size_t registerArraySize = d()->registerArraySize;
+        Register* registerArray = static_cast<Register*>(fastMalloc((registerArraySize + count) * sizeof(Register)));
         if (d()->registerArray)
-            memcpy(registerArray + count, d()->registerArray, numGlobals * sizeof(Register));
-        setRegisterArray(registerArray, numGlobals + count);
+            memcpy(registerArray + count, d()->registerArray.get(), registerArraySize * sizeof(Register));
+        setRegisterArray(registerArray, registerArraySize + count);
 
-        for (int i = 0, index = -numGlobals - 1; i < count; ++i, --index) {
+        for (int i = 0, index = -registerArraySize - 1; i < count; ++i, --index) {
             GlobalPropertyInfo& global = globals[i];
             ASSERT(global.attributes & DontDelete);
             SymbolTableEntry newEntry(index, global.attributes);
index 5959035..de07310 100644 (file)
@@ -70,8 +70,8 @@ void JSVariableObject::mark()
     if(!d->registerArray)
         return;
     
-    Register* end = d->registerArray + d->registerOffset;
-    for (Register* it = d->registerArray; it != end; ++it) {
+    Register* end = d->registerArray.get() + d->registerArraySize;
+    for (Register* it = d->registerArray.get(); it != end; ++it) {
         JSValue* v = (*it).u.jsValue;
         if (!v->marked())
             v->mark();
@@ -95,10 +95,9 @@ void JSVariableObject::copyRegisterArray(Register* src, size_t count)
 
 void JSVariableObject::setRegisterArray(Register* registerArray, size_t count)
 {
-    delete d->registerArray;
-    d->registerArray = registerArray;
-    d->registerBase = &d->registerArray;
-    d->registerOffset = count;
+    d->registerArray.set(registerArray);
+    d->registerArraySize = count;
+    d->registers = registerArray + count;
 }
 
 } // namespace KJS
index fd1d51c..57cb598 100644 (file)
 #ifndef JSVariableObject_h
 #define JSVariableObject_h
 
+#include "JSObject.h"
 #include "Register.h"
 #include "SymbolTable.h"
 #include "UnusedParam.h"
-#include "JSObject.h"
+#include <wtf/OwnPtr.h>
 #include <wtf/UnusedParam.h>
 
 namespace KJS {
@@ -54,33 +55,25 @@ namespace KJS {
 
         virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
 
-        JSValue*& valueAt(int index) const { return registers()[index].u.jsValue; }
+        JSValue*& valueAt(int index) const { return d->registers[index].u.jsValue; }
 
     protected:
         // Subclasses of JSVariableObject can subclass this struct to add data
         // without increasing their own size (since there's a hard limit on the
         // size of a JSCell).
         struct JSVariableObjectData {
-            JSVariableObjectData(SymbolTable* symbolTable_, Register** registerBase_, int registerOffset_)
+            JSVariableObjectData(SymbolTable* symbolTable_, Register* registers_)
                 : symbolTable(symbolTable_)
-                , registerBase(registerBase_)
-                , registerOffset(registerOffset_)
-                , registerArray(0)
+                , registers(registers_)
+                , registerArraySize(0)
             {
                 ASSERT(symbolTable_);
             }
             
-            ~JSVariableObjectData()
-            {
-                delete registerArray;
-            }
-
             SymbolTable* symbolTable; // Maps name -> offset from "r" in register file.
-
-            Register** registerBase; // Location where a pointer to the base of the register file is stored.
-            int registerOffset; // Offset of "r", the register past the end of local storage.
-
-            Register* registerArray; // Independent copy of registers that were once stored in the register file.
+            Register* registers; // Pointers to the register past the end of local storage. (Local storage indexes are negative.)
+            OwnPtr<Register> registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
+            size_t registerArraySize;
         };
 
         JSVariableObject(JSVariableObjectData* data)
@@ -94,9 +87,6 @@ namespace KJS {
         {
         }
 
-        Register** registerBase() const { return d->registerBase; }
-        Register* registers() const { return *registerBase() + d->registerOffset; }
-        
         void copyRegisterArray(Register* src, size_t count);
         void setRegisterArray(Register* registerArray, size_t count);
 
index e795995..6720f0e 100644 (file)
@@ -34,7 +34,7 @@ void ArgList::getSlice(int startIndex, ArgList& result) const
     const_iterator start = min(begin() + startIndex, end());
     result.m_vector.appendRange(start, end());
     result.m_size = result.m_vector.size();
-    result.m_bufferSlot = result.m_vector.dataSlot();
+    result.m_buffer = result.m_vector.data();
 }
 
 void ArgList::markLists(ListSet& markSet)
@@ -79,7 +79,7 @@ void ArgList::slowAppend(JSValue* v)
     m_vector.reserveCapacity(m_vector.capacity() * 4);
     
     m_vector.uncheckedAppend(v);
-    m_bufferSlot = m_vector.dataSlot();
+    m_buffer = m_vector.data();
 }
 
 } // namespace KJS
index 3e93d66..5137dfc 100644 (file)
@@ -50,15 +50,13 @@ namespace KJS {
             , m_isReadOnly(false)
 #endif
         {
-            m_bufferSlot = m_vector.dataSlot();
-            m_offset = 0;
+            m_buffer = m_vector.data();
             m_size = 0;
         }
 
         // Constructor for a read-only list whose data has already been allocated elsewhere.
-        ArgList(JSValue*** bufferSlot, size_t offset, size_t size)
-            : m_bufferSlot(bufferSlot)
-            , m_offset(offset)
+        ArgList(JSValue** buffer, size_t size)
+            : m_buffer(buffer)
             , m_size(size)
             , m_markSet(0)
 #ifndef NDEBUG
@@ -79,7 +77,7 @@ namespace KJS {
         JSValue* at(size_t i) const
         {
             if (i < m_size)
-                return buffer()[i];
+                return m_buffer[i];
             return jsUndefined();
         }
 
@@ -88,6 +86,7 @@ namespace KJS {
         void clear()
         {
             m_vector.clear();
+            m_buffer = 0;
             m_size = 0;
         }
 
@@ -108,21 +107,18 @@ namespace KJS {
 
         void getSlice(int startIndex, ArgList& result) const;
 
-        iterator begin() { return buffer(); }
-        iterator end() { return buffer() + m_size; }
+        iterator begin() { return m_buffer; }
+        iterator end() { return m_buffer + m_size; }
 
-        const_iterator begin() const { return buffer(); }
-        const_iterator end() const { return buffer() + m_size; }
+        const_iterator begin() const { return m_buffer; }
+        const_iterator end() const { return m_buffer + m_size; }
 
         static void markLists(ListSet&);
 
     private:
         void slowAppend(JSValue*);
         
-        JSValue** buffer() const { return *m_bufferSlot + m_offset; }
-
-        JSValue*** m_bufferSlot;
-        size_t m_offset;
+        JSValue** m_buffer;
         size_t m_size;
 
         VectorType m_vector;