VirtualRegister should be a class
authormsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Sep 2013 17:50:46 +0000 (17:50 +0000)
committermsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Sep 2013 17:50:46 +0000 (17:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=121732

Reviewed by Geoffrey Garen.

This is a refactoring change.  Changed VirtualRegister from an enum to a class.
Moved Operands::operandIsArgument(), operandToArgument(), argumentToOperand()
and the similar functions for locals to VirtualRegister class.

This is in preparation for changing the offset for the first local register from
0 to -1.  This is needed since most native calling conventions have the architected
frame pointer (e.g. %rbp for X86) point at the slot that stores the previous frame
pointer.  Local values start below that address.

* bytecode/CodeBlock.cpp:
* bytecode/CodeBlock.h:
* bytecode/Instruction.h:
* bytecode/LazyOperandValueProfile.h:
* bytecode/MethodOfGettingAValueProfile.cpp:
* bytecode/Operands.h:
* bytecode/UnlinkedCodeBlock.cpp:
* bytecode/UnlinkedCodeBlock.h:
* bytecode/ValueRecovery.h:
* bytecode/VirtualRegister.h:
* bytecompiler/BytecodeGenerator.cpp:
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/RegisterID.h:
* debugger/DebuggerCallFrame.cpp:
* dfg/DFGAbstractHeap.h:
* dfg/DFGAbstractInterpreterInlines.h:
* dfg/DFGArgumentPosition.h:
* dfg/DFGArgumentsSimplificationPhase.cpp:
* dfg/DFGByteCodeParser.cpp:
* dfg/DFGCFGSimplificationPhase.cpp:
* dfg/DFGCPSRethreadingPhase.cpp:
* dfg/DFGCapabilities.cpp:
* dfg/DFGConstantFoldingPhase.cpp:
* dfg/DFGFlushLivenessAnalysisPhase.cpp:
* dfg/DFGGraph.cpp:
* dfg/DFGGraph.h:
* dfg/DFGJITCode.cpp:
* dfg/DFGNode.h:
* dfg/DFGOSREntry.cpp:
* dfg/DFGOSREntrypointCreationPhase.cpp:
* dfg/DFGOSRExit.h:
* dfg/DFGOSRExitCompiler32_64.cpp:
* dfg/DFGOSRExitCompiler64.cpp:
* dfg/DFGRegisterBank.h:
* dfg/DFGScoreBoard.h:
* dfg/DFGSpeculativeJIT.cpp:
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT64.cpp:
* dfg/DFGValidate.cpp:
* dfg/DFGValueRecoveryOverride.h:
* dfg/DFGVariableAccessData.h:
* dfg/DFGVariableEvent.h:
* dfg/DFGVariableEventStream.cpp:
* dfg/DFGVirtualRegisterAllocationPhase.cpp:
* ftl/FTLExitArgumentForOperand.h:
* ftl/FTLLink.cpp:
* ftl/FTLLowerDFGToLLVM.cpp:
* ftl/FTLOSREntry.cpp:
* ftl/FTLOSRExit.cpp:
* ftl/FTLOSRExit.h:
* ftl/FTLOSRExitCompiler.cpp:
* interpreter/CallFrame.h:
* interpreter/Interpreter.cpp:
* jit/AssemblyHelpers.h:
* jit/JIT.h:
* jit/JITCall.cpp:
* jit/JITInlines.h:
* jit/JITOpcodes.cpp:
* jit/JITOpcodes32_64.cpp:
* jit/JITStubs.cpp:
* llint/LLIntSlowPaths.cpp:
* profiler/ProfilerBytecodeSequence.cpp:
* runtime/CommonSlowPaths.cpp:
* runtime/JSActivation.cpp:

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

65 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/Instruction.h
Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h
Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp
Source/JavaScriptCore/bytecode/Operands.h
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
Source/JavaScriptCore/bytecode/ValueRecovery.h
Source/JavaScriptCore/bytecode/VirtualRegister.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/bytecompiler/RegisterID.h
Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
Source/JavaScriptCore/dfg/DFGAbstractHeap.h
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGArgumentPosition.h
Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
Source/JavaScriptCore/dfg/DFGCapabilities.cpp
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Source/JavaScriptCore/dfg/DFGFlushLivenessAnalysisPhase.cpp
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGJITCode.cpp
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGOSREntry.cpp
Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp
Source/JavaScriptCore/dfg/DFGOSRExit.h
Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
Source/JavaScriptCore/dfg/DFGRegisterBank.h
Source/JavaScriptCore/dfg/DFGScoreBoard.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGValidate.cpp
Source/JavaScriptCore/dfg/DFGValueRecoveryOverride.h
Source/JavaScriptCore/dfg/DFGVariableAccessData.h
Source/JavaScriptCore/dfg/DFGVariableEvent.h
Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp
Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp
Source/JavaScriptCore/ftl/FTLExitArgumentForOperand.h
Source/JavaScriptCore/ftl/FTLLink.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
Source/JavaScriptCore/ftl/FTLOSREntry.cpp
Source/JavaScriptCore/ftl/FTLOSRExit.cpp
Source/JavaScriptCore/ftl/FTLOSRExit.h
Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
Source/JavaScriptCore/interpreter/CallFrame.h
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/jit/AssemblyHelpers.h
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITCall.cpp
Source/JavaScriptCore/jit/JITInlines.h
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
Source/JavaScriptCore/jit/JITStubs.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/JSActivation.cpp

index 1f4f4ee..00b8529 100644 (file)
@@ -1,3 +1,84 @@
+2013-09-25  Michael Saboff  <msaboff@apple.com>
+
+        VirtualRegister should be a class
+        https://bugs.webkit.org/show_bug.cgi?id=121732
+
+        Reviewed by Geoffrey Garen.
+
+        This is a refactoring change.  Changed VirtualRegister from an enum to a class.
+        Moved Operands::operandIsArgument(), operandToArgument(), argumentToOperand()
+        and the similar functions for locals to VirtualRegister class.
+
+        This is in preparation for changing the offset for the first local register from
+        0 to -1.  This is needed since most native calling conventions have the architected
+        frame pointer (e.g. %rbp for X86) point at the slot that stores the previous frame
+        pointer.  Local values start below that address.
+
+        * bytecode/CodeBlock.cpp:
+        * bytecode/CodeBlock.h:
+        * bytecode/Instruction.h:
+        * bytecode/LazyOperandValueProfile.h:
+        * bytecode/MethodOfGettingAValueProfile.cpp:
+        * bytecode/Operands.h:
+        * bytecode/UnlinkedCodeBlock.cpp:
+        * bytecode/UnlinkedCodeBlock.h:
+        * bytecode/ValueRecovery.h:
+        * bytecode/VirtualRegister.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/RegisterID.h:
+        * debugger/DebuggerCallFrame.cpp:
+        * dfg/DFGAbstractHeap.h:
+        * dfg/DFGAbstractInterpreterInlines.h:
+        * dfg/DFGArgumentPosition.h:
+        * dfg/DFGArgumentsSimplificationPhase.cpp:
+        * dfg/DFGByteCodeParser.cpp:
+        * dfg/DFGCFGSimplificationPhase.cpp:
+        * dfg/DFGCPSRethreadingPhase.cpp:
+        * dfg/DFGCapabilities.cpp:
+        * dfg/DFGConstantFoldingPhase.cpp:
+        * dfg/DFGFlushLivenessAnalysisPhase.cpp:
+        * dfg/DFGGraph.cpp:
+        * dfg/DFGGraph.h:
+        * dfg/DFGJITCode.cpp:
+        * dfg/DFGNode.h:
+        * dfg/DFGOSREntry.cpp:
+        * dfg/DFGOSREntrypointCreationPhase.cpp:
+        * dfg/DFGOSRExit.h:
+        * dfg/DFGOSRExitCompiler32_64.cpp:
+        * dfg/DFGOSRExitCompiler64.cpp:
+        * dfg/DFGRegisterBank.h:
+        * dfg/DFGScoreBoard.h:
+        * dfg/DFGSpeculativeJIT.cpp:
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT64.cpp:
+        * dfg/DFGValidate.cpp:
+        * dfg/DFGValueRecoveryOverride.h:
+        * dfg/DFGVariableAccessData.h:
+        * dfg/DFGVariableEvent.h:
+        * dfg/DFGVariableEventStream.cpp:
+        * dfg/DFGVirtualRegisterAllocationPhase.cpp:
+        * ftl/FTLExitArgumentForOperand.h:
+        * ftl/FTLLink.cpp:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        * ftl/FTLOSREntry.cpp:
+        * ftl/FTLOSRExit.cpp:
+        * ftl/FTLOSRExit.h:
+        * ftl/FTLOSRExitCompiler.cpp:
+        * interpreter/CallFrame.h:
+        * interpreter/Interpreter.cpp:
+        * jit/AssemblyHelpers.h:
+        * jit/JIT.h:
+        * jit/JITCall.cpp:
+        * jit/JITInlines.h:
+        * jit/JITOpcodes.cpp:
+        * jit/JITOpcodes32_64.cpp:
+        * jit/JITStubs.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        * profiler/ProfilerBytecodeSequence.cpp:
+        * runtime/CommonSlowPaths.cpp:
+        * runtime/JSActivation.cpp:
+
 2013-09-26  Anders Carlsson  <andersca@apple.com>
 
         Weak should have a move constructor and move assignment operator
index e7b66dc..e11fbbd 100644 (file)
@@ -168,12 +168,12 @@ CString CodeBlock::registerName(int r) const
         return constantName(r, getConstant(r));
 
     if (operandIsArgument(r)) {
-        if (!operandToArgument(r))
+        if (!VirtualRegister(r).toArgument())
             return "this";
-        return toCString("arg", operandToArgument(r));
+        return toCString("arg", VirtualRegister(r).toArgument());
     }
 
-    return toCString("loc", operandToLocal(r));
+    return toCString("loc", VirtualRegister(r).toLocal());
 }
 
 static CString regexpToSourceString(RegExp* regExp)
@@ -514,11 +514,11 @@ void CodeBlock::dumpBytecode(PrintStream& out)
     if (usesArguments()) {
         out.printf(
             "; uses arguments, in r%d, r%d",
-            argumentsRegister(),
-            unmodifiedArgumentsRegister(argumentsRegister()));
+            argumentsRegister().offset(),
+            unmodifiedArgumentsRegister(argumentsRegister()).offset());
     }
     if (needsFullScopeChain() && codeType() == FunctionCode)
-        out.printf("; activation in r%d", activationRegister());
+        out.printf("; activation in r%d", activationRegister().offset());
     out.printf("\n");
     
     const Instruction* begin = instructions().begin();
@@ -1619,7 +1619,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
 
     setConstantRegisters(unlinkedCodeBlock->constantRegisters());
     if (unlinkedCodeBlock->usesGlobalObject())
-        m_constantRegisters[unlinkedCodeBlock->globalObjectRegister()].set(*m_vm, ownerExecutable, m_globalObject.get());
+        m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().offset()].set(*m_vm, ownerExecutable, m_globalObject.get());
     m_functionDecls.grow(unlinkedCodeBlock->numberOfFunctionDecls());
     for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) {
         UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
@@ -2557,9 +2557,9 @@ void CodeBlock::createActivation(CallFrame* callFrame)
 {
     ASSERT(codeType() == FunctionCode);
     ASSERT(needsFullScopeChain());
-    ASSERT(!callFrame->uncheckedR(activationRegister()).jsValue());
+    ASSERT(!callFrame->uncheckedR(activationRegister().offset()).jsValue());
     JSActivation* activation = JSActivation::create(callFrame->vm(), callFrame, this);
-    callFrame->uncheckedR(activationRegister()) = JSValue(activation);
+    callFrame->uncheckedR(activationRegister().offset()) = JSValue(activation);
     callFrame->setScope(activation);
 }
 
@@ -3327,32 +3327,30 @@ bool CodeBlock::usesOpcode(OpcodeID opcodeID)
     return false;
 }
 
-String CodeBlock::nameForRegister(int registerNumber)
+String CodeBlock::nameForRegister(VirtualRegister virtualRegister)
 {
     ConcurrentJITLocker locker(symbolTable()->m_lock);
     SymbolTable::Map::iterator end = symbolTable()->end(locker);
     for (SymbolTable::Map::iterator ptr = symbolTable()->begin(locker); ptr != end; ++ptr) {
-        if (ptr->value.getIndex() == registerNumber) {
+        if (ptr->value.getIndex() == virtualRegister.offset()) {
             // FIXME: This won't work from the compilation thread.
             // https://bugs.webkit.org/show_bug.cgi?id=115300
             return String(ptr->key);
         }
     }
-    if (needsActivation() && registerNumber == activationRegister())
+    if (needsActivation() && virtualRegister == activationRegister())
         return ASCIILiteral("activation");
-    if (registerNumber == thisRegister())
+    if (virtualRegister == thisRegister())
         return ASCIILiteral("this");
     if (usesArguments()) {
-        if (registerNumber == argumentsRegister())
+        if (virtualRegister == argumentsRegister())
             return ASCIILiteral("arguments");
-        if (unmodifiedArgumentsRegister(argumentsRegister()) == registerNumber)
+        if (unmodifiedArgumentsRegister(argumentsRegister()) == virtualRegister)
             return ASCIILiteral("real arguments");
     }
-    if (registerNumber < 0) {
-        int argumentPosition = -registerNumber;
-        argumentPosition -= JSStack::CallFrameHeaderSize + 1;
-        return String::format("arguments[%3d]", argumentPosition - 1).impl();
-    }
+    if (virtualRegister.isArgument())
+        return String::format("arguments[%3d]", virtualRegister.toArgument()).impl();
+
     return "";
 }
 
index a987e24..5539ac9 100644 (file)
@@ -71,6 +71,7 @@
 #include "StructureStubInfo.h"
 #include "UnconditionalFinalizer.h"
 #include "ValueProfile.h"
+#include "VirtualRegister.h"
 #include "Watchpoint.h"
 #include <wtf/FastMalloc.h>
 #include <wtf/PassOwnPtr.h>
@@ -86,7 +87,7 @@ class ExecState;
 class LLIntOffsetsExtractor;
 class RepatchBuffer;
 
-inline int unmodifiedArgumentsRegister(int argumentsRegister) { return argumentsRegister + 1; }
+inline VirtualRegister unmodifiedArgumentsRegister(VirtualRegister argumentsRegister) { return VirtualRegister(argumentsRegister.offset() + 1); }
 
 static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
 
@@ -148,7 +149,7 @@ public:
 
     inline bool isKnownNotImmediate(int index)
     {
-        if (index == m_thisRegister && !m_isStrictMode)
+        if (index == m_thisRegister.offset() && !m_isStrictMode)
             return true;
 
         if (isConstantRegisterIndex(index))
@@ -298,58 +299,61 @@ public:
     void setVM(VM* vm) { m_vm = vm; }
     VM* vm() { return m_vm; }
 
-    void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
-    int thisRegister() const { return m_thisRegister; }
+    void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; }
+    VirtualRegister thisRegister() const { return m_thisRegister; }
 
     bool needsFullScopeChain() const { return m_unlinkedCode->needsFullScopeChain(); }
     bool usesEval() const { return m_unlinkedCode->usesEval(); }
 
-    void setArgumentsRegister(int argumentsRegister)
+    void setArgumentsRegister(VirtualRegister argumentsRegister)
     {
-        ASSERT(argumentsRegister != (int)InvalidVirtualRegister);
+        ASSERT(argumentsRegister.isValid());
         m_argumentsRegister = argumentsRegister;
         ASSERT(usesArguments());
     }
-    int argumentsRegister() const
+    VirtualRegister argumentsRegister() const
     {
         ASSERT(usesArguments());
         return m_argumentsRegister;
     }
-    int uncheckedArgumentsRegister()
+    VirtualRegister uncheckedArgumentsRegister()
     {
         if (!usesArguments())
-            return InvalidVirtualRegister;
+            return VirtualRegister();
         return argumentsRegister();
     }
-    void setActivationRegister(int activationRegister)
+    void setActivationRegister(VirtualRegister activationRegister)
     {
         m_activationRegister = activationRegister;
     }
-    int activationRegister() const
+
+    VirtualRegister activationRegister() const
     {
         ASSERT(needsFullScopeChain());
         return m_activationRegister;
     }
-    int uncheckedActivationRegister()
+
+    VirtualRegister uncheckedActivationRegister()
     {
         if (!needsFullScopeChain())
-            return InvalidVirtualRegister;
+            return VirtualRegister();
         return activationRegister();
     }
-    bool usesArguments() const { return m_argumentsRegister != (int)InvalidVirtualRegister; }
+
+    bool usesArguments() const { return m_argumentsRegister.isValid(); }
 
     bool needsActivation() const
     {
         return m_needsActivation;
     }
 
-    bool isCaptured(int operand, InlineCallFrame* inlineCallFrame = 0) const
+    bool isCaptured(VirtualRegister operand, InlineCallFrame* inlineCallFrame = 0) const
     {
-        if (operandIsArgument(operand))
-            return operandToArgument(operand) && usesArguments();
+        if (operand.isArgument())
+            return operand.toArgument() && usesArguments();
 
         if (inlineCallFrame)
-            return inlineCallFrame->capturedVars.get(operandToLocal(operand));
+            return inlineCallFrame->capturedVars.get(operand.toLocal());
 
         // The activation object isn't in the captured region, but it's "captured"
         // in the sense that stores to its location can be observed indirectly.
@@ -368,8 +372,8 @@ public:
         if (!symbolTable())
             return false;
 
-        return operand <= symbolTable()->captureStart()
-            && operand > symbolTable()->captureEnd();
+        return operand.offset() <= symbolTable()->captureStart()
+            && operand.offset() > symbolTable()->captureEnd();
     }
 
     CodeType codeType() const { return m_unlinkedCode->codeType(); }
@@ -391,7 +395,7 @@ public:
 
     void clearEvalCache();
 
-    String nameForRegister(int registerNumber);
+    String nameForRegister(VirtualRegister);
 
 #if ENABLE(JIT)
     void setNumberOfStructureStubInfos(size_t size) { m_structureStubInfos.grow(size); }
@@ -1027,9 +1031,9 @@ private:
     VM* m_vm;
 
     RefCountedArray<Instruction> m_instructions;
-    int m_thisRegister;
-    int m_argumentsRegister;
-    int m_activationRegister;
+    VirtualRegister m_thisRegister;
+    VirtualRegister m_argumentsRegister;
+    VirtualRegister m_activationRegister;
 
     bool m_isStrictMode;
     bool m_needsActivation;
index 301f90f..dac59a0 100644 (file)
@@ -35,6 +35,7 @@
 #include "SpecialPointer.h"
 #include "Structure.h"
 #include "StructureChain.h"
+#include "VirtualRegister.h"
 #include <wtf/VectorTraits.h>
 
 namespace JSC {
index 5a7835b..483e5b5 100644 (file)
@@ -46,26 +46,26 @@ class LazyOperandValueProfileKey {
 public:
     LazyOperandValueProfileKey()
         : m_bytecodeOffset(0) // 0 = empty value
-        , m_operand(InvalidVirtualRegister) // not a valid operand index in our current scheme
+        , m_operand(VirtualRegister()) // not a valid operand index in our current scheme
     {
     }
     
     LazyOperandValueProfileKey(WTF::HashTableDeletedValueType)
         : m_bytecodeOffset(1) // 1 = deleted value
-        , m_operand(InvalidVirtualRegister) // not a valid operand index in our current scheme
+        , m_operand(VirtualRegister()) // not a valid operand index in our current scheme
     {
     }
     
-    LazyOperandValueProfileKey(unsigned bytecodeOffset, int operand)
+    LazyOperandValueProfileKey(unsigned bytecodeOffset, VirtualRegister operand)
         : m_bytecodeOffset(bytecodeOffset)
         , m_operand(operand)
     {
-        ASSERT(operand != InvalidVirtualRegister);
+        ASSERT(m_operand.isValid());
     }
     
     bool operator!() const
     {
-        return m_operand == InvalidVirtualRegister;
+        return !m_operand.isValid();
     }
     
     bool operator==(const LazyOperandValueProfileKey& other) const
@@ -76,7 +76,7 @@ public:
     
     unsigned hash() const
     {
-        return WTF::intHash(m_bytecodeOffset) + m_operand;
+        return WTF::intHash(m_bytecodeOffset) + m_operand.offset();
     }
     
     unsigned bytecodeOffset() const
@@ -84,7 +84,8 @@ public:
         ASSERT(!!*this);
         return m_bytecodeOffset;
     }
-    int operand() const
+
+    VirtualRegister operand() const
     {
         ASSERT(!!*this);
         return m_operand;
@@ -92,11 +93,11 @@ public:
     
     bool isHashTableDeletedValue() const
     {
-        return m_operand == InvalidVirtualRegister && m_bytecodeOffset;
+        return !m_operand.isValid() && m_bytecodeOffset;
     }
 private: 
     unsigned m_bytecodeOffset;
-    int m_operand;
+    VirtualRegister m_operand;
 };
 
 struct LazyOperandValueProfileKeyHash {
@@ -129,7 +130,7 @@ namespace JSC {
 struct LazyOperandValueProfile : public MinimalValueProfile {
     LazyOperandValueProfile()
         : MinimalValueProfile()
-        , m_operand(InvalidVirtualRegister)
+        , m_operand(VirtualRegister())
     {
     }
     
@@ -144,7 +145,7 @@ struct LazyOperandValueProfile : public MinimalValueProfile {
         return LazyOperandValueProfileKey(m_bytecodeOffset, m_operand);
     }
     
-    int m_operand;
+    VirtualRegister m_operand;
     
     typedef SegmentedVector<LazyOperandValueProfile, 8> List;
 };
index 1380bf8..1ac5bb5 100644 (file)
@@ -39,7 +39,7 @@ MethodOfGettingAValueProfile MethodOfGettingAValueProfile::fromLazyOperand(
     result.m_kind = LazyOperand;
     result.u.lazyOperand.codeBlock = codeBlock;
     result.u.lazyOperand.bytecodeOffset = key.bytecodeOffset();
-    result.u.lazyOperand.operand = key.operand();
+    result.u.lazyOperand.operand = key.operand().offset();
     return result;
 }
 
@@ -53,7 +53,7 @@ EncodedJSValue* MethodOfGettingAValueProfile::getSpecFailBucket(unsigned index)
         return u.profile->specFailBucket(index);
         
     case LazyOperand: {
-        LazyOperandValueProfileKey key(u.lazyOperand.bytecodeOffset, u.lazyOperand.operand);
+        LazyOperandValueProfileKey key(u.lazyOperand.bytecodeOffset, VirtualRegister(u.lazyOperand.operand));
         
         ConcurrentJITLocker locker(u.lazyOperand.codeBlock->m_lock);
         LazyOperandValueProfile* profile =
index 126c599..77d7602 100644 (file)
 
 #include "CallFrame.h"
 #include "JSObject.h"
+#include "VirtualRegister.h"
+
 #include <wtf/PrintStream.h>
 #include <wtf/Vector.h>
 
 namespace JSC {
 
-inline int localToOperand(int local) { return -local; }
-inline bool operandIsLocal(int operand) { return operand <= 0; }
-inline int operandToLocal(int operand) { return -operand; }
-
-// argument 0 is 'this'.
-inline bool operandIsArgument(int operand) { return operand > 0; }
-inline int operandToArgument(int operand) { return operand - CallFrame::thisArgumentOffset(); }
-inline int argumentToOperand(int argument) { return argument + CallFrame::thisArgumentOffset(); }
-
 template<typename T> struct OperandValueTraits;
 
 template<typename T>
@@ -143,33 +136,43 @@ public:
     T& operand(int operand)
     {
         if (operandIsArgument(operand)) {
-            int argument = operandToArgument(operand);
+            int argument = VirtualRegister(operand).toArgument();
             return m_arguments[argument];
         }
-        
-        return m_locals[operandToLocal(operand)];
+
+        return m_locals[VirtualRegister(operand).toLocal()];
     }
-    
+
+    T& operand(VirtualRegister virtualRegister)
+    {
+        return operand(virtualRegister.offset());
+    }
+
     const T& operand(int operand) const { return const_cast<const T&>(const_cast<Operands*>(this)->operand(operand)); }
     
     bool hasOperand(int operand) const
     {
         if (operandIsArgument(operand))
             return true;
-        return static_cast<size_t>(operandToLocal(operand)) < numberOfLocals();
+        return static_cast<size_t>(VirtualRegister(operand).toLocal()) < numberOfLocals();
     }
     
     void setOperand(int operand, const T& value)
     {
         if (operandIsArgument(operand)) {
-            int argument = operandToArgument(operand);
+            int argument = VirtualRegister(operand).toArgument();
             m_arguments[argument] = value;
             return;
         }
         
-        setLocal(operandToLocal(operand), value);
+        setLocal(VirtualRegister(operand).toLocal(), value);
     }
     
+    void setOperand(VirtualRegister virtualRegister, const T& value)
+    {
+        setOperand(virtualRegister.offset(), value);
+    }
+
     size_t size() const { return numberOfArguments() + numberOfLocals(); }
     const T& at(size_t index) const
     {
@@ -199,18 +202,18 @@ public:
     int operandForIndex(size_t index) const
     {
         if (index < numberOfArguments())
-            return argumentToOperand(index);
-        return localToOperand(index - numberOfArguments());
+            return virtualRegisterForArgument(index).offset();
+        return virtualRegisterForLocal(index - numberOfArguments()).offset();
     }
     
     void setOperandFirstTime(int operand, const T& value)
     {
         if (operandIsArgument(operand)) {
-            setArgumentFirstTime(operandToArgument(operand), value);
+            setArgumentFirstTime(VirtualRegister(operand).toArgument(), value);
             return;
         }
         
-        setLocalFirstTime(operandToLocal(operand), value);
+        setLocalFirstTime(VirtualRegister(operand).toLocal(), value);
     }
     
     void fill(T value)
index 0460572..d13aa65 100644 (file)
@@ -194,8 +194,8 @@ UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType code
     , m_numCalleeRegisters(0)
     , m_numParameters(0)
     , m_vm(vm)
-    , m_argumentsRegister((int)InvalidVirtualRegister)
-    , m_globalObjectRegister((int)InvalidVirtualRegister)
+    , m_argumentsRegister(VirtualRegister())
+    , m_globalObjectRegister(VirtualRegister())
     , m_needsFullScopeChain(info.m_needsActivation)
     , m_usesEval(info.m_usesEval)
     , m_isNumericCompareFunction(false)
index 7b60472..433ef1d 100644 (file)
@@ -254,17 +254,17 @@ public:
     bool hasExpressionInfo() { return m_expressionInfo.size(); }
 
     // Special registers
-    void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
-    void setActivationRegister(int activationRegister) { m_activationRegister = activationRegister; }
+    void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; }
+    void setActivationRegister(VirtualRegister activationRegister) { m_activationRegister = activationRegister; }
 
-    void setArgumentsRegister(int argumentsRegister) { m_argumentsRegister = argumentsRegister; }
-    bool usesArguments() const { return m_argumentsRegister != (int)InvalidVirtualRegister; }
-    int argumentsRegister() const { return m_argumentsRegister; }
+    void setArgumentsRegister(VirtualRegister argumentsRegister) { m_argumentsRegister = argumentsRegister; }
+    bool usesArguments() const { return m_argumentsRegister.isValid(); }
+    VirtualRegister argumentsRegister() const { return m_argumentsRegister; }
 
 
-    bool usesGlobalObject() const { return m_globalObjectRegister != (int)InvalidVirtualRegister; }
-    void setGlobalObjectRegister(int globalObjectRegister) { m_globalObjectRegister = globalObjectRegister; }
-    int globalObjectRegister() const { return m_globalObjectRegister; }
+    bool usesGlobalObject() const { return m_globalObjectRegister.isValid(); }
+    void setGlobalObjectRegister(VirtualRegister globalObjectRegister) { m_globalObjectRegister = globalObjectRegister; }
+    VirtualRegister globalObjectRegister() const { return m_globalObjectRegister; }
 
     // Parameter information
     void setNumParameters(int newValue) { m_numParameters = newValue; }
@@ -399,8 +399,8 @@ public:
 
     CodeType codeType() const { return m_codeType; }
 
-    int thisRegister() const { return m_thisRegister; }
-    int activationRegister() const { return m_activationRegister; }
+    VirtualRegister thisRegister() const { return m_thisRegister; }
+    VirtualRegister activationRegister() const { return m_activationRegister; }
 
 
     void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
@@ -479,10 +479,10 @@ private:
     int m_numParameters;
     VM* m_vm;
 
-    int m_thisRegister;
-    int m_argumentsRegister;
-    int m_activationRegister;
-    int m_globalObjectRegister;
+    VirtualRegister m_thisRegister;
+    VirtualRegister m_argumentsRegister;
+    VirtualRegister m_activationRegister;
+    VirtualRegister m_globalObjectRegister;
 
     bool m_needsFullScopeChain : 1;
     bool m_usesEval : 1;
index 0bad4ac..58e7353 100644 (file)
@@ -211,7 +211,7 @@ public:
             result.m_technique = DisplacedInJSStack;
             break;
         }
-        result.m_source.virtualReg = virtualReg;
+        result.m_source.virtualReg = virtualReg.offset();
         return result;
     }
     
@@ -294,7 +294,7 @@ public:
     VirtualRegister virtualRegister() const
     {
         ASSERT(m_technique == DisplacedInJSStack || m_technique == Int32DisplacedInJSStack || m_technique == DoubleDisplacedInJSStack || m_technique == CellDisplacedInJSStack || m_technique == BooleanDisplacedInJSStack || m_technique == Int52DisplacedInJSStack || m_technique == StrictInt52DisplacedInJSStack);
-        return m_source.virtualReg;
+        return VirtualRegister(m_source.virtualReg);
     }
     
     JSValue constant() const
@@ -351,25 +351,25 @@ public:
             return;
 #endif
         case DisplacedInJSStack:
-            out.printf("*%d", virtualRegister());
+            out.printf("*%d", virtualRegister().offset());
             return;
         case Int32DisplacedInJSStack:
-            out.printf("*int32(%d)", virtualRegister());
+            out.printf("*int32(%d)", virtualRegister().offset());
             return;
         case Int52DisplacedInJSStack:
-            out.printf("*int52(%d)", virtualRegister());
+            out.printf("*int52(%d)", virtualRegister().offset());
             return;
         case StrictInt52DisplacedInJSStack:
-            out.printf("*strictInt52(%d)", virtualRegister());
+            out.printf("*strictInt52(%d)", virtualRegister().offset());
             return;
         case DoubleDisplacedInJSStack:
-            out.printf("*double(%d)", virtualRegister());
+            out.printf("*double(%d)", virtualRegister().offset());
             return;
         case CellDisplacedInJSStack:
-            out.printf("*cell(%d)", virtualRegister());
+            out.printf("*cell(%d)", virtualRegister().offset());
             return;
         case BooleanDisplacedInJSStack:
-            out.printf("*bool(%d)", virtualRegister());
+            out.printf("*bool(%d)", virtualRegister().offset());
             return;
         case ArgumentsThatWereNotCreated:
             out.printf("arguments");
@@ -400,7 +400,7 @@ private:
             MacroAssembler::RegisterID payloadGPR;
         } pair;
 #endif
-        VirtualRegister virtualReg;
+        int virtualReg;
         EncodedJSValue constant;
     } m_source;
 };
index e8fe1d8..6dc6b65 100644 (file)
 #ifndef VirtualRegister_h
 #define VirtualRegister_h
 
+#include "CallFrame.h"
+
 #include <wtf/Platform.h>
 #include <wtf/PrintStream.h>
 
 namespace JSC {
 
-// Type for a virtual register number (spill location).
-// Using an enum to make this type-checked at compile time, to avert programmer errors.
-enum VirtualRegister { InvalidVirtualRegister = 0x3fffffff };
+inline bool operandIsLocal(int operand)
+{
+    return operand <= 0;
+}
+
+inline bool operandIsArgument(int operand)
+{
+    return operand > 0;
+}
+
+
+class VirtualRegister {
+public:
+    friend VirtualRegister virtualRegisterForLocal(int);
+    friend VirtualRegister virtualRegisterForArgument(int, int);
+
+    VirtualRegister()
+        : m_virtualRegister(s_invalidVirtualRegister)
+    { }
+
+    explicit VirtualRegister(int virtualRegister)
+        : m_virtualRegister(virtualRegister)
+    { }
+
+    bool isValid() const { return (m_virtualRegister != s_invalidVirtualRegister); }
+    bool isLocal() const { return operandIsLocal(m_virtualRegister); }
+    bool isArgument() const { return operandIsArgument(m_virtualRegister); }
+    bool isConstant() const { return m_virtualRegister >= s_firstConstantRegisterIndex; }
+    int toLocal() const { ASSERT(isLocal()); return operandToLocal(m_virtualRegister); }
+    int toArgument() const { ASSERT(isArgument()); return operandToArgument(m_virtualRegister); }
+    int toConstantIndex() const { ASSERT(isConstant()); return m_virtualRegister - s_firstConstantRegisterIndex; }
+    int offset() const { return m_virtualRegister; }
+
+    bool operator==(const VirtualRegister other) const { return m_virtualRegister == other.m_virtualRegister; }
+    bool operator!=(const VirtualRegister other) const { return m_virtualRegister != other.m_virtualRegister; }
+
+private:
+    static const int s_invalidVirtualRegister = 0x3fffffff;
+    static const int s_firstConstantRegisterIndex = 0x40000000;
+
+    static int localToOperand(int local) { return -local; }
+    static int operandToLocal(int operand) { return -operand; }
+    static int operandToArgument(int operand) { return operand - CallFrame::thisArgumentOffset(); }
+    static int argumentToOperand(int argument) { return argument + CallFrame::thisArgumentOffset(); }
+
+    int m_virtualRegister;
+};
+
 COMPILE_ASSERT(sizeof(VirtualRegister) == sizeof(int), VirtualRegister_is_32bit);
 
+inline VirtualRegister virtualRegisterForLocal(int local)
+{
+    return VirtualRegister(VirtualRegister::localToOperand(local));
+}
+
+inline VirtualRegister virtualRegisterForArgument(int argument, int offset = 0)
+{
+    return VirtualRegister(VirtualRegister::argumentToOperand(argument) + offset);
+}
+
 } // namespace JSC
 
 namespace WTF {
 
 inline void printInternal(PrintStream& out, JSC::VirtualRegister value)
 {
-    out.print(static_cast<int>(value));
+    out.print(value.offset());
 }
 
 } // namespace WTF
index db96a6c..c9632eb 100644 (file)
@@ -60,7 +60,7 @@ ParserError BytecodeGenerator::generate()
 {
     SamplingRegion samplingRegion("Bytecode Generation");
     
-    m_codeBlock->setThisRegister(m_thisRegister.index());
+    m_codeBlock->setThisRegister(m_thisRegister.virtualRegister());
 
     m_scopeNode->emitBytecode(*this);
 
@@ -117,7 +117,7 @@ ParserError BytecodeGenerator::generate()
 bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
 {
     ConcurrentJITLocker locker(symbolTable().m_lock);
-    int index = localToOperand(m_calleeRegisters.size());
+    int index = virtualRegisterForLocal(m_calleeRegisters.size()).offset();
     SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
     SymbolTable::Map::AddResult result = symbolTable().add(locker, ident.impl(), newEntry);
 
@@ -230,10 +230,10 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionBodyNode* functionBody, Unl
     if (m_codeBlock->needsFullScopeChain()) {
         m_activationRegister = addVar();
         emitInitLazyRegister(m_activationRegister);
-        m_codeBlock->setActivationRegister(m_activationRegister->index());
+        m_codeBlock->setActivationRegister(m_activationRegister->virtualRegister());
     }
 
-    m_symbolTable->setCaptureStart(localToOperand(m_codeBlock->m_numVars));
+    m_symbolTable->setCaptureStart(virtualRegisterForLocal(m_codeBlock->m_numVars).offset());
 
     if (functionBody->usesArguments() || codeBlock->usesEval()) { // May reify arguments object.
         RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code.
@@ -242,8 +242,8 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionBodyNode* functionBody, Unl
         // We can save a little space by hard-coding the knowledge that the two
         // 'arguments' values are stored in consecutive registers, and storing
         // only the index of the assignable one.
-        codeBlock->setArgumentsRegister(argumentsRegister->index());
-        ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->index() == JSC::unmodifiedArgumentsRegister(codeBlock->argumentsRegister()));
+        codeBlock->setArgumentsRegister(argumentsRegister->virtualRegister());
+        ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->virtualRegister() == JSC::unmodifiedArgumentsRegister(codeBlock->argumentsRegister()));
 
         emitInitLazyRegister(argumentsRegister);
         emitInitLazyRegister(unmodifiedArgumentsRegister);
@@ -324,7 +324,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionBodyNode* functionBody, Unl
         instructions().append(m_activationRegister->index());
     }
 
-    m_symbolTable->setCaptureEnd(localToOperand(codeBlock->m_numVars));
+    m_symbolTable->setCaptureEnd(virtualRegisterForLocal(codeBlock->m_numVars).offset());
 
     m_firstLazyFunction = codeBlock->m_numVars;
     for (size_t i = 0; i < functionStack.size(); ++i) {
@@ -339,7 +339,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionBodyNode* functionBody, Unl
                 emitNewFunction(reg.get(), function);
             else {
                 emitInitLazyRegister(reg.get());
-                m_lazyFunctions.set(localToOperand(reg->index()), function);
+                m_lazyFunctions.set(reg->virtualRegister().toLocal(), function);
             }
         }
     }
@@ -351,7 +351,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionBodyNode* functionBody, Unl
     }
 
     if (shouldCaptureAllTheThings)
-        m_symbolTable->setCaptureEnd(localToOperand(codeBlock->m_numVars));
+        m_symbolTable->setCaptureEnd(virtualRegisterForLocal(codeBlock->m_numVars).offset());
 
     m_parameters.grow(parameters.size() + 1); // reserve space for "this"
 
@@ -533,8 +533,11 @@ RegisterID* BytecodeGenerator::uncheckedRegisterForArguments()
 
 RegisterID* BytecodeGenerator::createLazyRegisterIfNecessary(RegisterID* reg)
 {
-    int localVariableNumber = operandToLocal(reg->index());
-    
+    if (!reg->virtualRegister().isLocal())
+        return reg;
+
+    int localVariableNumber = reg->virtualRegister().toLocal();
+
     if (m_lastLazyFunction <= localVariableNumber || localVariableNumber < m_firstLazyFunction)
         return reg;
     emitLazyNewFunction(reg, m_lazyFunctions.get(localVariableNumber));
@@ -543,7 +546,7 @@ RegisterID* BytecodeGenerator::createLazyRegisterIfNecessary(RegisterID* reg)
 
 RegisterID* BytecodeGenerator::newRegister()
 {
-    m_calleeRegisters.append(localToOperand(m_calleeRegisters.size()));
+    m_calleeRegisters.append(virtualRegisterForLocal(m_calleeRegisters.size()));
     m_codeBlock->m_numCalleeRegisters = max<int>(m_codeBlock->m_numCalleeRegisters, m_calleeRegisters.size());
     return &m_calleeRegisters.last();
 }
@@ -1146,7 +1149,7 @@ RegisterID* BytecodeGenerator::emitLoadGlobalObject(RegisterID* dst)
         ++m_nextConstantOffset;
         m_codeBlock->addConstant(JSValue());
         m_globalObjectRegister = &m_constantPoolRegisters[index];
-        m_codeBlock->setGlobalObjectRegister(index);
+        m_codeBlock->setGlobalObjectRegister(VirtualRegister(index));
     }
     if (dst)
         emitMove(dst, m_globalObjectRegister);
@@ -1290,7 +1293,7 @@ RegisterID* BytecodeGenerator::emitGetArgumentsLength(RegisterID* dst, RegisterI
 {
     emitOpcode(op_get_arguments_length);
     instructions().append(dst->index());
-    ASSERT(base->index() == m_codeBlock->argumentsRegister());
+    ASSERT(base->virtualRegister() == m_codeBlock->argumentsRegister());
     instructions().append(base->index());
     instructions().append(addConstant(propertyNames().length));
     return dst;
@@ -1365,7 +1368,7 @@ RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID*
     UnlinkedArrayProfile arrayProfile = newArrayProfile();
     UnlinkedValueProfile profile = emitProfiledOpcode(op_get_argument_by_val);
     instructions().append(kill(dst));
-    ASSERT(base->index() == m_codeBlock->argumentsRegister());
+    ASSERT(base->virtualRegister() == m_codeBlock->argumentsRegister());
     instructions().append(base->index());
     instructions().append(property->index());
     instructions().append(arrayProfile);
@@ -1585,7 +1588,7 @@ void BytecodeGenerator::createArgumentsIfNecessary()
         return;
 
     emitOpcode(op_create_arguments);
-    instructions().append(m_codeBlock->argumentsRegister());
+    instructions().append(m_codeBlock->argumentsRegister().offset());
 }
 
 void BytecodeGenerator::createActivationIfNecessary()
@@ -1770,7 +1773,7 @@ RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
 
     if (m_codeBlock->usesArguments() && m_codeBlock->numParameters() != 1 && !isStrictMode()) {
         emitOpcode(op_tear_off_arguments);
-        instructions().append(m_codeBlock->argumentsRegister());
+        instructions().append(m_codeBlock->argumentsRegister().offset());
         instructions().append(m_activationRegister ? m_activationRegister->index() : emitLoad(0, JSValue())->index());
     }
 
index 1d138c0..fcc17df 100644 (file)
@@ -502,13 +502,13 @@ namespace JSC {
         RegisterID& registerFor(int index)
         {
             if (operandIsLocal(index))
-                return m_calleeRegisters[operandToLocal(index)];
+                return m_calleeRegisters[VirtualRegister(index).toLocal()];
 
             if (index == JSStack::Callee)
                 return m_calleeRegister;
 
             ASSERT(m_parameters.size());
-            return m_parameters[operandToArgument(index)];
+            return m_parameters[VirtualRegister(index).toArgument()];
         }
 
         unsigned addConstant(const Identifier&);
index 78d49d2..83216f6 100644 (file)
@@ -29,6 +29,8 @@
 #ifndef RegisterID_h
 #define RegisterID_h
 
+#include "VirtualRegister.h"
+
 #include <wtf/Assertions.h>
 #include <wtf/VectorTraits.h>
 
@@ -46,9 +48,19 @@ namespace JSC {
         {
         }
 
+        RegisterID(VirtualRegister virtualRegister)
+            : m_refCount(0)
+            , m_virtualRegister(virtualRegister)
+            , m_isTemporary(false)
+#ifndef NDEBUG
+            , m_didSetIndex(true)
+#endif
+        {
+        }
+        
         explicit RegisterID(int index)
             : m_refCount(0)
-            , m_index(index)
+            , m_virtualRegister(VirtualRegister(index))
             , m_isTemporary(false)
 #ifndef NDEBUG
             , m_didSetIndex(true)
@@ -62,7 +74,7 @@ namespace JSC {
 #ifndef NDEBUG
             m_didSetIndex = true;
 #endif
-            m_index = index;
+            m_virtualRegister = VirtualRegister(index);
         }
 
         void setTemporary()
@@ -73,7 +85,13 @@ namespace JSC {
         int index() const
         {
             ASSERT(m_didSetIndex);
-            return m_index;
+            return m_virtualRegister.offset();
+        }
+
+        VirtualRegister virtualRegister() const
+        {
+            ASSERT(m_virtualRegister.isValid());
+            return m_virtualRegister;
         }
 
         bool isTemporary()
@@ -100,7 +118,7 @@ namespace JSC {
     private:
 
         int m_refCount;
-        int m_index;
+        VirtualRegister m_virtualRegister;
         bool m_isTemporary;
 #ifndef NDEBUG
         bool m_didSetIndex;
index 97d64a8..098a529 100644 (file)
@@ -109,7 +109,7 @@ JSObject* DebuggerCallFrame::thisObject() const
     if (!codeBlock)
         return 0;
 
-    JSValue thisValue = m_callFrame->uncheckedR(codeBlock->thisRegister()).jsValue();
+    JSValue thisValue = m_callFrame->uncheckedR(codeBlock->thisRegister().offset()).jsValue();
     if (!thisValue.isObject())
         return 0;
 
index 6914fdf..379de10 100644 (file)
@@ -113,7 +113,7 @@ public:
         
         Payload(VirtualRegister operand)
             : m_isTop(false)
-            , m_value(static_cast<int>(operand))
+            , m_value(operand.offset())
         {
         }
         
index 3757463..1d7efcd 100644 (file)
@@ -142,7 +142,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case GetArgument: {
         ASSERT(m_graph.m_form == SSA);
         VariableAccessData* variable = node->variableAccessData();
-        AbstractValue& value = m_state.variables().operand(variable->local());
+        AbstractValue& value = m_state.variables().operand(variable->local().offset());
         ASSERT(value.isHeapTop());
         FiltrationResult result =
             value.filter(typeFilterFor(useKindFor(variable->flushFormat())));
@@ -152,8 +152,8 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
         
     case ExtractOSREntryLocal: {
-        if (!operandIsArgument(node->unlinkedLocal())
-            && m_graph.m_lazyVars.get(operandToLocal(node->unlinkedLocal()))) {
+        if (!(node->unlinkedLocal().isArgument())
+            && m_graph.m_lazyVars.get(node->unlinkedLocal().toLocal())) {
             // This is kind of pessimistic - we could know in some cases that the
             // DFG code at the point of the OSR had already initialized the lazy
             // variable. But maybe this is fine, since we're inserting OSR
@@ -171,7 +171,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             m_state.setIsValid(false);
             break;
         }
-        AbstractValue value = m_state.variables().operand(variableAccessData->local());
+        AbstractValue value = m_state.variables().operand(variableAccessData->local().offset());
         if (!variableAccessData->isCaptured()) {
             if (value.isClear())
                 node->setCanExit(true);
@@ -183,7 +183,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
         
     case GetLocalUnlinked: {
-        AbstractValue value = m_state.variables().operand(node->unlinkedLocal());
+        AbstractValue value = m_state.variables().operand(node->unlinkedLocal().offset());
         if (value.value())
             m_state.setFoundConstants(true);
         forNode(node) = value;
@@ -191,7 +191,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
         
     case SetLocal: {
-        m_state.variables().operand(node->local()) = forNode(node->child1());
+        m_state.variables().operand(node->local().offset()) = forNode(node->child1());
         break;
     }
         
@@ -1133,7 +1133,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case CheckArgumentsNotCreated:
         if (isEmptySpeculation(
                 m_state.variables().operand(
-                    m_graph.argumentsRegisterFor(node->codeOrigin)).m_type))
+                    m_graph.argumentsRegisterFor(node->codeOrigin).offset()).m_type))
             m_state.setFoundConstants(true);
         else
             node->setCanExit(true);
@@ -1607,13 +1607,13 @@ void AbstractInterpreter<AbstractStateType>::clobberCapturedVars(const CodeOrigi
         }
     } else {
         for (size_t i = m_codeBlock->m_numVars; i--;) {
-            if (m_codeBlock->isCaptured(localToOperand(i)))
+            if (m_codeBlock->isCaptured(virtualRegisterForLocal(i)))
                 m_state.variables().local(i).makeHeapTop();
         }
     }
 
     for (size_t i = m_state.variables().numberOfArguments(); i--;) {
-        if (m_codeBlock->isCaptured(argumentToOperand(i)))
+        if (m_codeBlock->isCaptured(virtualRegisterForArgument(i)))
             m_state.variables().argument(i).makeHeapTop();
     }
 }
index eb6dbc4..b4e4ade 100644 (file)
@@ -118,15 +118,15 @@ public:
     {
         for (unsigned i = 0; i < m_variables.size(); ++i) {
             VariableAccessData* variable = m_variables[i]->find();
-            int operand = variable->operand();
+            VirtualRegister operand = variable->local();
 
             if (i)
                 out.print(" ");
 
-            if (operandIsArgument(operand))
-                out.print("arg", operandToArgument(operand), "(", VariableAccessDataDump(*graph, variable), ")");
+            if (operand.isArgument())
+                out.print("arg", operand.toArgument(), "(", VariableAccessDataDump(*graph, variable), ")");
             else
-                out.print("r", operand, "(", VariableAccessDataDump(*graph, variable), ")");
+                out.print("r", operand.toLocal(), "(", VariableAccessDataDump(*graph, variable), ")");
         }
         out.print("\n");
     }
index 66544e7..c22e69e 100644 (file)
@@ -188,7 +188,7 @@ public:
                 case SetLocal: {
                     Node* source = node->child1().node();
                     VariableAccessData* variableAccessData = node->variableAccessData();
-                    int argumentsRegister =
+                    VirtualRegister argumentsRegister =
                         m_graph.uncheckedArgumentsRegisterFor(node->codeOrigin);
                     if (source->op() != CreateArguments && source->op() != PhantomArguments) {
                         // Make sure that the source of the SetLocal knows that if it's
@@ -216,7 +216,7 @@ public:
                         if (!m_isLive.contains(variableAccessData))
                             break;
                         
-                        if (argumentsRegister != InvalidVirtualRegister
+                        if (argumentsRegister.isValid()
                             && (variableAccessData->local() == argumentsRegister
                                 || variableAccessData->local() == unmodifiedArgumentsRegister(argumentsRegister))) {
                             m_createsArguments.add(node->codeOrigin.inlineCallFrame);
@@ -234,7 +234,7 @@ public:
                         data.mergeCallContext(node->codeOrigin.inlineCallFrame);
                         break;
                     }
-                    if (argumentsRegister != InvalidVirtualRegister
+                    if (argumentsRegister.isValid()
                         && (variableAccessData->local() == argumentsRegister
                             || variableAccessData->local() == unmodifiedArgumentsRegister(argumentsRegister))) {
                         if (node->codeOrigin.inlineCallFrame == source->codeOrigin.inlineCallFrame)
@@ -619,7 +619,7 @@ public:
                     AdjacencyList children = node->children;
                     
                     node->convertToGetLocalUnlinked(
-                        static_cast<VirtualRegister>(
+                        VirtualRegister(
                             node->codeOrigin.inlineCallFrame->stackOffset +
                             m_graph.baselineCodeBlockFor(node->codeOrigin)->argumentIndexAfterCapture(index)));
 
@@ -711,8 +711,8 @@ private:
         }
             
         case GetLocal: {
-            int argumentsRegister = m_graph.uncheckedArgumentsRegisterFor(node->codeOrigin);
-            if (argumentsRegister != InvalidVirtualRegister
+            VirtualRegister argumentsRegister = m_graph.uncheckedArgumentsRegisterFor(node->codeOrigin);
+            if (argumentsRegister.isValid()
                 && (node->local() == argumentsRegister
                     || node->local() == unmodifiedArgumentsRegister(argumentsRegister))) {
                 m_createsArguments.add(node->codeOrigin.inlineCallFrame);
@@ -783,8 +783,8 @@ private:
         switch (source->op()) {
         case GetLocal: {
             VariableAccessData* variableAccessData = source->variableAccessData();
-            int argumentsRegister = m_graph.uncheckedArgumentsRegisterFor(source->codeOrigin);
-            if (argumentsRegister == InvalidVirtualRegister)
+            VirtualRegister argumentsRegister = m_graph.uncheckedArgumentsRegisterFor(source->codeOrigin);
+            if (!argumentsRegister.isValid())
                 break;
             if (argumentsRegister == variableAccessData->local())
                 return true;
index cd8c053..ca47e1d 100644 (file)
@@ -191,37 +191,37 @@ private:
     void linkBlock(BasicBlock*, Vector<BasicBlock*>& possibleTargets);
     void linkBlocks(Vector<UnlinkedBlock>& unlinkedBlocks, Vector<BasicBlock*>& possibleTargets);
     
-    VariableAccessData* newVariableAccessData(int operand, bool isCaptured)
+    VariableAccessData* newVariableAccessData(VirtualRegister operand, bool isCaptured)
     {
-        ASSERT(operand < FirstConstantRegisterIndex);
+        ASSERT(!operand.isConstant());
         
-        m_graph.m_variableAccessData.append(VariableAccessData(static_cast<VirtualRegister>(operand), isCaptured));
+        m_graph.m_variableAccessData.append(VariableAccessData(operand, isCaptured));
         return &m_graph.m_variableAccessData.last();
     }
     
     // Get/Set the operands/result of a bytecode instruction.
-    Node* getDirect(int operand)
+    Node* getDirect(VirtualRegister operand)
     {
         // Is this a constant?
-        if (operand >= FirstConstantRegisterIndex) {
-            unsigned constant = operand - FirstConstantRegisterIndex;
+        if (operand.isConstant()) {
+            unsigned constant = operand.toConstantIndex();
             ASSERT(constant < m_constants.size());
             return getJSConstant(constant);
         }
 
-        ASSERT(operand != JSStack::Callee);
+        ASSERT(operand.offset() != JSStack::Callee);
         
         // Is this an argument?
-        if (operandIsArgument(operand))
+        if (operand.isArgument())
             return getArgument(operand);
 
         // Must be a local.
         return getLocal(operand);
     }
 
-    Node* get(int operand)
+    Node* get(VirtualRegister operand)
     {
-        if (operand == JSStack::Callee) {
+        if (operand.offset() == JSStack::Callee) {
             if (inlineCallFrame() && inlineCallFrame()->callee)
                 return cellConstant(inlineCallFrame()->callee.get());
             
@@ -230,12 +230,12 @@ private:
         
         return getDirect(m_inlineStackTop->remapOperand(operand));
     }
-
+    
     enum SetMode { NormalSet, SetOnEntry };
-    void setDirect(int operand, Node* value, SetMode setMode = NormalSet)
+    void setDirect(VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
     {
         // Is this an argument?
-        if (operandIsArgument(operand)) {
+        if (operand.isArgument()) {
             setArgument(operand, value, setMode);
             return;
         }
@@ -244,7 +244,7 @@ private:
         setLocal(operand, value, setMode);
     }
 
-    void set(int operand, Node* value, SetMode setMode = NormalSet)
+    void set(VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
     {
         setDirect(m_inlineStackTop->remapOperand(operand), value, setMode);
     }
@@ -264,9 +264,9 @@ private:
     }
 
     // Used in implementing get/set, above, where the operand is a local variable.
-    Node* getLocal(int operand)
+    Node* getLocal(VirtualRegister operand)
     {
-        unsigned local = operandToLocal(operand);
+        unsigned local = operand.toLocal();
         Node* node = m_currentBlock->variablesAtTail.local(local);
         bool isCaptured = m_codeBlock->isCaptured(operand, inlineCallFrame());
         
@@ -302,9 +302,9 @@ private:
         return node;
     }
 
-    void setLocal(int operand, Node* value, SetMode setMode = NormalSet)
+    void setLocal(VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
     {
-        unsigned local = operandToLocal(operand);
+        unsigned local = operand.toLocal();
         bool isCaptured = m_codeBlock->isCaptured(operand, inlineCallFrame());
         
         if (setMode == NormalSet) {
@@ -323,9 +323,9 @@ private:
     }
 
     // Used in implementing get/set, above, where the operand is an argument.
-    Node* getArgument(unsigned operand)
+    Node* getArgument(VirtualRegister operand)
     {
-        unsigned argument = operandToArgument(operand);
+        unsigned argument = operand.toArgument();
         ASSERT(argument < m_numArguments);
         
         Node* node = m_currentBlock->variablesAtTail.argument(argument);
@@ -352,9 +352,9 @@ private:
         m_currentBlock->variablesAtTail.argument(argument) = node;
         return node;
     }
-    void setArgument(int operand, Node* value, SetMode setMode = NormalSet)
+    void setArgument(VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
     {
-        unsigned argument = operandToArgument(operand);
+        unsigned argument = operand.toArgument();
         ASSERT(argument < m_numArguments);
         
         bool isCaptured = m_codeBlock->isCaptured(operand);
@@ -385,28 +385,28 @@ private:
         return stack->m_argumentPositions[argument];
     }
     
-    ArgumentPosition* findArgumentPositionForLocal(int operand)
+    ArgumentPosition* findArgumentPositionForLocal(VirtualRegister operand)
     {
         for (InlineStackEntry* stack = m_inlineStackTop; ; stack = stack->m_caller) {
             InlineCallFrame* inlineCallFrame = stack->m_inlineCallFrame;
             if (!inlineCallFrame)
                 break;
-            if (operand <= static_cast<int>(inlineCallFrame->stackOffset + JSStack::CallFrameHeaderSize))
+            if (operand.offset() <= static_cast<int>(inlineCallFrame->stackOffset + JSStack::CallFrameHeaderSize))
                 continue;
-            if (operand == inlineCallFrame->stackOffset + CallFrame::thisArgumentOffset())
+            if (operand.offset() == inlineCallFrame->stackOffset + CallFrame::thisArgumentOffset())
                 continue;
-            if (operand > static_cast<int>(inlineCallFrame->stackOffset + JSStack::CallFrameHeaderSize + inlineCallFrame->arguments.size()))
+            if (operand.offset() > static_cast<int>(inlineCallFrame->stackOffset + JSStack::CallFrameHeaderSize + inlineCallFrame->arguments.size()))
                 continue;
-            int argument = operandToArgument(operand - inlineCallFrame->stackOffset);
+            int argument = VirtualRegister(operand.offset() - inlineCallFrame->stackOffset).toArgument();
             return stack->m_argumentPositions[argument];
         }
         return 0;
     }
     
-    ArgumentPosition* findArgumentPosition(int operand)
+    ArgumentPosition* findArgumentPosition(VirtualRegister operand)
     {
-        if (operandIsArgument(operand))
-            return findArgumentPositionForArgument(operandToArgument(operand));
+        if (operand.isArgument())
+            return findArgumentPositionForArgument(operand.toArgument());
         return findArgumentPositionForLocal(operand);
     }
 
@@ -422,24 +422,24 @@ private:
             value);
     }
     
-    void flush(int operand)
+    void flush(VirtualRegister operand)
     {
         flushDirect(m_inlineStackTop->remapOperand(operand));
     }
     
-    void flushDirect(int operand)
+    void flushDirect(VirtualRegister operand)
     {
         flushDirect(operand, findArgumentPosition(operand));
     }
     
-    void flushDirect(int operand, ArgumentPosition* argumentPosition)
+    void flushDirect(VirtualRegister operand, ArgumentPosition* argumentPosition)
     {
         bool isCaptured = m_codeBlock->isCaptured(operand, inlineCallFrame());
         
-        ASSERT(operand < FirstConstantRegisterIndex);
+        ASSERT(!operand.isConstant());
         
-        if (!operandIsArgument(operand))
-            m_preservedVars.set(operandToLocal(operand));
+        if (operand.isLocal())
+            m_preservedVars.set(operand.toLocal());
         
         Node* node = m_currentBlock->variablesAtTail.operand(operand);
         
@@ -465,11 +465,11 @@ private:
         else
             numArguments = inlineStackEntry->m_codeBlock->numParameters();
         for (unsigned argument = numArguments; argument-- > 1;)
-            flushDirect(inlineStackEntry->remapOperand(argumentToOperand(argument)));
+            flushDirect(inlineStackEntry->remapOperand(virtualRegisterForArgument(argument)));
         for (int local = 0; local < inlineStackEntry->m_codeBlock->m_numVars; ++local) {
-            if (!inlineStackEntry->m_codeBlock->isCaptured(localToOperand(local)))
+            if (!inlineStackEntry->m_codeBlock->isCaptured(virtualRegisterForLocal(local)))
                 continue;
-            flushDirect(inlineStackEntry->remapOperand(localToOperand(local)));
+            flushDirect(inlineStackEntry->remapOperand(virtualRegisterForLocal(local)));
         }
     }
 
@@ -487,7 +487,7 @@ private:
     // Get an operand, and perform a ToInt32/ToNumber conversion on it.
     Node* getToInt32(int operand)
     {
-        return toInt32(get(operand));
+        return toInt32(get(VirtualRegister(operand)));
     }
 
     // Perform an ES5 ToInt32 operation - returns a node of type NodeResultInt32.
@@ -549,6 +549,7 @@ private:
     {
         return get(m_inlineStackTop->m_codeBlock->thisRegister());
     }
+
     void setThis(Node* value)
     {
         set(m_inlineStackTop->m_codeBlock->thisRegister(), value);
@@ -770,7 +771,7 @@ private:
     {
         SpeculatedType prediction = getPrediction();
         
-        addVarArgChild(get(currentInstruction[2].u.operand));
+        addVarArgChild(get(VirtualRegister(currentInstruction[2].u.operand)));
         int argCount = currentInstruction[3].u.operand;
         if (JSStack::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
             m_parameterSlots = JSStack::CallFrameHeaderSize + argCount;
@@ -778,10 +779,10 @@ private:
         int registerOffset = -currentInstruction[4].u.operand;
         int dummyThisArgument = op == Call ? 0 : 1;
         for (int i = 0 + dummyThisArgument; i < argCount; ++i)
-            addVarArgChild(get(registerOffset + argumentToOperand(i)));
+            addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
 
         Node* call = addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(prediction));
-        set(currentInstruction[1].u.operand, call);
+        set(VirtualRegister(currentInstruction[1].u.operand), call);
         return call;
     }
     
@@ -1095,20 +1096,20 @@ private:
             m_byteCodeParser->m_inlineStackTop = m_caller;
         }
         
-        int remapOperand(int operand) const
+        VirtualRegister remapOperand(VirtualRegister operand) const
         {
             if (!m_inlineCallFrame)
                 return operand;
             
-            if (operand >= FirstConstantRegisterIndex) {
-                int result = m_constantRemap[operand - FirstConstantRegisterIndex];
-                ASSERT(result >= FirstConstantRegisterIndex);
+            if (operand.isConstant()) {
+                VirtualRegister result = VirtualRegister(m_constantRemap[operand.toConstantIndex()]);
+                ASSERT(result.isConstant());
                 return result;
             }
 
-            ASSERT(operand != JSStack::Callee);
+            ASSERT(operand.offset() != JSStack::Callee);
 
-            return operand + m_inlineCallFrame->stackOffset;
+            return VirtualRegister(operand.offset() + m_inlineCallFrame->stackOffset);
         }
     };
     
@@ -1141,7 +1142,7 @@ void ByteCodeParser::handleCall(Instruction* currentInstruction, NodeType op, Co
 {
     ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
     
-    Node* callTarget = get(currentInstruction[2].u.operand);
+    Node* callTarget = get(VirtualRegister(currentInstruction[2].u.operand));
     
     CallLinkStatus callLinkStatus;
 
@@ -1213,7 +1214,7 @@ void ByteCodeParser::emitFunctionChecks(const CallLinkStatus& callLinkStatus, No
 {
     Node* thisArgument;
     if (kind == CodeForCall)
-        thisArgument = get(registerOffset + argumentToOperand(0));
+        thisArgument = get(virtualRegisterForArgument(0, registerOffset));
     else
         thisArgument = 0;
 
@@ -1238,7 +1239,7 @@ void ByteCodeParser::emitFunctionChecks(const CallLinkStatus& callLinkStatus, No
 void ByteCodeParser::emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind kind)
 {
     for (int i = kind == CodeForCall ? 0 : 1; i < argumentCountIncludingThis; ++i)
-        addToGraph(Phantom, get(registerOffset + argumentToOperand(i)));
+        addToGraph(Phantom, get(virtualRegisterForArgument(i, registerOffset)));
 }
 
 bool ByteCodeParser::handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus& callLinkStatus, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind kind)
@@ -1292,14 +1293,14 @@ bool ByteCodeParser::handleInlining(Node* callTargetNode, int resultOperand, con
     
     // FIXME: Don't flush constants!
     
-    int inlineCallFrameStart = m_inlineStackTop->remapOperand(registerOffset) + JSStack::CallFrameHeaderSize;
+    int inlineCallFrameStart = m_inlineStackTop->remapOperand(VirtualRegister(registerOffset)).offset() + JSStack::CallFrameHeaderSize;
     
     // Make sure that the area used by the call frame is reserved.
-    for (int arg = operandToLocal(inlineCallFrameStart) + JSStack::CallFrameHeaderSize + codeBlock->m_numVars; arg-- > operandToLocal(inlineCallFrameStart);)
+    for (int arg = VirtualRegister(inlineCallFrameStart).toLocal() + JSStack::CallFrameHeaderSize + codeBlock->m_numVars; arg-- > VirtualRegister(inlineCallFrameStart).toLocal();)
         m_preservedVars.set(arg);
     
     // Make sure that we have enough locals.
-    unsigned newNumLocals = operandToLocal(inlineCallFrameStart) + JSStack::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
+    unsigned newNumLocals = VirtualRegister(inlineCallFrameStart).toLocal() + JSStack::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
     if (newNumLocals > m_numLocals) {
         m_numLocals = newNumLocals;
         for (size_t i = 0; i < m_graph.numBlocks(); ++i)
@@ -1310,7 +1311,7 @@ bool ByteCodeParser::handleInlining(Node* callTargetNode, int resultOperand, con
 
     InlineStackEntry inlineStackEntry(
         this, codeBlock, codeBlock, m_graph.lastBlock(), callLinkStatus.function(),
-        (VirtualRegister)m_inlineStackTop->remapOperand(resultOperand),
+        m_inlineStackTop->remapOperand(VirtualRegister(resultOperand)),
         (VirtualRegister)inlineCallFrameStart, argumentCountIncludingThis, kind);
     
     // This is where the actual inlining really happens.
@@ -1427,19 +1428,19 @@ bool ByteCodeParser::handleInlining(Node* callTargetNode, int resultOperand, con
 bool ByteCodeParser::handleMinMax(int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis)
 {
     if (argumentCountIncludingThis == 1) { // Math.min()
-        set(resultOperand, constantNaN());
+        set(VirtualRegister(resultOperand), constantNaN());
         return true;
     }
      
     if (argumentCountIncludingThis == 2) { // Math.min(x)
-        Node* result = get(registerOffset + argumentToOperand(1));
+        Node* result = get(VirtualRegister(virtualRegisterForArgument(1, registerOffset)));
         addToGraph(Phantom, Edge(result, NumberUse));
-        set(resultOperand, result);
+        set(VirtualRegister(resultOperand), result);
         return true;
     }
     
     if (argumentCountIncludingThis == 3) { // Math.min(x, y)
-        set(resultOperand, addToGraph(op, get(registerOffset + argumentToOperand(1)), get(registerOffset + argumentToOperand(2))));
+        set(VirtualRegister(resultOperand), addToGraph(op, get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset))));
         return true;
     }
     
@@ -1454,17 +1455,17 @@ bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int
     switch (intrinsic) {
     case AbsIntrinsic: {
         if (argumentCountIncludingThis == 1) { // Math.abs()
-            set(resultOperand, constantNaN());
+            set(VirtualRegister(resultOperand), constantNaN());
             return true;
         }
 
         if (!MacroAssembler::supportsFloatingPointAbs())
             return false;
 
-        Node* node = addToGraph(ArithAbs, get(registerOffset + argumentToOperand(1)));
+        Node* node = addToGraph(ArithAbs, get(virtualRegisterForArgument(1, registerOffset)));
         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
             node->mergeFlags(NodeMayOverflow);
-        set(resultOperand, node);
+        set(VirtualRegister(resultOperand), node);
         return true;
     }
 
@@ -1476,14 +1477,14 @@ bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int
         
     case SqrtIntrinsic: {
         if (argumentCountIncludingThis == 1) { // Math.sqrt()
-            set(resultOperand, constantNaN());
+            set(VirtualRegister(resultOperand), constantNaN());
             return true;
         }
         
         if (!MacroAssembler::supportsFloatingPointSqrt())
             return false;
 
-        set(resultOperand, addToGraph(ArithSqrt, get(registerOffset + argumentToOperand(1))));
+        set(VirtualRegister(resultOperand), addToGraph(ArithSqrt, get(virtualRegisterForArgument(1, registerOffset))));
         return true;
     }
         
@@ -1500,8 +1501,8 @@ bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int
         case Array::Double:
         case Array::Contiguous:
         case Array::ArrayStorage: {
-            Node* arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1)));
-            set(resultOperand, arrayPush);
+            Node* arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
+            set(VirtualRegister(resultOperand), arrayPush);
             
             return true;
         }
@@ -1523,8 +1524,8 @@ bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int
         case Array::Double:
         case Array::Contiguous:
         case Array::ArrayStorage: {
-            Node* arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(registerOffset + argumentToOperand(0)));
-            set(resultOperand, arrayPop);
+            Node* arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)));
+            set(VirtualRegister(resultOperand), arrayPop);
             return true;
         }
             
@@ -1537,11 +1538,11 @@ bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int
         if (argumentCountIncludingThis != 2)
             return false;
 
-        int thisOperand = registerOffset + argumentToOperand(0);
-        int indexOperand = registerOffset + argumentToOperand(1);
-        Node* charCode = addToGraph(StringCharCodeAt, OpInfo(ArrayMode(Array::String).asWord()), get(thisOperand), getToInt32(indexOperand));
+        int thisOperand = virtualRegisterForArgument(0, registerOffset).offset();
+        int indexOperand = virtualRegisterForArgument(1, registerOffset).offset();
+        Node* charCode = addToGraph(StringCharCodeAt, OpInfo(ArrayMode(Array::String).asWord()), get(VirtualRegister(thisOperand)), getToInt32(indexOperand));
 
-        set(resultOperand, charCode);
+        set(VirtualRegister(resultOperand), charCode);
         return true;
     }
 
@@ -1549,21 +1550,21 @@ bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int
         if (argumentCountIncludingThis != 2)
             return false;
 
-        int thisOperand = registerOffset + argumentToOperand(0);
-        int indexOperand = registerOffset + argumentToOperand(1);
-        Node* charCode = addToGraph(StringCharAt, OpInfo(ArrayMode(Array::String).asWord()), get(thisOperand), getToInt32(indexOperand));
+        int thisOperand = virtualRegisterForArgument(0, registerOffset).offset();
+        int indexOperand = virtualRegisterForArgument(1, registerOffset).offset();
+        Node* charCode = addToGraph(StringCharAt, OpInfo(ArrayMode(Array::String).asWord()), get(VirtualRegister(thisOperand)), getToInt32(indexOperand));
 
-        set(resultOperand, charCode);
+        set(VirtualRegister(resultOperand), charCode);
         return true;
     }
     case FromCharCodeIntrinsic: {
         if (argumentCountIncludingThis != 2)
             return false;
 
-        int indexOperand = registerOffset + argumentToOperand(1);
+        int indexOperand = virtualRegisterForArgument(1, registerOffset).offset();
         Node* charCode = addToGraph(StringFromCharCode, getToInt32(indexOperand));
 
-        set(resultOperand, charCode);
+        set(VirtualRegister(resultOperand), charCode);
 
         return true;
     }
@@ -1572,8 +1573,8 @@ bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int
         if (argumentCountIncludingThis != 2)
             return false;
         
-        Node* regExpExec = addToGraph(RegExpExec, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1)));
-        set(resultOperand, regExpExec);
+        Node* regExpExec = addToGraph(RegExpExec, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
+        set(VirtualRegister(resultOperand), regExpExec);
         
         return true;
     }
@@ -1582,8 +1583,8 @@ bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int
         if (argumentCountIncludingThis != 2)
             return false;
         
-        Node* regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1)));
-        set(resultOperand, regExpExec);
+        Node* regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
+        set(VirtualRegister(resultOperand), regExpExec);
         
         return true;
     }
@@ -1591,11 +1592,11 @@ bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int
     case IMulIntrinsic: {
         if (argumentCountIncludingThis != 3)
             return false;
-        int leftOperand = registerOffset + argumentToOperand(1);
-        int rightOperand = registerOffset + argumentToOperand(2);
+        int leftOperand = virtualRegisterForArgument(1, registerOffset).offset();
+        int rightOperand = virtualRegisterForArgument(2, registerOffset).offset();
         Node* left = getToInt32(leftOperand);
         Node* right = getToInt32(rightOperand);
-        set(resultOperand, addToGraph(ArithIMul, left, right));
+        set(VirtualRegister(resultOperand), addToGraph(ArithIMul, left, right));
         return true;
     }
         
@@ -1651,8 +1652,8 @@ bool ByteCodeParser::handleTypedArrayConstructor(
     if (argumentCountIncludingThis != 2)
         return false;
     
-    set(resultOperand,
-        addToGraph(NewTypedArray, OpInfo(type), get(registerOffset + argumentToOperand(1))));
+    set(VirtualRegister(resultOperand),
+        addToGraph(NewTypedArray, OpInfo(type), get(virtualRegisterForArgument(1, registerOffset))));
     return true;
 }
 
@@ -1674,14 +1675,14 @@ bool ByteCodeParser::handleConstantInternalFunction(
             return false;
         
         if (argumentCountIncludingThis == 2) {
-            set(resultOperand,
-                addToGraph(NewArrayWithSize, OpInfo(ArrayWithUndecided), get(registerOffset + argumentToOperand(1))));
+            set(VirtualRegister(resultOperand),
+                addToGraph(NewArrayWithSize, OpInfo(ArrayWithUndecided), get(virtualRegisterForArgument(1, registerOffset))));
             return true;
         }
         
         for (int i = 1; i < argumentCountIncludingThis; ++i)
-            addVarArgChild(get(registerOffset + argumentToOperand(i)));
-        set(resultOperand,
+            addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
+        set(VirtualRegister(resultOperand),
             addToGraph(Node::VarArg, NewArray, OpInfo(ArrayWithUndecided), OpInfo(0)));
         return true;
     }
@@ -1692,12 +1693,12 @@ bool ByteCodeParser::handleConstantInternalFunction(
         if (argumentCountIncludingThis <= 1)
             result = cellConstant(m_vm->smallStrings.emptyString());
         else
-            result = addToGraph(ToString, get(registerOffset + argumentToOperand(1)));
+            result = addToGraph(ToString, get(virtualRegisterForArgument(1, registerOffset)));
         
         if (kind == CodeForConstruct)
             result = addToGraph(NewStringObject, OpInfo(function->globalObject()->stringObjectStructure()), result);
         
-        set(resultOperand, result);
+        set(VirtualRegister(resultOperand), result);
         return true;
     }
     
@@ -1733,7 +1734,7 @@ void ByteCodeParser::handleGetByOffset(
     int destinationOperand, SpeculatedType prediction, Node* base, unsigned identifierNumber,
     PropertyOffset offset)
 {
-    set(destinationOperand, handleGetByOffset(prediction, base, identifierNumber, offset));
+    set(VirtualRegister(destinationOperand), handleGetByOffset(prediction, base, identifierNumber, offset));
 }
 
 Node* ByteCodeParser::handlePutByOffset(Node* base, unsigned identifier, PropertyOffset offset, Node* value)
@@ -1760,7 +1761,7 @@ void ByteCodeParser::handleGetById(
     if (!getByIdStatus.isSimple()
         || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)
         || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadWeakConstantCache)) {
-        set(destinationOperand,
+        set(VirtualRegister(destinationOperand),
             addToGraph(
                 getByIdStatus.makesCalls() ? GetByIdFlush : GetById,
                 OpInfo(identifierNumber), OpInfo(prediction), base));
@@ -1803,7 +1804,7 @@ void ByteCodeParser::handleGetById(
     if (getByIdStatus.specificValue()) {
         ASSERT(getByIdStatus.specificValue().isCell());
         
-        set(destinationOperand, cellConstant(getByIdStatus.specificValue().asCell()));
+        set(VirtualRegister(destinationOperand), cellConstant(getByIdStatus.specificValue().asCell()));
         return;
     }
     
@@ -1850,7 +1851,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         m_graph.m_arguments.resize(m_numArguments);
         for (unsigned argument = 0; argument < m_numArguments; ++argument) {
             VariableAccessData* variable = newVariableAccessData(
-                argumentToOperand(argument), m_codeBlock->isCaptured(argumentToOperand(argument)));
+                virtualRegisterForArgument(argument), m_codeBlock->isCaptured(virtualRegisterForArgument(argument)));
             variable->mergeStructureCheckHoistingFailed(
                 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
             variable->mergeCheckArrayHoistingFailed(
@@ -1899,7 +1900,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         case op_enter:
             // Initialize all locals to undefined.
             for (int i = 0; i < m_inlineStackTop->m_codeBlock->m_numVars; ++i)
-                set(localToOperand(i), constantUndefined(), SetOnEntry);
+                set(virtualRegisterForLocal(i), constantUndefined(), SetOnEntry);
             NEXT_OPCODE(op_enter);
 
         case op_to_this: {
@@ -1923,7 +1924,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_create_this: {
             int calleeOperand = currentInstruction[2].u.operand;
-            Node* callee = get(calleeOperand);
+            Node* callee = get(VirtualRegister(calleeOperand));
             bool alreadyEmitted = false;
             if (callee->op() == WeakJSConstant) {
                 JSCell* cell = callee->weakConstant();
@@ -1935,19 +1936,19 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                     addToGraph(AllocationProfileWatchpoint, OpInfo(function));
                     // The callee is still live up to this point.
                     addToGraph(Phantom, callee);
-                    set(currentInstruction[1].u.operand,
+                    set(VirtualRegister(currentInstruction[1].u.operand),
                         addToGraph(NewObject, OpInfo(allocationProfile->structure())));
                     alreadyEmitted = true;
                 }
             }
             if (!alreadyEmitted)
-                set(currentInstruction[1].u.operand,
+                set(VirtualRegister(currentInstruction[1].u.operand),
                     addToGraph(CreateThis, OpInfo(currentInstruction[3].u.operand), callee));
             NEXT_OPCODE(op_create_this);
         }
 
         case op_new_object: {
-            set(currentInstruction[1].u.operand,
+            set(VirtualRegister(currentInstruction[1].u.operand),
                 addToGraph(NewObject,
                     OpInfo(currentInstruction[3].u.objectAllocationProfile->structure())));
             NEXT_OPCODE(op_new_object);
@@ -1958,15 +1959,15 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             int numOperands = currentInstruction[3].u.operand;
             ArrayAllocationProfile* profile = currentInstruction[4].u.arrayAllocationProfile;
             for (int operandIdx = startOperand; operandIdx > startOperand - numOperands; --operandIdx)
-                addVarArgChild(get(operandIdx));
-            set(currentInstruction[1].u.operand, addToGraph(Node::VarArg, NewArray, OpInfo(profile->selectIndexingType()), OpInfo(0)));
+                addVarArgChild(get(VirtualRegister(operandIdx)));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(Node::VarArg, NewArray, OpInfo(profile->selectIndexingType()), OpInfo(0)));
             NEXT_OPCODE(op_new_array);
         }
             
         case op_new_array_with_size: {
             int lengthOperand = currentInstruction[2].u.operand;
             ArrayAllocationProfile* profile = currentInstruction[3].u.arrayAllocationProfile;
-            set(currentInstruction[1].u.operand, addToGraph(NewArrayWithSize, OpInfo(profile->selectIndexingType()), get(lengthOperand)));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewArrayWithSize, OpInfo(profile->selectIndexingType()), get(VirtualRegister(lengthOperand))));
             NEXT_OPCODE(op_new_array_with_size);
         }
             
@@ -1988,12 +1989,12 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             }
             
             m_graph.m_newArrayBufferData.append(data);
-            set(currentInstruction[1].u.operand, addToGraph(NewArrayBuffer, OpInfo(&m_graph.m_newArrayBufferData.last())));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewArrayBuffer, OpInfo(&m_graph.m_newArrayBufferData.last())));
             NEXT_OPCODE(op_new_array_buffer);
         }
             
         case op_new_regexp: {
-            set(currentInstruction[1].u.operand, addToGraph(NewRegexp, OpInfo(currentInstruction[2].u.operand)));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewRegexp, OpInfo(currentInstruction[2].u.operand)));
             NEXT_OPCODE(op_new_regexp);
         }
             
@@ -2002,12 +2003,12 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             if (!cachedFunction 
                 || m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex)
                 || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadFunction)) {
-                set(currentInstruction[1].u.operand, get(JSStack::Callee));
+                set(VirtualRegister(currentInstruction[1].u.operand), get(VirtualRegister(JSStack::Callee)));
             } else {
                 ASSERT(cachedFunction->inherits(JSFunction::info()));
-                Node* actualCallee = get(JSStack::Callee);
+                Node* actualCallee = get(VirtualRegister(JSStack::Callee));
                 addToGraph(CheckFunction, OpInfo(cachedFunction), actualCallee);
-                set(currentInstruction[1].u.operand, addToGraph(WeakJSConstant, OpInfo(cachedFunction)));
+                set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(WeakJSConstant, OpInfo(cachedFunction)));
             }
             NEXT_OPCODE(op_get_callee);
         }
@@ -2017,21 +2018,21 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         case op_bitand: {
             Node* op1 = getToInt32(currentInstruction[2].u.operand);
             Node* op2 = getToInt32(currentInstruction[3].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(BitAnd, op1, op2));
             NEXT_OPCODE(op_bitand);
         }
 
         case op_bitor: {
             Node* op1 = getToInt32(currentInstruction[2].u.operand);
             Node* op2 = getToInt32(currentInstruction[3].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(BitOr, op1, op2));
             NEXT_OPCODE(op_bitor);
         }
 
         case op_bitxor: {
             Node* op1 = getToInt32(currentInstruction[2].u.operand);
             Node* op2 = getToInt32(currentInstruction[3].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(BitXor, op1, op2));
             NEXT_OPCODE(op_bitxor);
         }
 
@@ -2044,7 +2045,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 result = op1;
             else
                 result = addToGraph(BitRShift, op1, op2);
-            set(currentInstruction[1].u.operand, result);
+            set(VirtualRegister(currentInstruction[1].u.operand), result);
             NEXT_OPCODE(op_rshift);
         }
 
@@ -2057,7 +2058,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 result = op1;
             else
                 result = addToGraph(BitLShift, op1, op2);
-            set(currentInstruction[1].u.operand, result);
+            set(VirtualRegister(currentInstruction[1].u.operand), result);
             NEXT_OPCODE(op_lshift);
         }
 
@@ -2084,7 +2085,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 result = addToGraph(BitURShift, op1, op2);
                 result = makeSafe(addToGraph(UInt32ToNumber, result));
             }
-            set(currentInstruction[1].u.operand, result);
+            set(VirtualRegister(currentInstruction[1].u.operand), result);
             NEXT_OPCODE(op_urshift);
         }
 
@@ -2092,62 +2093,64 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_inc: {
             int srcDst = currentInstruction[1].u.operand;
-            Node* op = get(srcDst);
-            set(srcDst, makeSafe(addToGraph(ArithAdd, op, one())));
+            VirtualRegister srcDstVirtualRegister = VirtualRegister(srcDst);
+            Node* op = get(srcDstVirtualRegister);
+            set(srcDstVirtualRegister, makeSafe(addToGraph(ArithAdd, op, one())));
             NEXT_OPCODE(op_inc);
         }
 
         case op_dec: {
             int srcDst = currentInstruction[1].u.operand;
-            Node* op = get(srcDst);
-            set(srcDst, makeSafe(addToGraph(ArithSub, op, one())));
+            VirtualRegister srcDstVirtualRegister = VirtualRegister(srcDst);
+            Node* op = get(srcDstVirtualRegister);
+            set(srcDstVirtualRegister, makeSafe(addToGraph(ArithSub, op, one())));
             NEXT_OPCODE(op_dec);
         }
 
         // === Arithmetic operations ===
 
         case op_add: {
-            Node* op1 = get(currentInstruction[2].u.operand);
-            Node* op2 = get(currentInstruction[3].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
             if (op1->hasNumberResult() && op2->hasNumberResult())
-                set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithAdd, op1, op2)));
+                set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ArithAdd, op1, op2)));
             else
-                set(currentInstruction[1].u.operand, makeSafe(addToGraph(ValueAdd, op1, op2)));
+                set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ValueAdd, op1, op2)));
             NEXT_OPCODE(op_add);
         }
 
         case op_sub: {
-            Node* op1 = get(currentInstruction[2].u.operand);
-            Node* op2 = get(currentInstruction[3].u.operand);
-            set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithSub, op1, op2)));
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ArithSub, op1, op2)));
             NEXT_OPCODE(op_sub);
         }
 
         case op_negate: {
-            Node* op1 = get(currentInstruction[2].u.operand);
-            set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithNegate, op1)));
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ArithNegate, op1)));
             NEXT_OPCODE(op_negate);
         }
 
         case op_mul: {
             // Multiply requires that the inputs are not truncated, unfortunately.
-            Node* op1 = get(currentInstruction[2].u.operand);
-            Node* op2 = get(currentInstruction[3].u.operand);
-            set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMul, op1, op2)));
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ArithMul, op1, op2)));
             NEXT_OPCODE(op_mul);
         }
 
         case op_mod: {
-            Node* op1 = get(currentInstruction[2].u.operand);
-            Node* op2 = get(currentInstruction[3].u.operand);
-            set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMod, op1, op2)));
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ArithMod, op1, op2)));
             NEXT_OPCODE(op_mod);
         }
 
         case op_div: {
-            Node* op1 = get(currentInstruction[2].u.operand);
-            Node* op2 = get(currentInstruction[3].u.operand);
-            set(currentInstruction[1].u.operand, makeDivSafe(addToGraph(ArithDiv, op1, op2)));
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), makeDivSafe(addToGraph(ArithDiv, op1, op2)));
             NEXT_OPCODE(op_div);
         }
 
@@ -2159,67 +2162,67 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             NEXT_OPCODE(op_debug);
 #endif
         case op_mov: {
-            Node* op = get(currentInstruction[2].u.operand);
-            set(currentInstruction[1].u.operand, op);
+            Node* op = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), op);
             NEXT_OPCODE(op_mov);
         }
 
         case op_check_has_instance:
-            addToGraph(CheckHasInstance, get(currentInstruction[3].u.operand));
+            addToGraph(CheckHasInstance, get(VirtualRegister(currentInstruction[3].u.operand)));
             NEXT_OPCODE(op_check_has_instance);
 
         case op_instanceof: {
-            Node* value = get(currentInstruction[2].u.operand);
-            Node* prototype = get(currentInstruction[3].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(InstanceOf, value, prototype));
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* prototype = get(VirtualRegister(currentInstruction[3].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(InstanceOf, value, prototype));
             NEXT_OPCODE(op_instanceof);
         }
             
         case op_is_undefined: {
-            Node* value = get(currentInstruction[2].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(IsUndefined, value));
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsUndefined, value));
             NEXT_OPCODE(op_is_undefined);
         }
 
         case op_is_boolean: {
-            Node* value = get(currentInstruction[2].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(IsBoolean, value));
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsBoolean, value));
             NEXT_OPCODE(op_is_boolean);
         }
 
         case op_is_number: {
-            Node* value = get(currentInstruction[2].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(IsNumber, value));
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsNumber, value));
             NEXT_OPCODE(op_is_number);
         }
 
         case op_is_string: {
-            Node* value = get(currentInstruction[2].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(IsString, value));
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsString, value));
             NEXT_OPCODE(op_is_string);
         }
 
         case op_is_object: {
-            Node* value = get(currentInstruction[2].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(IsObject, value));
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsObject, value));
             NEXT_OPCODE(op_is_object);
         }
 
         case op_is_function: {
-            Node* value = get(currentInstruction[2].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(IsFunction, value));
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(IsFunction, value));
             NEXT_OPCODE(op_is_function);
         }
 
         case op_not: {
-            Node* value = get(currentInstruction[2].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(LogicalNot, value));
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(LogicalNot, value));
             NEXT_OPCODE(op_not);
         }
             
         case op_to_primitive: {
-            Node* value = get(currentInstruction[2].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(ToPrimitive, value));
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(ToPrimitive, value));
             NEXT_OPCODE(op_to_primitive);
         }
             
@@ -2235,7 +2238,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 #endif
             auto toStringNodes = std::make_unique<Node*[]>(numOperands);
             for (int i = 0; i < numOperands; i++)
-                toStringNodes[i] = addToGraph(ToString, get(startOperand - i));
+                toStringNodes[i] = addToGraph(ToString, get(VirtualRegister(startOperand - i)));
 
             for (int i = 0; i < numOperands; i++)
                 addToGraph(Phantom, toStringNodes[i]);
@@ -2256,141 +2259,141 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 ASSERT(indexInOperands < maxRopeArguments);
                 operands[indexInOperands++] = toStringNodes[operandIdx];
             }
-            set(currentInstruction[1].u.operand,
+            set(VirtualRegister(currentInstruction[1].u.operand),
                 addToGraph(MakeRope, operands[0], operands[1], operands[2]));
             NEXT_OPCODE(op_strcat);
         }
 
         case op_less: {
-            Node* op1 = get(currentInstruction[2].u.operand);
-            Node* op2 = get(currentInstruction[3].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue a = valueOfJSConstant(op1);
                 JSValue b = valueOfJSConstant(op2);
                 if (a.isNumber() && b.isNumber()) {
-                    set(currentInstruction[1].u.operand,
+                    set(VirtualRegister(currentInstruction[1].u.operand),
                         getJSConstantForValue(jsBoolean(a.asNumber() < b.asNumber())));
                     NEXT_OPCODE(op_less);
                 }
             }
-            set(currentInstruction[1].u.operand, addToGraph(CompareLess, op1, op2));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareLess, op1, op2));
             NEXT_OPCODE(op_less);
         }
 
         case op_lesseq: {
-            Node* op1 = get(currentInstruction[2].u.operand);
-            Node* op2 = get(currentInstruction[3].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue a = valueOfJSConstant(op1);
                 JSValue b = valueOfJSConstant(op2);
                 if (a.isNumber() && b.isNumber()) {
-                    set(currentInstruction[1].u.operand,
+                    set(VirtualRegister(currentInstruction[1].u.operand),
                         getJSConstantForValue(jsBoolean(a.asNumber() <= b.asNumber())));
                     NEXT_OPCODE(op_lesseq);
                 }
             }
-            set(currentInstruction[1].u.operand, addToGraph(CompareLessEq, op1, op2));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareLessEq, op1, op2));
             NEXT_OPCODE(op_lesseq);
         }
 
         case op_greater: {
-            Node* op1 = get(currentInstruction[2].u.operand);
-            Node* op2 = get(currentInstruction[3].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue a = valueOfJSConstant(op1);
                 JSValue b = valueOfJSConstant(op2);
                 if (a.isNumber() && b.isNumber()) {
-                    set(currentInstruction[1].u.operand,
+                    set(VirtualRegister(currentInstruction[1].u.operand),
                         getJSConstantForValue(jsBoolean(a.asNumber() > b.asNumber())));
                     NEXT_OPCODE(op_greater);
                 }
             }
-            set(currentInstruction[1].u.operand, addToGraph(CompareGreater, op1, op2));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareGreater, op1, op2));
             NEXT_OPCODE(op_greater);
         }
 
         case op_greatereq: {
-            Node* op1 = get(currentInstruction[2].u.operand);
-            Node* op2 = get(currentInstruction[3].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue a = valueOfJSConstant(op1);
                 JSValue b = valueOfJSConstant(op2);
                 if (a.isNumber() && b.isNumber()) {
-                    set(currentInstruction[1].u.operand,
+                    set(VirtualRegister(currentInstruction[1].u.operand),
                         getJSConstantForValue(jsBoolean(a.asNumber() >= b.asNumber())));
                     NEXT_OPCODE(op_greatereq);
                 }
             }
-            set(currentInstruction[1].u.operand, addToGraph(CompareGreaterEq, op1, op2));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareGreaterEq, op1, op2));
             NEXT_OPCODE(op_greatereq);
         }
 
         case op_eq: {
-            Node* op1 = get(currentInstruction[2].u.operand);
-            Node* op2 = get(currentInstruction[3].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue a = valueOfJSConstant(op1);
                 JSValue b = valueOfJSConstant(op2);
-                set(currentInstruction[1].u.operand,
+                set(VirtualRegister(currentInstruction[1].u.operand),
                     getJSConstantForValue(jsBoolean(JSValue::equal(m_codeBlock->globalObject()->globalExec(), a, b))));
                 NEXT_OPCODE(op_eq);
             }
-            set(currentInstruction[1].u.operand, addToGraph(CompareEq, op1, op2));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareEq, op1, op2));
             NEXT_OPCODE(op_eq);
         }
 
         case op_eq_null: {
-            Node* value = get(currentInstruction[2].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(CompareEqConstant, value, constantNull()));
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareEqConstant, value, constantNull()));
             NEXT_OPCODE(op_eq_null);
         }
 
         case op_stricteq: {
-            Node* op1 = get(currentInstruction[2].u.operand);
-            Node* op2 = get(currentInstruction[3].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue a = valueOfJSConstant(op1);
                 JSValue b = valueOfJSConstant(op2);
-                set(currentInstruction[1].u.operand,
+                set(VirtualRegister(currentInstruction[1].u.operand),
                     getJSConstantForValue(jsBoolean(JSValue::strictEqual(m_codeBlock->globalObject()->globalExec(), a, b))));
                 NEXT_OPCODE(op_stricteq);
             }
             if (isConstantForCompareStrictEq(op1))
-                set(currentInstruction[1].u.operand, addToGraph(CompareStrictEqConstant, op2, op1));
+                set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareStrictEqConstant, op2, op1));
             else if (isConstantForCompareStrictEq(op2))
-                set(currentInstruction[1].u.operand, addToGraph(CompareStrictEqConstant, op1, op2));
+                set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareStrictEqConstant, op1, op2));
             else
-                set(currentInstruction[1].u.operand, addToGraph(CompareStrictEq, op1, op2));
+                set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareStrictEq, op1, op2));
             NEXT_OPCODE(op_stricteq);
         }
 
         case op_neq: {
-            Node* op1 = get(currentInstruction[2].u.operand);
-            Node* op2 = get(currentInstruction[3].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue a = valueOfJSConstant(op1);
                 JSValue b = valueOfJSConstant(op2);
-                set(currentInstruction[1].u.operand,
+                set(VirtualRegister(currentInstruction[1].u.operand),
                     getJSConstantForValue(jsBoolean(!JSValue::equal(m_codeBlock->globalObject()->globalExec(), a, b))));
                 NEXT_OPCODE(op_neq);
             }
-            set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareEq, op1, op2)));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(LogicalNot, addToGraph(CompareEq, op1, op2)));
             NEXT_OPCODE(op_neq);
         }
 
         case op_neq_null: {
-            Node* value = get(currentInstruction[2].u.operand);
-            set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareEqConstant, value, constantNull())));
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(LogicalNot, addToGraph(CompareEqConstant, value, constantNull())));
             NEXT_OPCODE(op_neq_null);
         }
 
         case op_nstricteq: {
-            Node* op1 = get(currentInstruction[2].u.operand);
-            Node* op2 = get(currentInstruction[3].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue a = valueOfJSConstant(op1);
                 JSValue b = valueOfJSConstant(op2);
-                set(currentInstruction[1].u.operand,
+                set(VirtualRegister(currentInstruction[1].u.operand),
                     getJSConstantForValue(jsBoolean(!JSValue::strictEqual(m_codeBlock->globalObject()->globalExec(), a, b))));
                 NEXT_OPCODE(op_nstricteq);
             }
@@ -2401,7 +2404,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 invertedResult = addToGraph(CompareStrictEqConstant, op1, op2);
             else
                 invertedResult = addToGraph(CompareStrictEq, op1, op2);
-            set(currentInstruction[1].u.operand, addToGraph(LogicalNot, invertedResult));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(LogicalNot, invertedResult));
             NEXT_OPCODE(op_nstricteq);
         }
 
@@ -2410,22 +2413,22 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         case op_get_by_val: {
             SpeculatedType prediction = getPrediction();
             
-            Node* base = get(currentInstruction[2].u.operand);
+            Node* base = get(VirtualRegister(currentInstruction[2].u.operand));
             ArrayMode arrayMode = getArrayModeConsideringSlowPath(currentInstruction[4].u.arrayProfile, Array::Read);
-            Node* property = get(currentInstruction[3].u.operand);
+            Node* property = get(VirtualRegister(currentInstruction[3].u.operand));
             Node* getByVal = addToGraph(GetByVal, OpInfo(arrayMode.asWord()), OpInfo(prediction), base, property);
-            set(currentInstruction[1].u.operand, getByVal);
+            set(VirtualRegister(currentInstruction[1].u.operand), getByVal);
 
             NEXT_OPCODE(op_get_by_val);
         }
 
         case op_put_by_val: {
-            Node* base = get(currentInstruction[1].u.operand);
+            Node* base = get(VirtualRegister(currentInstruction[1].u.operand));
 
             ArrayMode arrayMode = getArrayModeConsideringSlowPath(currentInstruction[4].u.arrayProfile, Array::Write);
             
-            Node* property = get(currentInstruction[2].u.operand);
-            Node* value = get(currentInstruction[3].u.operand);
+            Node* property = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* value = get(VirtualRegister(currentInstruction[3].u.operand));
             
             addVarArgChild(base);
             addVarArgChild(property);
@@ -2441,7 +2444,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         case op_get_array_length: {
             SpeculatedType prediction = getPrediction();
             
-            Node* base = get(currentInstruction[2].u.operand);
+            Node* base = get(VirtualRegister(currentInstruction[2].u.operand));
             unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand];
             
             StringImpl* uid = m_graph.identifiers()[identifierNumber];
@@ -2459,8 +2462,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         case op_put_by_id_transition_normal:
         case op_put_by_id_transition_direct_out_of_line:
         case op_put_by_id_transition_normal_out_of_line: {
-            Node* value = get(currentInstruction[3].u.operand);
-            Node* base = get(currentInstruction[1].u.operand);
+            Node* value = get(VirtualRegister(currentInstruction[3].u.operand));
+            Node* base = get(VirtualRegister(currentInstruction[1].u.operand));
             unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
             bool direct = currentInstruction[8].u.operand;
 
@@ -2566,7 +2569,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         }
 
         case op_init_global_const: {
-            Node* value = get(currentInstruction[2].u.operand);
+            Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
             addToGraph(
                 PutGlobalVar,
                 OpInfo(m_inlineStackTop->m_codeBlock->globalObject()->assertRegisterIsInThisObject(currentInstruction[1].u.registerPointer)),
@@ -2584,7 +2587,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_jtrue: {
             unsigned relativeOffset = currentInstruction[2].u.operand;
-            Node* condition = get(currentInstruction[1].u.operand);
+            Node* condition = get(VirtualRegister(currentInstruction[1].u.operand));
             if (canFold(condition)) {
                 TriState state = valueOfJSConstant(condition).pureToBoolean();
                 if (state == TrueTriState) {
@@ -2603,7 +2606,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_jfalse: {
             unsigned relativeOffset = currentInstruction[2].u.operand;
-            Node* condition = get(currentInstruction[1].u.operand);
+            Node* condition = get(VirtualRegister(currentInstruction[1].u.operand));
             if (canFold(condition)) {
                 TriState state = valueOfJSConstant(condition).pureToBoolean();
                 if (state == FalseTriState) {
@@ -2622,7 +2625,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_jeq_null: {
             unsigned relativeOffset = currentInstruction[2].u.operand;
-            Node* value = get(currentInstruction[1].u.operand);
+            Node* value = get(VirtualRegister(currentInstruction[1].u.operand));
             Node* condition = addToGraph(CompareEqConstant, value, constantNull());
             addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jeq_null)), condition);
             LAST_OPCODE(op_jeq_null);
@@ -2630,7 +2633,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_jneq_null: {
             unsigned relativeOffset = currentInstruction[2].u.operand;
-            Node* value = get(currentInstruction[1].u.operand);
+            Node* value = get(VirtualRegister(currentInstruction[1].u.operand));
             Node* condition = addToGraph(CompareEqConstant, value, constantNull());
             addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jneq_null)), OpInfo(m_currentIndex + relativeOffset), condition);
             LAST_OPCODE(op_jneq_null);
@@ -2638,8 +2641,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_jless: {
             unsigned relativeOffset = currentInstruction[3].u.operand;
-            Node* op1 = get(currentInstruction[1].u.operand);
-            Node* op2 = get(currentInstruction[2].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue aValue = valueOfJSConstant(op1);
                 JSValue bValue = valueOfJSConstant(op2);
@@ -2664,8 +2667,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_jlesseq: {
             unsigned relativeOffset = currentInstruction[3].u.operand;
-            Node* op1 = get(currentInstruction[1].u.operand);
-            Node* op2 = get(currentInstruction[2].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue aValue = valueOfJSConstant(op1);
                 JSValue bValue = valueOfJSConstant(op2);
@@ -2690,8 +2693,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_jgreater: {
             unsigned relativeOffset = currentInstruction[3].u.operand;
-            Node* op1 = get(currentInstruction[1].u.operand);
-            Node* op2 = get(currentInstruction[2].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue aValue = valueOfJSConstant(op1);
                 JSValue bValue = valueOfJSConstant(op2);
@@ -2716,8 +2719,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_jgreatereq: {
             unsigned relativeOffset = currentInstruction[3].u.operand;
-            Node* op1 = get(currentInstruction[1].u.operand);
-            Node* op2 = get(currentInstruction[2].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue aValue = valueOfJSConstant(op1);
                 JSValue bValue = valueOfJSConstant(op2);
@@ -2742,8 +2745,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_jnless: {
             unsigned relativeOffset = currentInstruction[3].u.operand;
-            Node* op1 = get(currentInstruction[1].u.operand);
-            Node* op2 = get(currentInstruction[2].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue aValue = valueOfJSConstant(op1);
                 JSValue bValue = valueOfJSConstant(op2);
@@ -2768,8 +2771,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_jnlesseq: {
             unsigned relativeOffset = currentInstruction[3].u.operand;
-            Node* op1 = get(currentInstruction[1].u.operand);
-            Node* op2 = get(currentInstruction[2].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue aValue = valueOfJSConstant(op1);
                 JSValue bValue = valueOfJSConstant(op2);
@@ -2794,8 +2797,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_jngreater: {
             unsigned relativeOffset = currentInstruction[3].u.operand;
-            Node* op1 = get(currentInstruction[1].u.operand);
-            Node* op2 = get(currentInstruction[2].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue aValue = valueOfJSConstant(op1);
                 JSValue bValue = valueOfJSConstant(op2);
@@ -2820,8 +2823,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_jngreatereq: {
             unsigned relativeOffset = currentInstruction[3].u.operand;
-            Node* op1 = get(currentInstruction[1].u.operand);
-            Node* op2 = get(currentInstruction[2].u.operand);
+            Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
+            Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
             if (canFold(op1) && canFold(op2)) {
                 JSValue aValue = valueOfJSConstant(op1);
                 JSValue bValue = valueOfJSConstant(op2);
@@ -2859,7 +2862,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 data.cases.append(SwitchCase::withBytecodeIndex(jsNumber(static_cast<int32_t>(table.min + i)), target));
             }
             m_graph.m_switchData.append(data);
-            addToGraph(Switch, OpInfo(&m_graph.m_switchData.last()), get(currentInstruction[3].u.operand));
+            addToGraph(Switch, OpInfo(&m_graph.m_switchData.last()), get(VirtualRegister(currentInstruction[3].u.operand)));
             LAST_OPCODE(op_switch_imm);
         }
             
@@ -2879,7 +2882,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                     SwitchCase::withBytecodeIndex(LazyJSValue::singleCharacterString(table.min + i), target));
             }
             m_graph.m_switchData.append(data);
-            addToGraph(Switch, OpInfo(&m_graph.m_switchData.last()), get(currentInstruction[3].u.operand));
+            addToGraph(Switch, OpInfo(&m_graph.m_switchData.last()), get(VirtualRegister(currentInstruction[3].u.operand)));
             LAST_OPCODE(op_switch_char);
         }
 
@@ -2899,15 +2902,15 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                     SwitchCase::withBytecodeIndex(LazyJSValue::knownStringImpl(iter->key.get()), target));
             }
             m_graph.m_switchData.append(data);
-            addToGraph(Switch, OpInfo(&m_graph.m_switchData.last()), get(currentInstruction[3].u.operand));
+            addToGraph(Switch, OpInfo(&m_graph.m_switchData.last()), get(VirtualRegister(currentInstruction[3].u.operand)));
             LAST_OPCODE(op_switch_string);
         }
 
         case op_ret:
             flushArgumentsAndCapturedVariables();
             if (inlineCallFrame()) {
-                ASSERT(m_inlineStackTop->m_returnValue != InvalidVirtualRegister);
-                setDirect(m_inlineStackTop->m_returnValue, get(currentInstruction[1].u.operand));
+                ASSERT(m_inlineStackTop->m_returnValue.isValid());
+                setDirect(m_inlineStackTop->m_returnValue, get(VirtualRegister(currentInstruction[1].u.operand)));
                 m_inlineStackTop->m_didReturn = true;
                 if (m_inlineStackTop->m_unlinkedBlocks.isEmpty()) {
                     // If we're returning from the first block, then we're done parsing.
@@ -2928,17 +2931,17 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 }
                 LAST_OPCODE(op_ret);
             }
-            addToGraph(Return, get(currentInstruction[1].u.operand));
+            addToGraph(Return, get(VirtualRegister(currentInstruction[1].u.operand)));
             LAST_OPCODE(op_ret);
             
         case op_end:
             flushArgumentsAndCapturedVariables();
             ASSERT(!inlineCallFrame());
-            addToGraph(Return, get(currentInstruction[1].u.operand));
+            addToGraph(Return, get(VirtualRegister(currentInstruction[1].u.operand)));
             LAST_OPCODE(op_end);
 
         case op_throw:
-            addToGraph(Throw, get(currentInstruction[1].u.operand));
+            addToGraph(Throw, get(VirtualRegister(currentInstruction[1].u.operand)));
             flushAllArgumentsAndCapturedVariablesInInlineStack();
             addToGraph(Unreachable);
             LAST_OPCODE(op_throw);
@@ -2959,7 +2962,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             
         case op_call_varargs: {
             ASSERT(inlineCallFrame());
-            ASSERT(currentInstruction[4].u.operand == m_inlineStackTop->m_codeBlock->argumentsRegister());
+            ASSERT(currentInstruction[4].u.operand == m_inlineStackTop->m_codeBlock->argumentsRegister().offset());
             ASSERT(!m_inlineStackTop->m_codeBlock->symbolTable()->slowArguments());
             // It would be cool to funnel this into handleCall() so that it can handle
             // inlining. But currently that won't be profitable anyway, since none of the
@@ -2974,12 +2977,12 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             if (JSStack::CallFrameHeaderSize + argCount > m_parameterSlots)
                 m_parameterSlots = JSStack::CallFrameHeaderSize + argCount;
             
-            addVarArgChild(get(currentInstruction[2].u.operand)); // callee
-            addVarArgChild(get(currentInstruction[3].u.operand)); // this
+            addVarArgChild(get(VirtualRegister(currentInstruction[2].u.operand))); // callee
+            addVarArgChild(get(VirtualRegister(currentInstruction[3].u.operand))); // this
             for (unsigned argument = 1; argument < argCount; ++argument)
-                addVarArgChild(get(argumentToOperand(argument)));
+                addVarArgChild(get(virtualRegisterForArgument(argument)));
             
-            set(currentInstruction[1].u.operand,
+            set(VirtualRegister(currentInstruction[1].u.operand),
                 addToGraph(Node::VarArg, Call, OpInfo(0), OpInfo(prediction)));
             
             NEXT_OPCODE(op_call_varargs);
@@ -2993,7 +2996,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             addToGraph(
                 CheckFunction,
                 OpInfo(actualPointerFor(m_inlineStackTop->m_codeBlock, currentInstruction[2].u.specialPointer)),
-                get(currentInstruction[1].u.operand));
+                get(VirtualRegister(currentInstruction[1].u.operand)));
             addToGraph(Jump, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jneq_ptr)));
             LAST_OPCODE(op_jneq_ptr);
 
@@ -3011,11 +3014,11 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             case GlobalVar:
             case GlobalPropertyWithVarInjectionChecks:
             case GlobalVarWithVarInjectionChecks:
-                set(dst, cellConstant(m_inlineStackTop->m_codeBlock->globalObject()));
+                set(VirtualRegister(dst), cellConstant(m_inlineStackTop->m_codeBlock->globalObject()));
                 break;
             case ClosureVar:
             case ClosureVarWithVarInjectionChecks:
-                set(dst, getScope(m_inlineStackTop->m_codeBlock->needsActivation(), depth));
+                set(VirtualRegister(dst), getScope(m_inlineStackTop->m_codeBlock->needsActivation(), depth));
                 break;
             case Dynamic:
                 RELEASE_ASSERT_NOT_REACHED();
@@ -3047,34 +3050,34 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             case GlobalPropertyWithVarInjectionChecks: {
                 GetByIdStatus status = GetByIdStatus::computeFor(*m_vm, structure, uid);
                 if (status.takesSlowPath()) {
-                    set(dst, addToGraph(GetByIdFlush, OpInfo(identifierNumber), OpInfo(prediction), get(scope)));
+                    set(VirtualRegister(dst), addToGraph(GetByIdFlush, OpInfo(identifierNumber), OpInfo(prediction), get(VirtualRegister(scope))));
                     break;
                 }
                 Node* base = cellConstantWithStructureCheck(globalObject, status.structureSet().singletonStructure());
                 if (JSValue specificValue = status.specificValue())
-                    set(dst, cellConstant(specificValue.asCell()));
+                    set(VirtualRegister(dst), cellConstant(specificValue.asCell()));
                 else
-                    set(dst, handleGetByOffset(prediction, base, identifierNumber, operand));
+                    set(VirtualRegister(dst), handleGetByOffset(prediction, base, identifierNumber, operand));
                 break;
             }
             case GlobalVar:
             case GlobalVarWithVarInjectionChecks: {
                 SymbolTableEntry entry = globalObject->symbolTable()->get(uid);
                 if (!entry.couldBeWatched() || !m_graph.watchpoints().isStillValid(entry.watchpointSet())) {
-                    set(dst, addToGraph(GetGlobalVar, OpInfo(operand), OpInfo(prediction)));
+                    set(VirtualRegister(dst), addToGraph(GetGlobalVar, OpInfo(operand), OpInfo(prediction)));
                     break;
                 }
 
                 addToGraph(GlobalVarWatchpoint, OpInfo(operand), OpInfo(identifierNumber));
                 JSValue specificValue = globalObject->registerAt(entry.getIndex()).get();
-                set(dst, cellConstant(specificValue.asCell()));
+                set(VirtualRegister(dst), cellConstant(specificValue.asCell()));
                 break;
             }
             case ClosureVar:
             case ClosureVarWithVarInjectionChecks:
-                set(dst, 
+                set(VirtualRegister(dst),
                     addToGraph(GetClosureVar, OpInfo(operand), OpInfo(prediction), 
-                        addToGraph(GetClosureRegisters, get(scope))));
+                        addToGraph(GetClosureRegisters, get(VirtualRegister(scope)))));
                 break;
             case Dynamic:
                 RELEASE_ASSERT_NOT_REACHED();
@@ -3105,29 +3108,29 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             case GlobalPropertyWithVarInjectionChecks: {
                 PutByIdStatus status = PutByIdStatus::computeFor(*m_vm, globalObject, structure, uid, false);
                 if (!status.isSimpleReplace()) {
-                    addToGraph(PutById, OpInfo(identifierNumber), get(scope), get(value));
+                    addToGraph(PutById, OpInfo(identifierNumber), get(VirtualRegister(scope)), get(VirtualRegister(value)));
                     break;
                 }
                 Node* base = cellConstantWithStructureCheck(globalObject, status.oldStructure());
-                handlePutByOffset(base, identifierNumber, static_cast<PropertyOffset>(operand), get(value));
+                handlePutByOffset(base, identifierNumber, static_cast<PropertyOffset>(operand), get(VirtualRegister(value)));
                 // Keep scope alive until after put.
-                addToGraph(Phantom, get(scope));
+                addToGraph(Phantom, get(VirtualRegister(scope)));
                 break;
             }
             case GlobalVar:
             case GlobalVarWithVarInjectionChecks: {
                 SymbolTableEntry entry = globalObject->symbolTable()->get(uid);
                 ASSERT(!entry.couldBeWatched() || !m_graph.watchpoints().isStillValid(entry.watchpointSet()));
-                addToGraph(PutGlobalVar, OpInfo(operand), get(value));
+                addToGraph(PutGlobalVar, OpInfo(operand), get(VirtualRegister(value)));
                 // Keep scope alive until after put.
-                addToGraph(Phantom, get(scope));
+                addToGraph(Phantom, get(VirtualRegister(scope)));
                 break;
             }
             case ClosureVar:
             case ClosureVarWithVarInjectionChecks: {
-                Node* scopeNode = get(scope);
+                Node* scopeNode = get(VirtualRegister(scope));
                 Node* scopeRegisters = addToGraph(GetClosureRegisters, scopeNode);
-                addToGraph(PutClosureVar, OpInfo(operand), scopeNode, scopeRegisters, get(value));
+                addToGraph(PutClosureVar, OpInfo(operand), scopeNode, scopeRegisters, get(VirtualRegister(value)));
                 break;
             }
             case Dynamic:
@@ -3158,86 +3161,86 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         }
             
         case op_init_lazy_reg: {
-            set(currentInstruction[1].u.operand, getJSConstantForValue(JSValue()));
+            set(VirtualRegister(currentInstruction[1].u.operand), getJSConstantForValue(JSValue()));
             ASSERT(operandIsLocal(currentInstruction[1].u.operand));
-            m_graph.m_lazyVars.set(operandToLocal(currentInstruction[1].u.operand));
+            m_graph.m_lazyVars.set(VirtualRegister(currentInstruction[1].u.operand).toLocal());
             NEXT_OPCODE(op_init_lazy_reg);
         }
             
         case op_create_activation: {
-            set(currentInstruction[1].u.operand, addToGraph(CreateActivation, get(currentInstruction[1].u.operand)));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CreateActivation, get(VirtualRegister(currentInstruction[1].u.operand))));
             NEXT_OPCODE(op_create_activation);
         }
             
         case op_create_arguments: {
             m_graph.m_hasArguments = true;
-            Node* createArguments = addToGraph(CreateArguments, get(currentInstruction[1].u.operand));
-            set(currentInstruction[1].u.operand, createArguments);
-            set(unmodifiedArgumentsRegister(currentInstruction[1].u.operand), createArguments);
+            Node* createArguments = addToGraph(CreateArguments, get(VirtualRegister(currentInstruction[1].u.operand)));
+            set(VirtualRegister(currentInstruction[1].u.operand), createArguments);
+            set(unmodifiedArgumentsRegister(VirtualRegister(currentInstruction[1].u.operand)), createArguments);
             NEXT_OPCODE(op_create_arguments);
         }
             
         case op_tear_off_activation: {
-            addToGraph(TearOffActivation, get(currentInstruction[1].u.operand));
+            addToGraph(TearOffActivation, get(VirtualRegister(currentInstruction[1].u.operand)));
             NEXT_OPCODE(op_tear_off_activation);
         }
 
         case op_tear_off_arguments: {
             m_graph.m_hasArguments = true;
-            addToGraph(TearOffArguments, get(unmodifiedArgumentsRegister(currentInstruction[1].u.operand)), get(currentInstruction[2].u.operand));
+            addToGraph(TearOffArguments, get(unmodifiedArgumentsRegister(VirtualRegister(currentInstruction[1].u.operand))), get(VirtualRegister(currentInstruction[2].u.operand)));
             NEXT_OPCODE(op_tear_off_arguments);
         }
             
         case op_get_arguments_length: {
             m_graph.m_hasArguments = true;
-            set(currentInstruction[1].u.operand, addToGraph(GetMyArgumentsLengthSafe));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetMyArgumentsLengthSafe));
             NEXT_OPCODE(op_get_arguments_length);
         }
             
         case op_get_argument_by_val: {
             m_graph.m_hasArguments = true;
-            set(currentInstruction[1].u.operand,
+            set(VirtualRegister(currentInstruction[1].u.operand),
                 addToGraph(
                     GetMyArgumentByValSafe, OpInfo(0), OpInfo(getPrediction()),
-                    get(currentInstruction[3].u.operand)));
+                    get(VirtualRegister(currentInstruction[3].u.operand))));
             NEXT_OPCODE(op_get_argument_by_val);
         }
             
         case op_new_func: {
             if (!currentInstruction[3].u.operand) {
-                set(currentInstruction[1].u.operand,
+                set(VirtualRegister(currentInstruction[1].u.operand),
                     addToGraph(NewFunctionNoCheck, OpInfo(currentInstruction[2].u.operand)));
             } else {
-                set(currentInstruction[1].u.operand,
+                set(VirtualRegister(currentInstruction[1].u.operand),
                     addToGraph(
                         NewFunction,
                         OpInfo(currentInstruction[2].u.operand),
-                        get(currentInstruction[1].u.operand)));
+                        get(VirtualRegister(currentInstruction[1].u.operand))));
             }
             NEXT_OPCODE(op_new_func);
         }
             
         case op_new_func_exp: {
-            set(currentInstruction[1].u.operand,
+            set(VirtualRegister(currentInstruction[1].u.operand),
                 addToGraph(NewFunctionExpression, OpInfo(currentInstruction[2].u.operand)));
             NEXT_OPCODE(op_new_func_exp);
         }
 
         case op_typeof: {
-            set(currentInstruction[1].u.operand,
-                addToGraph(TypeOf, get(currentInstruction[2].u.operand)));
+            set(VirtualRegister(currentInstruction[1].u.operand),
+                addToGraph(TypeOf, get(VirtualRegister(currentInstruction[2].u.operand))));
             NEXT_OPCODE(op_typeof);
         }
 
         case op_to_number: {
-            set(currentInstruction[1].u.operand,
-                addToGraph(Identity, Edge(get(currentInstruction[2].u.operand), NumberUse)));
+            set(VirtualRegister(currentInstruction[1].u.operand),
+                addToGraph(Identity, Edge(get(VirtualRegister(currentInstruction[2].u.operand)), NumberUse)));
             NEXT_OPCODE(op_to_number);
         }
             
         case op_in: {
-            set(currentInstruction[1].u.operand,
-                addToGraph(In, get(currentInstruction[2].u.operand), get(currentInstruction[3].u.operand)));
+            set(VirtualRegister(currentInstruction[1].u.operand),
+                addToGraph(In, get(VirtualRegister(currentInstruction[2].u.operand)), get(VirtualRegister(currentInstruction[3].u.operand))));
             NEXT_OPCODE(op_in);
         }
 
@@ -3360,7 +3363,7 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
     if (m_caller) {
         // Inline case.
         ASSERT(codeBlock != byteCodeParser->m_codeBlock);
-        ASSERT(inlineCallFrameStart != InvalidVirtualRegister);
+        ASSERT(inlineCallFrameStart.isValid());
         ASSERT(callsiteBlockHead);
         
         m_inlineCallFrame = byteCodeParser->m_graph.m_inlineCallFrames->add();
@@ -3371,7 +3374,7 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
             m_inlineCallFrame,
             byteCodeParser->m_codeBlock->ownerExecutable(), 
             codeBlock->ownerExecutable());
-        m_inlineCallFrame->stackOffset = inlineCallFrameStart - JSStack::CallFrameHeaderSize;
+        m_inlineCallFrame->stackOffset = inlineCallFrameStart.offset() - JSStack::CallFrameHeaderSize;
         if (callee) {
             initializeLazyWriteBarrierForInlineCallFrameCallee(
                 byteCodeParser->m_graph.m_plan.writeBarriers,
@@ -3389,19 +3392,20 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
             m_inlineCallFrame->capturedVars = m_inlineCallFrame->caller.inlineCallFrame->capturedVars;
         else {
             for (int i = byteCodeParser->m_codeBlock->m_numVars; i--;) {
-                if (byteCodeParser->m_codeBlock->isCaptured(localToOperand(i)))
+                if (byteCodeParser->m_codeBlock->isCaptured(virtualRegisterForLocal(i)))
                     m_inlineCallFrame->capturedVars.set(i);
             }
         }
 
         for (int i = argumentCountIncludingThis; i--;) {
-            if (codeBlock->isCaptured(argumentToOperand(i)))
-                m_inlineCallFrame->capturedVars.set(operandToLocal(argumentToOperand(i) + m_inlineCallFrame->stackOffset));
+            VirtualRegister argument = virtualRegisterForArgument(i);
+            if (codeBlock->isCaptured(argument))
+                m_inlineCallFrame->capturedVars.set(VirtualRegister(argument.offset() + m_inlineCallFrame->stackOffset).toLocal());
         }
         for (size_t i = codeBlock->m_numVars; i--;) {
-            int localOperand = localToOperand(i);
-            if (codeBlock->isCaptured(localOperand))
-                m_inlineCallFrame->capturedVars.set(operandToLocal(localOperand + m_inlineCallFrame->stackOffset));
+            VirtualRegister local = virtualRegisterForLocal(i);
+            if (codeBlock->isCaptured(local))
+                m_inlineCallFrame->capturedVars.set(VirtualRegister(local.offset() + m_inlineCallFrame->stackOffset).toLocal());
         }
 
 #if DFG_ENABLE(DEBUG_VERBOSE)
@@ -3465,8 +3469,8 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
         // Machine code block case.
         ASSERT(codeBlock == byteCodeParser->m_codeBlock);
         ASSERT(!callee);
-        ASSERT(returnValueVR == InvalidVirtualRegister);
-        ASSERT(inlineCallFrameStart == InvalidVirtualRegister);
+        ASSERT(!returnValueVR.isValid());
+        ASSERT(!inlineCallFrameStart.isValid());
         ASSERT(!callsiteBlockHead);
 
         m_inlineCallFrame = 0;
@@ -3619,7 +3623,7 @@ bool ByteCodeParser::parse()
 #endif
     
     InlineStackEntry inlineStackEntry(
-        this, m_codeBlock, m_profiledBlock, 0, 0, InvalidVirtualRegister, InvalidVirtualRegister,
+        this, m_codeBlock, m_profiledBlock, 0, 0, VirtualRegister(), VirtualRegister(),
         m_codeBlock->numParameters(), CodeForCall);
     
     parseCodeBlock();
index bb620a7..b6fc951 100644 (file)
@@ -311,7 +311,7 @@ private:
         }
     }
 
-    void keepOperandAlive(BasicBlock* block, BasicBlock* jettisonedBlock, CodeOrigin codeOrigin, int operand)
+    void keepOperandAlive(BasicBlock* block, BasicBlock* jettisonedBlock, CodeOrigin codeOrigin, VirtualRegister operand)
     {
         Node* livenessNode = jettisonedBlock->variablesAtHead.operand(operand);
         if (!livenessNode)
@@ -326,9 +326,9 @@ private:
     void jettisonBlock(BasicBlock* block, BasicBlock* jettisonedBlock, CodeOrigin boundaryCodeOrigin)
     {
         for (size_t i = 0; i < jettisonedBlock->variablesAtHead.numberOfArguments(); ++i)
-            keepOperandAlive(block, jettisonedBlock, boundaryCodeOrigin, argumentToOperand(i));
+            keepOperandAlive(block, jettisonedBlock, boundaryCodeOrigin, virtualRegisterForArgument(i));
         for (size_t i = 0; i < jettisonedBlock->variablesAtHead.numberOfLocals(); ++i)
-            keepOperandAlive(block, jettisonedBlock, boundaryCodeOrigin, localToOperand(i));
+            keepOperandAlive(block, jettisonedBlock, boundaryCodeOrigin, virtualRegisterForLocal(i));
         
         fixJettisonedPredecessors(block, jettisonedBlock);
     }
@@ -380,9 +380,9 @@ private:
             // different path than secondBlock.
             
             for (size_t i = 0; i < jettisonedBlock->variablesAtHead.numberOfArguments(); ++i)
-                keepOperandAlive(firstBlock, jettisonedBlock, boundaryCodeOrigin, argumentToOperand(i));
+                keepOperandAlive(firstBlock, jettisonedBlock, boundaryCodeOrigin, virtualRegisterForArgument(i));
             for (size_t i = 0; i < jettisonedBlock->variablesAtHead.numberOfLocals(); ++i)
-                keepOperandAlive(firstBlock, jettisonedBlock, boundaryCodeOrigin, localToOperand(i));
+                keepOperandAlive(firstBlock, jettisonedBlock, boundaryCodeOrigin, virtualRegisterForLocal(i));
         }
         
         for (size_t i = 0; i < secondBlock->phis.size(); ++i)
index 2bde386..5f646f3 100644 (file)
@@ -217,10 +217,10 @@ private:
     void canonicalizeGetLocal(Node* node)
     {
         VariableAccessData* variable = node->variableAccessData();
-        if (operandIsArgument(variable->local()))
-            canonicalizeGetLocalFor<ArgumentOperand>(node, variable, operandToArgument(variable->local()));
+        if (variable->local().isArgument())
+            canonicalizeGetLocalFor<ArgumentOperand>(node, variable, variable->local().toArgument());
         else
-            canonicalizeGetLocalFor<LocalOperand>(node, variable, operandToLocal(variable->local()));
+            canonicalizeGetLocalFor<LocalOperand>(node, variable, variable->local().toLocal());
     }
     
     void canonicalizeSetLocal(Node* node)
@@ -285,17 +285,17 @@ private:
     void canonicalizeFlushOrPhantomLocal(Node* node)
     {
         VariableAccessData* variable = node->variableAccessData();
-        if (operandIsArgument(variable->local()))
-            canonicalizeFlushOrPhantomLocalFor<nodeType, ArgumentOperand>(node, variable, operandToArgument(variable->local()));
+        if (variable->local().isArgument())
+            canonicalizeFlushOrPhantomLocalFor<nodeType, ArgumentOperand>(node, variable, variable->local().toArgument());
         else
-            canonicalizeFlushOrPhantomLocalFor<nodeType, LocalOperand>(node, variable, operandToLocal(variable->local()));
+            canonicalizeFlushOrPhantomLocalFor<nodeType, LocalOperand>(node, variable, variable->local().toLocal());
     }
     
     void canonicalizeSetArgument(Node* node)
     {
-        int local = node->local();
-        ASSERT(operandIsArgument(local));
-        int argument = operandToArgument(local);
+        VirtualRegister local = node->local();
+        ASSERT(local.isArgument());
+        int argument = local.toArgument();
         m_block->variablesAtHead.setArgumentFirstTime(argument, node);
         m_block->variablesAtTail.setArgumentFirstTime(argument, node);
     }
index ea88697..358eabc 100644 (file)
@@ -190,7 +190,7 @@ CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, Instruc
     }
 
     case op_call_varargs:
-        if (codeBlock->usesArguments() && pc[4].u.operand == codeBlock->argumentsRegister())
+        if (codeBlock->usesArguments() && pc[4].u.operand == codeBlock->argumentsRegister().offset())
             return CanInline;
         return CannotCompile;
 
index 274511e..ced2126 100644 (file)
@@ -385,23 +385,7 @@ private:
         
         return changed;
     }
-    
-#if !ASSERT_DISABLED
-    bool isCapturedAtOrAfter(BasicBlock* block, unsigned indexInBlock, int operand)
-    {
-        for (; indexInBlock < block->size(); ++indexInBlock) {
-            Node* node = block->at(indexInBlock);
-            if (!node->hasLocal(m_graph))
-                continue;
-            if (node->local() != operand)
-                continue;
-            if (node->variableAccessData()->isCaptured())
-                return true;
-        }
-        return false;
-    }
-#endif // !ASSERT_DISABLED
-    
+
     void addStructureTransitionCheck(CodeOrigin codeOrigin, unsigned indexInBlock, JSCell* cell)
     {
         Node* weakConstant = m_insertionSet.insertNode(
index 9612d3d..b86fac5 100644 (file)
@@ -167,7 +167,7 @@ private:
         }
     }
     
-    void setForNode(Node* node, int operand, FlushFormat nodeFormat, FlushFormat newFormat)
+    void setForNode(Node* node, VirtualRegister operand, FlushFormat nodeFormat, FlushFormat newFormat)
     {
         FlushFormat& currentFormat = m_live.operand(operand);
         
index 796634a..5a2ddfd 100644 (file)
@@ -234,18 +234,18 @@ void Graph::dump(PrintStream& out, const char* prefix, Node* node, DumpContext*
     ASSERT(node->hasVariableAccessData(*this) == node->hasLocal(*this));
     if (node->hasVariableAccessData(*this)) {
         VariableAccessData* variableAccessData = node->variableAccessData();
-        int operand = variableAccessData->operand();
-        if (operandIsArgument(operand))
-            out.print(comma, "arg", operandToArgument(operand), "(", VariableAccessDataDump(*this, variableAccessData), ")");
+        VirtualRegister operand = variableAccessData->local();
+        if (operand.isArgument())
+            out.print(comma, "arg", operand.toArgument(), "(", VariableAccessDataDump(*this, variableAccessData), ")");
         else
-            out.print(comma, "loc", operandToLocal(operand), "(", VariableAccessDataDump(*this, variableAccessData), ")");
+            out.print(comma, "loc", operand.toLocal(), "(", VariableAccessDataDump(*this, variableAccessData), ")");
     }
     if (node->hasUnlinkedLocal()) {
-        int operand = node->unlinkedLocal();
-        if (operandIsArgument(operand))
-            out.print(comma, "arg", operandToArgument(operand));
+        VirtualRegister operand = node->unlinkedLocal();
+        if (operand.isArgument())
+            out.print(comma, "arg", operand.toArgument());
         else
-            out.print(comma, "loc", operandToLocal(operand));
+            out.print(comma, "loc", operand.toLocal());
     }
     if (node->hasConstantBuffer()) {
         out.print(comma);
index 191bc77..c23faf4 100644 (file)
@@ -429,17 +429,17 @@ public:
         return hasExitSite(node->codeOrigin, exitKind);
     }
     
-    int argumentsRegisterFor(const CodeOrigin& codeOrigin)
+    VirtualRegister argumentsRegisterFor(const CodeOrigin& codeOrigin)
     {
         if (!codeOrigin.inlineCallFrame)
             return m_codeBlock->argumentsRegister();
         
-        return baselineCodeBlockForInlineCallFrame(
-            codeOrigin.inlineCallFrame)->argumentsRegister() +
-            codeOrigin.inlineCallFrame->stackOffset;
+        return VirtualRegister(baselineCodeBlockForInlineCallFrame(
+            codeOrigin.inlineCallFrame)->argumentsRegister().offset() +
+            codeOrigin.inlineCallFrame->stackOffset);
     }
     
-    int uncheckedArgumentsRegisterFor(const CodeOrigin& codeOrigin)
+    VirtualRegister uncheckedArgumentsRegisterFor(const CodeOrigin& codeOrigin)
     {
         if (!codeOrigin.inlineCallFrame)
             return m_codeBlock->uncheckedArgumentsRegister();
@@ -447,13 +447,13 @@ public:
         CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(
             codeOrigin.inlineCallFrame);
         if (!codeBlock->usesArguments())
-            return InvalidVirtualRegister;
+            return VirtualRegister();
         
-        return codeBlock->argumentsRegister() +
-            codeOrigin.inlineCallFrame->stackOffset;
+        return VirtualRegister(codeBlock->argumentsRegister().offset() +
+            codeOrigin.inlineCallFrame->stackOffset);
     }
     
-    int uncheckedActivationRegisterFor(const CodeOrigin&)
+    VirtualRegister uncheckedActivationRegisterFor(const CodeOrigin&)
     {
         // This will ignore CodeOrigin because we don't inline code that uses activations.
         // Hence for inlined call frames it will return the outermost code block's
@@ -472,14 +472,14 @@ public:
         CodeBlock* profiledBlock = baselineCodeBlockFor(node->codeOrigin);
         
         if (node->op() == GetArgument)
-            return profiledBlock->valueProfileForArgument(operandToArgument(node->local()));
+            return profiledBlock->valueProfileForArgument(node->local().toArgument());
         
         if (node->hasLocal(*this)) {
             if (m_form == SSA)
                 return 0;
-            if (!operandIsArgument(node->local()))
+            if (!node->local().isArgument())
                 return 0;
-            int argument = operandToArgument(node->local());
+            int argument = node->local().toArgument();
             if (node->variableAccessData() != m_arguments[argument]->variableAccessData())
                 return 0;
             return profiledBlock->valueProfileForArgument(argument);
index a0db5a4..d1636bc 100644 (file)
@@ -81,7 +81,7 @@ void JITCode::reconstruct(
         int operand = result.operandForIndex(i);
         
         if (operandIsArgument(operand)
-            && !operandToArgument(operand)
+            && !VirtualRegister(operand).toArgument()
             && codeBlock->codeType() == FunctionCode
             && codeBlock->specializationKind() == CodeForConstruct) {
             // Ugh. If we're in a constructor, the 'this' argument may hold garbage. It will
index c8dbb1e..f573364 100644 (file)
@@ -164,7 +164,7 @@ struct Node {
         : codeOrigin(codeOrigin)
         , codeOriginForExitTarget(codeOrigin)
         , children(children)
-        , m_virtualRegister(InvalidVirtualRegister)
+        , m_virtualRegister(VirtualRegister())
         , m_refCount(1)
         , m_prediction(SpecNone)
     {
@@ -177,7 +177,7 @@ struct Node {
         : codeOrigin(codeOrigin)
         , codeOriginForExitTarget(codeOrigin)
         , children(AdjacencyList::Fixed, child1, child2, child3)
-        , m_virtualRegister(InvalidVirtualRegister)
+        , m_virtualRegister(VirtualRegister())
         , m_refCount(1)
         , m_prediction(SpecNone)
     {
@@ -191,7 +191,7 @@ struct Node {
         : codeOrigin(codeOrigin)
         , codeOriginForExitTarget(codeOrigin)
         , children(AdjacencyList::Fixed, child1, child2, child3)
-        , m_virtualRegister(InvalidVirtualRegister)
+        , m_virtualRegister(VirtualRegister())
         , m_refCount(1)
         , m_prediction(SpecNone)
         , m_opInfo(imm.m_value)
@@ -206,7 +206,7 @@ struct Node {
         : codeOrigin(codeOrigin)
         , codeOriginForExitTarget(codeOrigin)
         , children(AdjacencyList::Fixed, child1, child2, child3)
-        , m_virtualRegister(InvalidVirtualRegister)
+        , m_virtualRegister(VirtualRegister())
         , m_refCount(1)
         , m_prediction(SpecNone)
         , m_opInfo(imm1.m_value)
@@ -222,7 +222,7 @@ struct Node {
         : codeOrigin(codeOrigin)
         , codeOriginForExitTarget(codeOrigin)
         , children(AdjacencyList::Variable, firstChild, numChildren)
-        , m_virtualRegister(InvalidVirtualRegister)
+        , m_virtualRegister(VirtualRegister())
         , m_refCount(1)
         , m_prediction(SpecNone)
         , m_opInfo(imm1.m_value)
@@ -390,7 +390,7 @@ struct Node {
     {
         m_op = GetLocalUnlinked;
         m_flags &= ~(NodeMustGenerate | NodeMightClobber | NodeClobbersWorld);
-        m_opInfo = local;
+        m_opInfo = local.offset();
         children.reset();
     }
     
@@ -1057,20 +1057,20 @@ struct Node {
     
     bool hasVirtualRegister()
     {
-        return m_virtualRegister != InvalidVirtualRegister;
+        return m_virtualRegister.isValid();
     }
     
     VirtualRegister virtualRegister()
     {
         ASSERT(hasResult());
-        ASSERT(m_virtualRegister != InvalidVirtualRegister);
+        ASSERT(m_virtualRegister.isValid());
         return m_virtualRegister;
     }
     
     void setVirtualRegister(VirtualRegister virtualRegister)
     {
         ASSERT(hasResult());
-        ASSERT(m_virtualRegister == InvalidVirtualRegister);
+        ASSERT(!m_virtualRegister.isValid());
         m_virtualRegister = virtualRegister;
     }
     
index 599f45a..01ddbc3 100644 (file)
@@ -138,34 +138,35 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn
     }
     
     for (size_t local = 0; local < entry->m_expectedValues.numberOfLocals(); ++local) {
+        int localOffset = virtualRegisterForLocal(local).offset();
         if (entry->m_localsForcedDouble.get(local)) {
-            if (!exec->registers()[localToOperand(local)].jsValue().isNumber()) {
+            if (!exec->registers()[localOffset].jsValue().isNumber()) {
                 if (Options::verboseOSR()) {
                     dataLog(
-                        "    OSR failed because variable ", localToOperand(local), " is ",
-                        exec->registers()[localToOperand(local)].jsValue(), ", expected number.\n");
+                        "    OSR failed because variable ", localOffset, " is ",
+                        exec->registers()[localOffset].jsValue(), ", expected number.\n");
                 }
                 return 0;
             }
             continue;
         }
         if (entry->m_localsForcedMachineInt.get(local)) {
-            if (!exec->registers()[localToOperand(local)].jsValue().isMachineInt()) {
+            if (!exec->registers()[localOffset].jsValue().isMachineInt()) {
                 if (Options::verboseOSR()) {
                     dataLog(
-                        "    OSR failed because variable ", localToOperand(local), " is ",
-                        exec->registers()[localToOperand(local)].jsValue(), ", expected ",
+                        "    OSR failed because variable ", localOffset, " is ",
+                        exec->registers()[localOffset].jsValue(), ", expected ",
                         "machine int.\n");
                 }
                 return 0;
             }
             continue;
         }
-        if (!entry->m_expectedValues.local(local).validate(exec->registers()[localToOperand(local)].jsValue())) {
+        if (!entry->m_expectedValues.local(local).validate(exec->registers()[localOffset].jsValue())) {
             if (Options::verboseOSR()) {
                 dataLog(
-                    "    OSR failed because variable ", localToOperand(local), " is ",
-                    exec->registers()[localToOperand(local)].jsValue(), ", expected ",
+                    "    OSR failed because variable ", localOffset, " is ",
+                    exec->registers()[localOffset].jsValue(), ", expected ",
                     entry->m_expectedValues.local(local), ".\n");
             }
             return 0;
@@ -179,7 +180,7 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn
     //    it seems silly: you'd be diverting the program to error handling when it
     //    would have otherwise just kept running albeit less quickly.
     
-    if (!vm->interpreter->stack().grow(&exec->registers()[localToOperand(codeBlock->m_numCalleeRegisters)])) {
+    if (!vm->interpreter->stack().grow(&exec->registers()[virtualRegisterForLocal(codeBlock->m_numCalleeRegisters).offset()])) {
         if (Options::verboseOSR())
             dataLogF("    OSR failed because stack growth failed.\n");
         return 0;
@@ -191,9 +192,9 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn
     // 3) Perform data format conversions.
     for (size_t local = 0; local < entry->m_expectedValues.numberOfLocals(); ++local) {
         if (entry->m_localsForcedDouble.get(local))
-            *bitwise_cast<double*>(exec->registers() + localToOperand(local)) = exec->registers()[localToOperand(local)].jsValue().asNumber();
+            *bitwise_cast<double*>(exec->registers() + virtualRegisterForLocal(local).offset()) = exec->registers()[virtualRegisterForLocal(local).offset()].jsValue().asNumber();
         if (entry->m_localsForcedMachineInt.get(local))
-            *bitwise_cast<int64_t*>(exec->registers() + localToOperand(local)) = exec->registers()[localToOperand(local)].jsValue().asMachineInt() << JSValue::int52ShiftAmount;
+            *bitwise_cast<int64_t*>(exec->registers() + virtualRegisterForLocal(local).offset()) = exec->registers()[virtualRegisterForLocal(local).offset()].jsValue().asMachineInt() << JSValue::int52ShiftAmount;
     }
     
     // 4) Fix the call frame.
index ef4f4bc..f98cfe8 100644 (file)
@@ -101,7 +101,7 @@ public:
             VariableAccessData* variable = previousHead->variableAccessData();
             Node* node = newRoot->appendNode(
                 m_graph, variable->prediction(), ExtractOSREntryLocal, codeOrigin,
-                OpInfo(variable->local()));
+                OpInfo(variable->local().offset()));
             newRoot->appendNode(
                 m_graph, SpecNone, SetLocal, codeOrigin, OpInfo(variable), Edge(node));
         }
index 19ee504..e3f2199 100644 (file)
@@ -106,7 +106,7 @@ struct OSRExit : public OSRExitBase {
     void convertToForward(BasicBlock*, Node*, unsigned nodeIndex, const ValueRecovery&);
 
     unsigned m_streamIndex;
-    int m_lastSetOperand;
+    VirtualRegister m_lastSetOperand;
     
     RefPtr<ValueRecoveryOverride> m_valueRecoveryOverride;
 };
index f25ad24..35354cd 100644 (file)
@@ -201,7 +201,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
         case CellDisplacedInJSStack:
         case BooleanDisplacedInJSStack: {
             numberOfDisplacedVirtualRegisters++;
-            ASSERT(operandIsLocal(recovery.virtualRegister()));
+            ASSERT(recovery.virtualRegister().isLocal());
             
             // See if we might like to store to this virtual register before doing
             // virtual register shuffling. If so, we say that the virtual register
@@ -210,7 +210,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
             // to ensure this happens efficiently. Note that we expect this case
             // to be rare, so the handling of it is optimized for the cases in
             // which it does not happen.
-            int local = operandToLocal(recovery.virtualRegister());
+            int local = recovery.virtualRegister().toLocal();
             if (local < (int)operands.numberOfLocals()) {
                 switch (operands.local(local).technique()) {
                 case InGPR:
@@ -535,17 +535,19 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
     // 9) Dump all poisoned virtual registers.
     
     if (numberOfPoisonedVirtualRegisters) {
-        for (int virtualRegister = 0; virtualRegister < (int)operands.numberOfLocals(); ++virtualRegister) {
-            if (!poisonedVirtualRegisters[virtualRegister])
+        for (int localIndex = 0; localIndex < (int)operands.numberOfLocals(); ++localIndex) {
+            if (!poisonedVirtualRegisters[localIndex])
                 continue;
             
-            const ValueRecovery& recovery = operands.local(virtualRegister);
+            VirtualRegister virtualRegister = virtualRegisterForLocal(localIndex);
+
+            const ValueRecovery& recovery = operands.local(localIndex);
             switch (recovery.technique()) {
             case InGPR:
             case UnboxedInt32InGPR:
             case UnboxedBooleanInGPR: {
-                m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + poisonIndex(virtualRegister)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
-                m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)localToOperand(virtualRegister)));
+                m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + poisonIndex(localIndex)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+                m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor(virtualRegister));
                 uint32_t tag = JSValue::EmptyValueTag;
                 if (recovery.technique() == InGPR)
                     tag = JSValue::CellTag;
@@ -553,17 +555,17 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
                     tag = JSValue::Int32Tag;
                 else
                     tag = JSValue::BooleanTag;
-                m_jit.store32(AssemblyHelpers::TrustedImm32(tag), AssemblyHelpers::tagFor((VirtualRegister)localToOperand(virtualRegister)));
+                m_jit.store32(AssemblyHelpers::TrustedImm32(tag), AssemblyHelpers::tagFor(virtualRegister));
                 break;
             }
 
             case InFPR:
             case InPair:
             case UInt32InGPR:
-                m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + poisonIndex(virtualRegister)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
-                m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + poisonIndex(virtualRegister)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag), GPRInfo::regT1);
-                m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)localToOperand(virtualRegister)));
-                m_jit.store32(GPRInfo::regT1, AssemblyHelpers::tagFor((VirtualRegister)localToOperand(virtualRegister)));
+                m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + poisonIndex(localIndex)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+                m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + poisonIndex(localIndex)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag), GPRInfo::regT1);
+                m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor(virtualRegister));
+                m_jit.store32(GPRInfo::regT1, AssemblyHelpers::tagFor(virtualRegister));
                 break;
                 
             default:
@@ -706,9 +708,9 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
     
     // 15) Load the result of the last bytecode operation into regT0.
     
-    if (exit.m_lastSetOperand != std::numeric_limits<int>::max()) {
-        m_jit.load32(AssemblyHelpers::payloadFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
-        m_jit.load32(AssemblyHelpers::tagFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister2);
+    if (exit.m_lastSetOperand.isValid()) {
+        m_jit.load32(AssemblyHelpers::payloadFor(exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
+        m_jit.load32(AssemblyHelpers::tagFor(exit.m_lastSetOperand), GPRInfo::cachedResultRegister2);
     }
     
     // 16) And finish.
index 523ac38..74d2b98 100644 (file)
@@ -31,6 +31,8 @@
 #include "DFGOperations.h"
 #include "DFGOSRExitCompilerCommon.h"
 #include "Operations.h"
+#include "VirtualRegister.h"
+
 #include <wtf/DataLog.h>
 
 namespace JSC { namespace DFG {
@@ -394,7 +396,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
 
             if (!m_jit.baselineCodeBlockFor(inlineCallFrame)->usesArguments())
                 continue;
-            int argumentsRegister = m_jit.argumentsRegisterFor(inlineCallFrame);
+            VirtualRegister argumentsRegister = m_jit.argumentsRegisterFor(inlineCallFrame);
             if (didCreateArgumentsObject.add(inlineCallFrame).isNewEntry) {
                 // We know this call frame optimized out an arguments object that
                 // the baseline JIT would have created. Do that creation now.
@@ -422,7 +424,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, const Operands<ValueRecov
     
     // 10) Load the result of the last bytecode operation into regT0.
     
-    if (exit.m_lastSetOperand != std::numeric_limits<int>::max())
+    if (exit.m_lastSetOperand.isValid())
         m_jit.load64(AssemblyHelpers::addressFor(exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
     
     // 11) And finish.
index 0dbaec4..ffa822a 100644 (file)
@@ -85,10 +85,10 @@ public:
     // returns -1 (InvalidGPRReg or InvalidFPRReg).
     RegID tryAllocate()
     {
-        VirtualRegister ignored;
+        VirtualRegister ignored = VirtualRegister();
         
         for (uint32_t i = 0; i < NUM_REGS; ++i) {
-            if (!m_data[i].lockCount && m_data[i].name == InvalidVirtualRegister)
+            if (!m_data[i].lockCount && !m_data[i].name.isValid())
                 return allocateInternal(i, ignored);
         }
         
@@ -147,7 +147,7 @@ public:
 
         ++m_data[index].lockCount;
         VirtualRegister name = nameAtIndex(index);
-        if (name != InvalidVirtualRegister)
+        if (name.isValid())
             releaseAtIndex(index);
         
         return name;
@@ -165,8 +165,8 @@ public:
         ASSERT(index < NUM_REGS);
         ASSERT(m_data[index].lockCount);
         // 'index' should not currently be named, the new name must be valid.
-        ASSERT(m_data[index].name == InvalidVirtualRegister);
-        ASSERT(name != InvalidVirtualRegister);
+        ASSERT(!m_data[index].name.isValid());
+        ASSERT(name.isValid());
         // 'index' should not currently have a spillOrder.
         ASSERT(m_data[index].spillOrder == SpillHintInvalid);
 
@@ -201,7 +201,7 @@ public:
     }
 
     // Get the name (VirtualRegister) associated with the
-    // given register (or InvalidVirtualRegister for none).
+    // given register (or default VirtualRegister() for none).
     VirtualRegister name(RegID reg) const
     {
         return nameAtIndex(BankInfo::toIndex(reg));
@@ -209,7 +209,7 @@ public:
     
     bool isInUse(RegID reg) const
     {
-        return isLocked(reg) || name(reg) != InvalidVirtualRegister;
+        return isLocked(reg) || name(reg).isValid();
     }
     
 #ifndef NDEBUG
@@ -217,8 +217,8 @@ public:
     {
         // For each register, print the VirtualRegister 'name'.
         for (uint32_t i =0; i < NUM_REGS; ++i) {
-            if (m_data[i].name != InvalidVirtualRegister)
-                dataLogF("[%02d]", m_data[i].name);
+            if (m_data[i].name.isValid())
+                dataLogF("[%02d]", m_data[i].name.offset());
             else
                 dataLogF("[--]");
         }
@@ -312,11 +312,11 @@ private:
         // 'index' must be a valid register.
         ASSERT(index < NUM_REGS);
         // 'index' should currently be named.
-        ASSERT(m_data[index].name != InvalidVirtualRegister);
+        ASSERT(m_data[index].name.isValid());
         // 'index' should currently have a valid spill order.
         ASSERT(m_data[index].spillOrder != SpillHintInvalid);
 
-        m_data[index].name = InvalidVirtualRegister;
+        m_data[index].name = VirtualRegister();
         m_data[index].spillOrder = SpillHintInvalid;
     }
 
@@ -327,7 +327,7 @@ private:
         ASSERT(i < NUM_REGS && !m_data[i].lockCount);
 
         // Return the VirtualRegister of the named value currently stored in
-        // the register being returned - or InvalidVirtualRegister if none.
+        // the register being returned - or default VirtualRegister() if none.
         spillMe = m_data[i].name;
 
         // Clear any name/spillOrder currently associated with the register,
@@ -345,7 +345,7 @@ private:
     // count, name and spillOrder hint.
     struct MapEntry {
         MapEntry()
-            : name(InvalidVirtualRegister)
+            : name(VirtualRegister())
             , spillOrder(SpillHintInvalid)
             , lockCount(0)
         {
index f0c17e5..0f24f4e 100644 (file)
@@ -89,14 +89,14 @@ public:
             // Use count must have hit zero for it to have been added to the free list!
             ASSERT(!m_used[index]);
             m_highWatermark = std::max(m_highWatermark, static_cast<unsigned>(index) + 1);
-            return (VirtualRegister)localToOperand(index);
+            return virtualRegisterForLocal(index);
         }
 
         // Allocate a new VirtualRegister, and add a corresponding entry to m_used.
         size_t next = m_used.size();
         m_used.append(0);
         m_highWatermark = std::max(m_highWatermark, static_cast<unsigned>(next) + 1);
-        return (VirtualRegister)localToOperand(next);
+        return virtualRegisterForLocal(next);
     }
 
     // Increment the usecount for the VirtualRegister associated with 'child',
@@ -107,7 +107,7 @@ public:
             return;
 
         // Find the virtual register number for this child, increment its use count.
-        uint32_t index = operandToLocal(child->virtualRegister());
+        uint32_t index = child->virtualRegister().toLocal();
         ASSERT(m_used[index] != max());
         if (child->refCount() == ++m_used[index]) {
 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
index bf3f6fb..f3775e8 100644 (file)
@@ -48,7 +48,7 @@ SpeculativeJIT::SpeculativeJIT(JITCompiler& jit)
     , m_generationInfo(m_jit.codeBlock()->m_numCalleeRegisters)
     , m_arguments(jit.codeBlock()->numParameters())
     , m_variables(jit.graph().m_localVars)
-    , m_lastSetOperand(std::numeric_limits<int>::max())
+    , m_lastSetOperand(VirtualRegister())
     , m_state(m_jit.graph())
     , m_interpreter(m_jit.graph(), m_state)
     , m_stream(&jit.jitCode()->variableEventStream)
@@ -1183,7 +1183,7 @@ void SpeculativeJIT::checkConsistency()
 
     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
         VirtualRegister virtualRegister = iter.name();
-        if (virtualRegister == InvalidVirtualRegister)
+        if (!virtualRegister.isValid())
             continue;
 
         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
@@ -1209,7 +1209,7 @@ void SpeculativeJIT::checkConsistency()
 
     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
         VirtualRegister virtualRegister = iter.name();
-        if (virtualRegister == InvalidVirtualRegister)
+        if (!virtualRegister.isValid())
             continue;
 
         GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
@@ -1538,7 +1538,7 @@ void SpeculativeJIT::compileMovHint(Node* node)
     if (child->op() == UInt32ToNumber)
         noticeOSRBirth(child->child1().node());
     
-    m_stream->appendAndLog(VariableEvent::movHint(MinifiedID(child), node->local()));
+    m_stream->appendAndLog(VariableEvent::movHint(MinifiedID(child), node->local().offset()));
 }
 
 void SpeculativeJIT::compileMovHintAndCheck(Node* node)
@@ -1556,7 +1556,7 @@ void SpeculativeJIT::compileInlineStart(Node* node)
     CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
     for (int i = 0; i < argumentCountIncludingThis; ++i) {
         ValueRecovery recovery;
-        if (codeBlock->isCaptured(argumentToOperand(i)))
+        if (codeBlock->isCaptured(virtualRegisterForArgument(i)))
             recovery = ValueRecovery::alreadyInJSStack();
         else {
             ArgumentPosition& argumentPosition =
@@ -1639,7 +1639,7 @@ void SpeculativeJIT::compileCurrentBlock()
     for (size_t i = 0; i < m_arguments.size(); ++i) {
         ValueSource valueSource = ValueSource(ValueInJSStack);
         m_arguments[i] = valueSource;
-        m_stream->appendAndLog(VariableEvent::setLocal(argumentToOperand(i), valueSource.dataFormat()));
+        m_stream->appendAndLog(VariableEvent::setLocal(virtualRegisterForArgument(i), valueSource.dataFormat()));
     }
     
     m_state.reset();
@@ -1659,10 +1659,10 @@ void SpeculativeJIT::compileCurrentBlock()
             valueSource = ValueSource::forFlushFormat(node->variableAccessData()->flushFormat());
         m_variables[i] = valueSource;
         // FIXME: Don't emit SetLocal(Dead). https://bugs.webkit.org/show_bug.cgi?id=108019
-        m_stream->appendAndLog(VariableEvent::setLocal(localToOperand(i), valueSource.dataFormat()));
+        m_stream->appendAndLog(VariableEvent::setLocal(virtualRegisterForLocal(i), valueSource.dataFormat()));
     }
     
-    m_lastSetOperand = std::numeric_limits<int>::max();
+    m_lastSetOperand = VirtualRegister();
     m_codeOriginForExitTarget = CodeOrigin();
     m_codeOriginForExitProfile = CodeOrigin();
     
index 4ab5404..8c4b29b 100644 (file)
@@ -41,6 +41,7 @@
 #include "DFGValueSource.h"
 #include "MarkedAllocator.h"
 #include "ValueRecovery.h"
+#include "VirtualRegister.h"
 
 namespace JSC { namespace DFG {
 
@@ -184,7 +185,7 @@ public:
 #endif
         VirtualRegister spillMe;
         GPRReg gpr = m_gprs.allocate(spillMe);
-        if (spillMe != InvalidVirtualRegister) {
+        if (spillMe.isValid()) {
 #if USE(JSVALUE32_64)
             GenerationInfo& info = generationInfoFromVirtualRegister(spillMe);
             RELEASE_ASSERT(info.registerFormat() != DataFormatJSDouble);
@@ -201,7 +202,7 @@ public:
         m_jit.addRegisterAllocationAtOffset(m_jit.debugOffset());
 #endif
         VirtualRegister spillMe = m_gprs.allocateSpecific(specific);
-        if (spillMe != InvalidVirtualRegister) {
+        if (spillMe.isValid()) {
 #if USE(JSVALUE32_64)
             GenerationInfo& info = generationInfoFromVirtualRegister(spillMe);
             RELEASE_ASSERT(info.registerFormat() != DataFormatJSDouble);
@@ -223,7 +224,7 @@ public:
 #endif
         VirtualRegister spillMe;
         FPRReg fpr = m_fprs.allocate(spillMe);
-        if (spillMe != InvalidVirtualRegister)
+        if (spillMe.isValid())
             spill(spillMe);
         return fpr;
     }
@@ -360,7 +361,7 @@ public:
         ASSERT(plans.isEmpty());
         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
             GPRReg gpr = iter.regID();
-            if (iter.name() != InvalidVirtualRegister && gpr != exclude && gpr != exclude2) {
+            if (iter.name().isValid() && gpr != exclude && gpr != exclude2) {
                 SilentRegisterSavePlan plan = silentSavePlanForGPR(iter.name(), gpr);
                 if (doSpill)
                     silentSpill(plan);
@@ -368,7 +369,7 @@ public:
             }
         }
         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
-            if (iter.name() != InvalidVirtualRegister && iter.regID() != fprExclude) {
+            if (iter.name().isValid() && iter.regID() != fprExclude) {
                 SilentRegisterSavePlan plan = silentSavePlanForFPR(iter.name(), iter.regID());
                 if (doSpill)
                     silentSpill(plan);
@@ -601,13 +602,13 @@ public:
     void flushRegisters()
     {
         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
-            if (iter.name() != InvalidVirtualRegister) {
+            if (iter.name().isValid()) {
                 spill(iter.name());
                 iter.release();
             }
         }
         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
-            if (iter.name() != InvalidVirtualRegister) {
+            if (iter.name().isValid()) {
                 spill(iter.name());
                 iter.release();
             }
@@ -620,11 +621,11 @@ public:
     bool isFlushed()
     {
         for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
-            if (iter.name() != InvalidVirtualRegister)
+            if (iter.name().isValid())
                 return false;
         }
         for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
-            if (iter.name() != InvalidVirtualRegister)
+            if (iter.name().isValid())
                 return false;
         }
         return true;
@@ -759,7 +760,7 @@ public:
     // Access to our fixed callee CallFrame.
     MacroAssembler::Address argumentSlot(int argument)
     {
-        return MacroAssembler::Address(GPRInfo::callFrameRegister, (-m_jit.codeBlock()->m_numCalleeRegisters + argumentToOperand(argument)) * static_cast<int>(sizeof(Register)));
+        return MacroAssembler::Address(GPRInfo::callFrameRegister, (-m_jit.codeBlock()->m_numCalleeRegisters + virtualRegisterForArgument(argument).offset()) * static_cast<int>(sizeof(Register)));
     }
 
     MacroAssembler::Address callFrameTagSlot(int slot)
@@ -774,12 +775,12 @@ public:
 
     MacroAssembler::Address argumentTagSlot(int argument)
     {
-        return MacroAssembler::Address(GPRInfo::callFrameRegister, (-m_jit.codeBlock()->m_numCalleeRegisters + argumentToOperand(argument)) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+        return MacroAssembler::Address(GPRInfo::callFrameRegister, (-m_jit.codeBlock()->m_numCalleeRegisters + virtualRegisterForArgument(argument).offset()) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
     }
 
     MacroAssembler::Address argumentPayloadSlot(int argument)
     {
-        return MacroAssembler::Address(GPRInfo::callFrameRegister, (-m_jit.codeBlock()->m_numCalleeRegisters + argumentToOperand(argument)) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+        return MacroAssembler::Address(GPRInfo::callFrameRegister, (-m_jit.codeBlock()->m_numCalleeRegisters + virtualRegisterForArgument(argument).offset()) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
     }
 
     void emitCall(Node*);
@@ -2188,12 +2189,12 @@ public:
     // Tracking for which nodes are currently holding the values of arguments and bytecode
     // operand-indexed variables.
     
-    ValueSource valueSourceForOperand(int operand)
+    ValueSource valueSourceForOperand(VirtualRegister operand)
     {
         return valueSourceReferenceForOperand(operand);
     }
     
-    void setNodeForOperand(Node* node, int operand)
+    void setNodeForOperand(Node* node, VirtualRegister operand)
     {
         valueSourceReferenceForOperand(operand) = ValueSource(MinifiedID(node));
     }
@@ -2202,21 +2203,21 @@ public:
     // and potentially resizes the array. So it would not be right to call this
     // twice and then perform operands on both references, since the one from
     // the first call may no longer be valid.
-    ValueSource& valueSourceReferenceForOperand(int operand)
+    ValueSource& valueSourceReferenceForOperand(VirtualRegister operand)
     {
-        if (operandIsArgument(operand)) {
-            int argument = operandToArgument(operand);
+        if (operand.isArgument()) {
+            int argument = operand.toArgument();
             return m_arguments[argument];
         }
 
-        int local = operandToLocal(operand);
+        int local = operand.toLocal();
         if ((unsigned)local >= m_variables.size())
             m_variables.resize(local + 1);
         
         return m_variables[local];
     }
     
-    void recordSetLocal(int operand, ValueSource valueSource)
+    void recordSetLocal(VirtualRegister operand, ValueSource valueSource)
     {
         valueSourceReferenceForOperand(operand) = valueSource;
         m_stream->appendAndLog(VariableEvent::setLocal(operand, valueSource.dataFormat()));
@@ -2224,7 +2225,7 @@ public:
 
     GenerationInfo& generationInfoFromVirtualRegister(VirtualRegister virtualRegister)
     {
-        return m_generationInfo[operandToLocal(virtualRegister)];
+        return m_generationInfo[virtualRegister.toLocal()];
     }
     
     GenerationInfo& generationInfo(Node* node)
@@ -2267,7 +2268,7 @@ public:
 
     Vector<ValueSource, 0> m_arguments;
     Vector<ValueSource, 0> m_variables;
-    int m_lastSetOperand;
+    VirtualRegister m_lastSetOperand;
     CodeOrigin m_codeOriginForExitTarget;
     CodeOrigin m_codeOriginForExitProfile;
     
@@ -2286,7 +2287,7 @@ public:
 
     ValueRecovery computeValueRecoveryFor(int operand)
     {
-        return computeValueRecoveryFor(valueSourceForOperand(operand));
+        return computeValueRecoveryFor(valueSourceForOperand(VirtualRegister(operand)));
     }
 };
 
index 538f58a..2661826 100644 (file)
@@ -4780,7 +4780,7 @@ void SpeculativeJIT::compile(Node* node)
         addSlowPathGenerator(
             slowPathCall(
                 created, this, operationGetArgumentsLength, resultGPR,
-                m_jit.argumentsRegisterFor(node->codeOrigin)));
+                m_jit.argumentsRegisterFor(node->codeOrigin).offset()));
         
         jsValueResult(resultGPR, node);
         break;
@@ -4919,14 +4919,14 @@ void SpeculativeJIT::compile(Node* node)
             addSlowPathGenerator(
                 slowPathCall(
                     slowPath, this, operationGetInlinedArgumentByVal, resultGPR, 
-                    m_jit.argumentsRegisterFor(node->codeOrigin),
+                    m_jit.argumentsRegisterFor(node->codeOrigin).offset(),
                     node->codeOrigin.inlineCallFrame,
                     indexGPR));
         } else {
             addSlowPathGenerator(
                 slowPathCall(
                     slowPath, this, operationGetArgumentByVal, resultGPR, 
-                    m_jit.argumentsRegisterFor(node->codeOrigin),
+                    m_jit.argumentsRegisterFor(node->codeOrigin).offset(),
                     indexGPR));
         }
         
index 88bfdd4..b946e46 100644 (file)
@@ -78,7 +78,7 @@ public:
         // Validate that all local variables at the head of the root block are dead.
         BasicBlock* root = m_graph.block(0);
         for (unsigned i = 0; i < root->variablesAtHead.numberOfLocals(); ++i)
-            V_EQUAL((static_cast<VirtualRegister>(localToOperand(i)), 0), static_cast<Node*>(0), root->variablesAtHead.local(i));
+            V_EQUAL((virtualRegisterForLocal(i), 0), static_cast<Node*>(0), root->variablesAtHead.local(i));
         
         // Validate ref counts and uses.
         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
@@ -317,17 +317,17 @@ private:
                 block->variablesAtHead.numberOfLocals());
             
             for (size_t i = 0; i < block->variablesAtHead.numberOfArguments(); ++i) {
-                VALIDATE((static_cast<VirtualRegister>(argumentToOperand(i)), block), !block->variablesAtHead.argument(i) || block->variablesAtHead.argument(i)->hasVariableAccessData(m_graph));
+                VALIDATE((virtualRegisterForArgument(i), block), !block->variablesAtHead.argument(i) || block->variablesAtHead.argument(i)->hasVariableAccessData(m_graph));
                 if (m_graph.m_form == ThreadedCPS)
-                    VALIDATE((static_cast<VirtualRegister>(argumentToOperand(i)), block), !block->variablesAtTail.argument(i) || block->variablesAtTail.argument(i)->hasVariableAccessData(m_graph));
+                    VALIDATE((virtualRegisterForArgument(i), block), !block->variablesAtTail.argument(i) || block->variablesAtTail.argument(i)->hasVariableAccessData(m_graph));
                 
                 getLocalPositions.argument(i) = notSet;
                 setLocalPositions.argument(i) = notSet;
             }
             for (size_t i = 0; i < block->variablesAtHead.numberOfLocals(); ++i) {
-                VALIDATE((static_cast<VirtualRegister>(localToOperand(i)), block), !block->variablesAtHead.local(i) || block->variablesAtHead.local(i)->hasVariableAccessData(m_graph));
+                VALIDATE((virtualRegisterForLocal(i), block), !block->variablesAtHead.local(i) || block->variablesAtHead.local(i)->hasVariableAccessData(m_graph));
                 if (m_graph.m_form == ThreadedCPS)
-                    VALIDATE((static_cast<VirtualRegister>(localToOperand(i)), block), !block->variablesAtTail.local(i) || block->variablesAtTail.local(i)->hasVariableAccessData(m_graph));
+                    VALIDATE((virtualRegisterForLocal(i), block), !block->variablesAtTail.local(i) || block->variablesAtTail.local(i)->hasVariableAccessData(m_graph));
 
                 getLocalPositions.local(i) = notSet;
                 setLocalPositions.local(i) = notSet;
@@ -389,18 +389,18 @@ private:
             
             for (size_t i = 0; i < block->variablesAtHead.numberOfArguments(); ++i) {
                 checkOperand(
-                    block, getLocalPositions, setLocalPositions, argumentToOperand(i));
+                    block, getLocalPositions, setLocalPositions, virtualRegisterForArgument(i));
             }
             for (size_t i = 0; i < block->variablesAtHead.numberOfLocals(); ++i) {
                 checkOperand(
-                    block, getLocalPositions, setLocalPositions, localToOperand(i));
+                    block, getLocalPositions, setLocalPositions, virtualRegisterForLocal(i));
             }
         }
     }
     
     void checkOperand(
         BasicBlock* block, Operands<size_t>& getLocalPositions,
-        Operands<size_t>& setLocalPositions, int operand)
+        Operands<size_t>& setLocalPositions, VirtualRegister operand)
     {
         if (getLocalPositions.operand(operand) == notSet)
             return;
@@ -432,23 +432,23 @@ private:
     void reportValidationContext(VirtualRegister local, BasicBlock* block)
     {
         if (!block) {
-            dataLog("r", static_cast<int>(local), " in null Block ");
+            dataLog("r", local, " in null Block ");
             return;
         }
 
-        dataLog("r", static_cast<int>(local), " in Block ", *block);
+        dataLog("r", local, " in Block ", *block);
     }
     
     void reportValidationContext(
         VirtualRegister local, BasicBlock* sourceBlock, BasicBlock* destinationBlock)
     {
-        dataLog("r", static_cast<int>(local), " in Block ", *sourceBlock, " -> ", *destinationBlock);
+        dataLog("r", local, " in Block ", *sourceBlock, " -> ", *destinationBlock);
     }
     
     void reportValidationContext(
         VirtualRegister local, BasicBlock* sourceBlock, Node* prevNode)
     {
-        dataLog(prevNode, " for r", static_cast<int>(local), " in Block ", *sourceBlock);
+        dataLog(prevNode, " for r", local, " in Block ", *sourceBlock);
     }
     
     void reportValidationContext(Node* node, BasicBlock* block)
index 317111a..89de9fd 100644 (file)
@@ -39,13 +39,13 @@ class ValueRecoveryOverride : public RefCounted<ValueRecoveryOverride> {
 public:
     ValueRecoveryOverride() { }
     
-    ValueRecoveryOverride(int operand, const ValueRecovery& recovery)
+    ValueRecoveryOverride(VirtualRegister operand, const ValueRecovery& recovery)
         : operand(operand)
         , recovery(recovery)
     {
     }
     
-    int operand;
+    VirtualRegister operand;
     ValueRecovery recovery;
 };
 
index 3e68f44..07aa54f 100644 (file)
@@ -80,12 +80,7 @@ public:
         ASSERT(m_local == find()->m_local);
         return m_local;
     }
-    
-    int operand()
-    {
-        return static_cast<int>(local());
-    }
-    
+
     bool mergeIsCaptured(bool isCaptured)
     {
         return checkAndSet(m_shouldNeverUnbox, m_shouldNeverUnbox | isCaptured)
@@ -230,7 +225,7 @@ public:
     {
         // We don't support this facility for arguments, yet.
         // FIXME: make this work for arguments.
-        if (operandIsArgument(operand()))
+        if (local().isArgument())
             return false;
         
         // If the variable is not a number prediction, then this doesn't
@@ -278,7 +273,7 @@ public:
     {
         ASSERT(isRoot());
         
-        if (operandIsArgument(local()) || shouldNeverUnbox())
+        if (local().isArgument() || shouldNeverUnbox())
             return DFG::mergeDoubleFormatState(m_doubleFormatState, NotUsingDoubleFormat);
         
         if (m_doubleFormatState == CantUseDoubleFormat)
@@ -333,7 +328,7 @@ public:
         if (isInt32Speculation(prediction))
             return FlushedInt32;
         
-        if (enableInt52() && !operandIsArgument(m_local) && isMachineIntSpeculation(prediction))
+        if (enableInt52() && !m_local.isArgument() && isMachineIntSpeculation(prediction))
             return FlushedInt52;
         
         if (isCellSpeculation(prediction))
index 1605f79..73ea4a2 100644 (file)
@@ -141,7 +141,7 @@ public:
         ASSERT(kind == BirthToSpill || kind == Spill);
         VariableEvent event;
         event.m_id = id;
-        event.u.virtualReg = virtualRegister;
+        event.u.virtualReg = virtualRegister.offset();
         event.m_kind = kind;
         event.m_dataFormat = format;
         return event;
@@ -155,10 +155,10 @@ public:
         return event;
     }
     
-    static VariableEvent setLocal(int operand, DataFormat format)
+    static VariableEvent setLocal(VirtualRegister virtualRegister, DataFormat format)
     {
         VariableEvent event;
-        event.u.virtualReg = operand;
+        event.u.virtualReg = virtualRegister.offset();
         event.m_kind = SetLocalEvent;
         event.m_dataFormat = format;
         return event;
index 391827f..09e7d53 100644 (file)
@@ -115,7 +115,7 @@ void VariableEventStream::reconstruct(
     
     unsigned numVariables;
     if (codeOrigin.inlineCallFrame)
-        numVariables = baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame)->m_numCalleeRegisters + operandToLocal(codeOrigin.inlineCallFrame->stackOffset);
+        numVariables = baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame)->m_numCalleeRegisters + VirtualRegister(codeOrigin.inlineCallFrame->stackOffset).toLocal();
     else
         numVariables = baselineCodeBlock->m_numCalleeRegisters;
     
@@ -283,7 +283,7 @@ void VariableEventStream::reconstruct(
     // that those values don't have to be recovered. Signal this by using ValueRecovery::alreadyInJSStack()
     for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->caller.inlineCallFrame) {
         for (unsigned i = JSStack::CallFrameHeaderSize; i--;)
-            valueRecoveries.setLocal(operandToLocal(inlineCallFrame->stackOffset) - i - 1, ValueRecovery::alreadyInJSStack());
+            valueRecoveries.setLocal(VirtualRegister(inlineCallFrame->stackOffset).toLocal() - i - 1, ValueRecovery::alreadyInJSStack());
     }
 }
 
index 446e060..b2d7a77 100644 (file)
@@ -126,7 +126,7 @@ public:
         for (size_t i = 0; i < inlineCallFrameCount; i++) {
             InlineCallFrame* inlineCallFrame = m_graph.m_inlineCallFrames->at(i);
             CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
-            unsigned requiredCalleeRegisters = operandToLocal(inlineCallFrame->stackOffset) + codeBlock->m_numCalleeRegisters;
+            unsigned requiredCalleeRegisters = VirtualRegister(inlineCallFrame->stackOffset).toLocal() + codeBlock->m_numCalleeRegisters;
             if (requiredCalleeRegisters > calleeRegisters)
                 calleeRegisters = requiredCalleeRegisters;
         }
index 3cb1255..a5ec737 100644 (file)
@@ -38,11 +38,11 @@ namespace JSC { namespace FTL {
 class ExitArgumentForOperand {
 public:
     ExitArgumentForOperand()
-        : m_operand(InvalidVirtualRegister)
+        : m_operand(VirtualRegister())
     {
     }
     
-    ExitArgumentForOperand(ExitArgument exitArgument, int operand)
+    ExitArgumentForOperand(ExitArgument exitArgument, VirtualRegister operand)
         : m_exitArgument(exitArgument)
         , m_operand(operand)
     {
@@ -51,13 +51,13 @@ public:
     bool operator!() const { return !m_exitArgument; }
     
     const ExitArgument& exitArgument() const { return m_exitArgument; }
-    int operand() const { return m_operand; }
+    VirtualRegister operand() const { return m_operand; }
     
     void dump(PrintStream&) const;
     
 private:
     ExitArgument m_exitArgument;
-    int m_operand;
+    VirtualRegister m_operand;
 };
 
 inline bool lesserArgumentIndex(
index cc40099..bc37b74 100644 (file)
@@ -35,6 +35,7 @@
 #include "FTLJITCode.h"
 #include "JITStubs.h"
 #include "LinkBuffer.h"
+#include "VirtualRegister.h"
 #include <wtf/LLVMHeaders.h>
 
 namespace JSC { namespace FTL {
@@ -75,7 +76,7 @@ void link(State& state)
         // Plant a check that sufficient space is available in the JSStack.
         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291
         jit.addPtr(
-            CCallHelpers::TrustedImm32(localToOperand(codeBlock->m_numCalleeRegisters) * sizeof(Register)),
+            CCallHelpers::TrustedImm32(virtualRegisterForLocal(codeBlock->m_numCalleeRegisters).offset() * sizeof(Register)),
             GPRInfo::callFrameRegister, GPRInfo::regT1);
         CCallHelpers::Jump stackCheck = jit.branchPtr(
             CCallHelpers::Above,
index 8a3b204..2396287 100644 (file)
@@ -42,6 +42,8 @@
 #include "LinkBuffer.h"
 #include "OperandsInlines.h"
 #include "Operations.h"
+#include "VirtualRegister.h"
+
 #include <wtf/ProcessID.h>
 
 namespace JSC { namespace FTL {
@@ -69,7 +71,7 @@ public:
         , m_heaps(state.context)
         , m_out(state.context)
         , m_valueSources(OperandsLike, state.graph.block(0)->variablesAtHead)
-        , m_lastSetOperand(std::numeric_limits<int>::max())
+        , m_lastSetOperand(VirtualRegister())
         , m_exitThunkGenerator(state)
         , m_state(state.graph)
         , m_interpreter(state.graph, m_state)
@@ -524,7 +526,7 @@ private:
     void compileGetArgument()
     {
         VariableAccessData* variable = m_node->variableAccessData();
-        int operand = variable->operand();
+        VirtualRegister operand = variable->local();
 
         LValue jsValue = m_out.load64(addressFor(operand));
 
@@ -554,7 +556,7 @@ private:
     {
         EncodedJSValue* buffer = static_cast<EncodedJSValue*>(
             m_ftlState.jitCode->ftlForOSREntry()->entryBuffer()->dataBuffer());
-        setJSValue(m_out.load64(m_out.absolute(buffer + operandToLocal(m_node->unlinkedLocal()))));
+        setJSValue(m_out.load64(m_out.absolute(buffer + m_node->unlinkedLocal().toLocal())));
     }
     
     void compileGetLocal()
@@ -2003,7 +2005,7 @@ private:
         
         LValue calleeFrame = m_out.add(
             m_callFrame,
-            m_out.constIntPtr(sizeof(Register) * localToOperand(codeBlock()->m_numCalleeRegisters)));
+            m_out.constIntPtr(sizeof(Register) * virtualRegisterForLocal(codeBlock()->m_numCalleeRegisters).offset()));
         
         m_out.store32(
             m_out.constInt32(numPassedArgs + dummyThisArgument),
@@ -2016,7 +2018,7 @@ private:
         for (int i = 0; i < numPassedArgs; ++i) {
             m_out.store64(
                 lowJSValue(m_graph.varArgChild(m_node, 1 + i)),
-                addressFor(calleeFrame, argumentToOperand(i + dummyThisArgument)));
+                addressFor(calleeFrame, virtualRegisterForArgument(i + dummyThisArgument).offset()));
         }
         
         setJSValue(vmCall(m_out.operation(function), calleeFrame));
@@ -3351,7 +3353,7 @@ private:
         
         m_ftlState.jitCode->osrExit.append(OSRExit(
             kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
-            m_codeOriginForExitTarget, m_codeOriginForExitProfile, m_lastSetOperand,
+            m_codeOriginForExitTarget, m_codeOriginForExitProfile, m_lastSetOperand.offset(),
             m_valueSources.numberOfArguments(), m_valueSources.numberOfLocals()));
         m_ftlState.osrExit.append(OSRExitCompilationInfo());
         
@@ -3626,7 +3628,7 @@ private:
         ASSERT(node->containsMovHint());
         ASSERT(node->op() != ZombieHint);
         
-        int operand = node->local();
+        VirtualRegister operand = node->local();
         
         m_lastSetOperand = operand;
         m_valueSources.operand(operand) = ValueSource(node->child1().node());
@@ -3744,14 +3746,26 @@ private:
     {
         return addressFor(m_callFrame, operand);
     }
+    TypedPointer addressFor(VirtualRegister operand)
+    {
+        return addressFor(m_callFrame, operand.offset());
+    }
     TypedPointer payloadFor(int operand)
     {
         return payloadFor(m_callFrame, operand);
     }
+    TypedPointer payloadFor(VirtualRegister operand)
+    {
+        return payloadFor(m_callFrame, operand.offset());
+    }
     TypedPointer tagFor(int operand)
     {
         return tagFor(m_callFrame, operand);
     }
+    TypedPointer tagFor(VirtualRegister operand)
+    {
+        return tagFor(m_callFrame, operand.offset());
+    }
     
     VM& vm() { return m_graph.m_vm; }
     CodeBlock* codeBlock() { return m_graph.m_codeBlock; }
@@ -3781,7 +3795,7 @@ private:
     HashMap<Node*, LValue> m_phis;
     
     Operands<ValueSource> m_valueSources;
-    int m_lastSetOperand;
+    VirtualRegister m_lastSetOperand;
     ExitThunkGenerator m_exitThunkGenerator;
     
     InPlaceAbstractState m_state;
index 330e1b2..0910624 100644 (file)
@@ -65,7 +65,7 @@ void* prepareOSREntry(
     
     for (int argument = values.numberOfArguments(); argument--;) {
         RELEASE_ASSERT(
-            exec->r(argumentToOperand(argument)).jsValue() == values.argument(argument));
+            exec->r(virtualRegisterForArgument(argument).offset()).jsValue() == values.argument(argument));
     }
     
     RELEASE_ASSERT(
@@ -78,7 +78,7 @@ void* prepareOSREntry(
         scratch[local] = JSValue::encode(values.local(local));
     
     int stackFrameSize = entryCodeBlock->m_numCalleeRegisters;
-    if (!vm.interpreter->stack().grow(&exec->registers()[localToOperand(stackFrameSize)])) {
+    if (!vm.interpreter->stack().grow(&exec->registers()[virtualRegisterForLocal(stackFrameSize).offset()])) {
         if (Options::verboseOSR())
             dataLog("    OSR failed bcause stack growth failed.\n");
         return 0;
index 0188e60..ffd0d07 100644 (file)
@@ -78,23 +78,23 @@ void OSRExit::convertToForward(
     if (!value)
         return;
     
-    int overriddenOperand = lastMovHint->local();
+    VirtualRegister overriddenOperand = lastMovHint->local();
     m_lastSetOperand = overriddenOperand;
     
     // Is the value for this operand being passed as an argument to the exit, or is
     // it something else? If it's an argument already, then replace that argument;
     // otherwise add another argument.
-    if (m_values[overriddenOperand].isArgument()) {
-        ExitArgument exitArgument = m_values[overriddenOperand].exitArgument();
+    if (m_values[overriddenOperand.offset()].isArgument()) {
+        ExitArgument exitArgument = m_values[overriddenOperand.offset()].exitArgument();
         arguments[exitArgument.argument()] = value.value();
-        m_values[overriddenOperand] = ExitValue::exitArgument(
+        m_values[overriddenOperand.offset()] = ExitValue::exitArgument(
             exitArgument.withFormat(value.format()));
         return;
     }
     
     unsigned argument = arguments.size();
     arguments.append(value.value());
-    m_values[m_lastSetOperand] = ExitValue::exitArgument(
+    m_values[m_lastSetOperand.offset()] = ExitValue::exitArgument(
         ExitArgument(value.format(), argument));
 }
 
index bc2830e..824fe7d 100644 (file)
@@ -40,6 +40,7 @@
 #include "MethodOfGettingAValueProfile.h"
 #include "Operands.h"
 #include "ValueProfile.h"
+#include "VirtualRegister.h"
 
 namespace JSC { namespace FTL {
 
@@ -160,7 +161,7 @@ struct OSRExit : public DFG::OSRExitBase {
     // Offset within the exit stubs of the stub for this exit.
     unsigned m_patchableCodeOffset;
     
-    int m_lastSetOperand;
+    VirtualRegister m_lastSetOperand;
     
     Operands<ExitValue> m_values;
     
index cf0605a..0e5e14a 100644 (file)
@@ -93,7 +93,7 @@ static void compileStub(
         if (!value.isArgument())
             continue;
         
-        sortedArguments.append(ExitArgumentForOperand(value.exitArgument(), operand));
+        sortedArguments.append(ExitArgumentForOperand(value.exitArgument(), VirtualRegister(operand)));
     }
     std::sort(sortedArguments.begin(), sortedArguments.end(), lesserArgumentIndex);
     
@@ -158,7 +158,7 @@ static void compileStub(
     jit.pop(MacroAssembler::framePointerRegister);
     jit.pop(GPRInfo::nonArgGPR0); // ignore the result.
     
-    if (exit.m_lastSetOperand != std::numeric_limits<int>::max()) {
+    if (exit.m_lastSetOperand.isValid()) {
         jit.load64(
             AssemblyHelpers::addressFor(exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
     }
index 63a3d27..d53b6aa 100644 (file)
@@ -218,7 +218,7 @@ namespace JSC  {
 
         // Read a register from the codeframe (or constant from the CodeBlock).
         Register& r(int);
-        // Read a register for a non-constant 
+        // Read a register for a non-constant
         Register& uncheckedR(int);
 
         // Access to arguments as passed. (After capture, arguments may move to a different location.)
index d650b1a..9aea159 100644 (file)
@@ -67,6 +67,8 @@
 #include "StrictEvalActivation.h"
 #include "StrongInlines.h"
 #include "VMStackBounds.h"
+#include "VirtualRegister.h"
+
 #include <limits.h>
 #include <stdio.h>
 #include <wtf/StackStats.h>
@@ -318,7 +320,7 @@ void Interpreter::dumpRegisters(CallFrame* callFrame)
     while (it > end) {
         JSValue v = it->jsValue();
         int registerNumber = it - callFrame->registers();
-        String name = codeBlock->nameForRegister(registerNumber);
+        String name = codeBlock->nameForRegister(VirtualRegister(registerNumber));
         dataLogF("[r% 3d %14s]      | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, toCString(v).data(), (long long)JSValue::encode(v));
         it++;
     }
@@ -352,7 +354,7 @@ void Interpreter::dumpRegisters(CallFrame* callFrame)
         do {
             JSValue v = it->jsValue();
             int registerNumber = it - callFrame->registers();
-            String name = codeBlock->nameForRegister(registerNumber);
+            String name = codeBlock->nameForRegister(VirtualRegister(registerNumber));
             dataLogF("[r% 3d %14s]      | %10p | %-16s 0x%lld \n", registerNumber, name.ascii().data(), it, toCString(v).data(), (long long)JSValue::encode(v));
             --it;
             --registerCount;
@@ -408,13 +410,13 @@ static bool unwindCallFrame(StackVisitor& visitor)
 #if ENABLE(DFG_JIT)
         RELEASE_ASSERT(!visitor->isInlinedFrame());
 #endif
-        activation = callFrame->uncheckedR(oldCodeBlock->activationRegister()).jsValue();
+        activation = callFrame->uncheckedR(oldCodeBlock->activationRegister().offset()).jsValue();
         if (activation)
             jsCast<JSActivation*>(activation)->tearOff(*scope->vm());
     }
 
     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->usesArguments()) {
-        if (JSValue arguments = visitor->r(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) {
+        if (JSValue arguments = visitor->r(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister()).offset()).jsValue()) {
             if (activation)
                 jsCast<Arguments*>(arguments)->didTearOffActivation(callFrame, jsCast<JSActivation*>(activation));
 #if ENABLE(DFG_JIT)
@@ -689,7 +691,7 @@ NEVER_INLINE HandlerInfo* Interpreter::unwind(CallFrame*& callFrame, JSValue& ex
 
     // Unwind the scope chain within the exception handler's call frame.
     int targetScopeDepth = handler->scopeDepth;
-    if (codeBlock->needsActivation() && callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
+    if (codeBlock->needsActivation() && callFrame->uncheckedR(codeBlock->activationRegister().offset()).jsValue())
         ++targetScopeDepth;
 
     JSScope* scope = callFrame->scope();
index 7b7bccc..6e52efe 100644 (file)
@@ -156,7 +156,7 @@ public:
     
     static Address addressFor(VirtualRegister virtualRegister)
     {
-        return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register));
+        return Address(GPRInfo::callFrameRegister, virtualRegister.offset() * sizeof(Register));
     }
     static Address addressFor(int operand)
     {
@@ -165,7 +165,7 @@ public:
 
     static Address tagFor(VirtualRegister virtualRegister)
     {
-        return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+        return Address(GPRInfo::callFrameRegister, virtualRegister.offset() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
     }
     static Address tagFor(int operand)
     {
@@ -174,7 +174,7 @@ public:
 
     static Address payloadFor(VirtualRegister virtualRegister)
     {
-        return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+        return Address(GPRInfo::callFrameRegister, virtualRegister.offset() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
     }
     static Address payloadFor(int operand)
     {
@@ -380,16 +380,16 @@ public:
         return m_baselineCodeBlock;
     }
     
-    int argumentsRegisterFor(InlineCallFrame* inlineCallFrame)
+    VirtualRegister argumentsRegisterFor(InlineCallFrame* inlineCallFrame)
     {
         if (!inlineCallFrame)
             return codeBlock()->argumentsRegister();
         
-        return baselineCodeBlockForInlineCallFrame(
-            inlineCallFrame)->argumentsRegister() + inlineCallFrame->stackOffset;
+        return VirtualRegister(baselineCodeBlockForInlineCallFrame(
+            inlineCallFrame)->argumentsRegister().offset() + inlineCallFrame->stackOffset);
     }
     
-    int argumentsRegisterFor(const CodeOrigin& codeOrigin)
+    VirtualRegister argumentsRegisterFor(const CodeOrigin& codeOrigin)
     {
         return argumentsRegisterFor(codeOrigin.inlineCallFrame);
     }
index eee151b..1443ddd 100644 (file)
@@ -583,8 +583,11 @@ namespace JSC {
         void emitGetJITStubArg(int argumentNumber, RegisterID dst);
 
         void emitGetVirtualRegister(int src, RegisterID dst);
+        void emitGetVirtualRegister(VirtualRegister src, RegisterID dst);
         void emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2);
+        void emitGetVirtualRegisters(VirtualRegister src1, RegisterID dst1, VirtualRegister src2, RegisterID dst2);
         void emitPutVirtualRegister(int dst, RegisterID from = regT0);
+        void emitPutVirtualRegister(VirtualRegister dst, RegisterID from = regT0);
         void emitStoreCell(int dst, RegisterID payload, bool /* only used in JSValue32_64 */ = false)
         {
             emitPutVirtualRegister(dst, payload);
index e837fab..950ff73 100644 (file)
@@ -76,7 +76,7 @@ void JIT::compileLoadVarargs(Instruction* instruction)
     JumpList slowCase;
     JumpList end;
     bool canOptimize = m_codeBlock->usesArguments()
-        && arguments == m_codeBlock->argumentsRegister()
+        && arguments == m_codeBlock->argumentsRegister().offset()
         && !m_codeBlock->symbolTable()->slowArguments();
 
     if (canOptimize) {
index 0a76bf2..8d02157 100644 (file)
@@ -758,7 +758,7 @@ ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, RegisterID dst)
         return;
     }
 
-    if (src == m_lastResultBytecodeRegister && m_codeBlock->isTemporaryRegisterIndex(operandToLocal(src)) && !atJumpTarget()) {
+    if (src == m_lastResultBytecodeRegister && operandIsLocal(src) && m_codeBlock->isTemporaryRegisterIndex(VirtualRegister(src).toLocal()) && !atJumpTarget()) {
         // The argument we want is already stored in eax
         if (dst != cachedResultRegister)
             move(cachedResultRegister, dst);
@@ -770,6 +770,11 @@ ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, RegisterID dst)
     killLastResultRegister();
 }
 
+ALWAYS_INLINE void JIT::emitGetVirtualRegister(VirtualRegister src, RegisterID dst)
+{
+    emitGetVirtualRegister(src.offset(), dst);
+}
+
 ALWAYS_INLINE void JIT::emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2)
 {
     if (src2 == m_lastResultBytecodeRegister) {
@@ -781,6 +786,11 @@ ALWAYS_INLINE void JIT::emitGetVirtualRegisters(int src1, RegisterID dst1, int s
     }
 }
 
+ALWAYS_INLINE void JIT::emitGetVirtualRegisters(VirtualRegister src1, RegisterID dst1, VirtualRegister src2, RegisterID dst2)
+{
+    emitGetVirtualRegisters(src1.offset(), dst1, src2.offset(), dst2);
+}
+
 ALWAYS_INLINE int32_t JIT::getConstantOperandImmediateInt(int src)
 {
     return getConstantOperand(src).asInt32();
@@ -797,6 +807,11 @@ ALWAYS_INLINE void JIT::emitPutVirtualRegister(int dst, RegisterID from)
     m_lastResultBytecodeRegister = (from == cachedResultRegister) ? dst : std::numeric_limits<int>::max();
 }
 
+ALWAYS_INLINE void JIT::emitPutVirtualRegister(VirtualRegister dst, RegisterID from)
+{
+    emitPutVirtualRegister(dst.offset(), from);
+}
+
 ALWAYS_INLINE void JIT::emitInitRegister(int dst)
 {
     store64(TrustedImm64(JSValue::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register)));
index b4dc929..0eccac1 100644 (file)
@@ -39,6 +39,7 @@
 #include "JSPropertyNameIterator.h"
 #include "LinkBuffer.h"
 #include "SlowPathCall.h"
+#include "VirtualRegister.h"
 
 namespace JSC {
 
@@ -257,9 +258,9 @@ void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction)
     int arguments = currentInstruction[1].u.operand;
     int activation = currentInstruction[2].u.operand;
 
-    Jump argsNotCreated = branchTest64(Zero, Address(callFrameRegister, sizeof(Register) * (unmodifiedArgumentsRegister(arguments))));
+    Jump argsNotCreated = branchTest64(Zero, Address(callFrameRegister, sizeof(Register) * (unmodifiedArgumentsRegister(VirtualRegister(arguments)).offset())));
     JITStubCall stubCall(this, cti_op_tear_off_arguments);
-    stubCall.addArgument(unmodifiedArgumentsRegister(arguments), regT2);
+    stubCall.addArgument(unmodifiedArgumentsRegister(VirtualRegister(arguments)).offset(), regT2);
     stubCall.addArgument(activation, regT2);
     stubCall.call();
     argsNotCreated.link(this);
@@ -507,7 +508,7 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction)
     emitGetVirtualRegister(base, regT0);
     if (!m_codeBlock->isKnownNotImmediate(base))
         isNotObject.append(emitJumpIfNotJSCell(regT0));
-    if (base != m_codeBlock->thisRegister() || m_codeBlock->isStrictMode()) {
+    if (base != m_codeBlock->thisRegister().offset() || m_codeBlock->isStrictMode()) {
         loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
         isNotObject.append(emitJumpIfNotObject(regT2));
     }
@@ -833,7 +834,7 @@ void JIT::emit_op_enter(Instruction*)
     // object lifetime and increasing GC pressure.
     size_t count = m_codeBlock->m_numVars;
     for (size_t j = 0; j < count; ++j)
-        emitInitRegister(localToOperand(j));
+        emitInitRegister(virtualRegisterForLocal(j).offset());
 }
 
 void JIT::emit_op_create_activation(Instruction* currentInstruction)
@@ -852,7 +853,7 @@ void JIT::emit_op_create_arguments(Instruction* currentInstruction)
     Jump argsCreated = branchTest64(NonZero, Address(callFrameRegister, sizeof(Register) * dst));
     JITStubCall(this, cti_op_create_arguments).call();
     emitPutVirtualRegister(dst);
-    emitPutVirtualRegister(unmodifiedArgumentsRegister(dst));
+    emitPutVirtualRegister(unmodifiedArgumentsRegister(VirtualRegister(dst)));
     argsCreated.link(this);
 }
 
@@ -1145,7 +1146,7 @@ void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vecto
     linkSlowCase(iter);
     JITStubCall(this, cti_op_create_arguments).call();
     emitPutVirtualRegister(arguments);
-    emitPutVirtualRegister(unmodifiedArgumentsRegister(arguments));
+    emitPutVirtualRegister(unmodifiedArgumentsRegister(VirtualRegister(arguments)));
     
     skipArgumentsCreation.link(this);
     JITStubCall stubCall(this, cti_op_get_by_val_generic);
index 10322b2..47776b7 100644 (file)
@@ -39,6 +39,7 @@
 #include "JSVariableObject.h"
 #include "LinkBuffer.h"
 #include "SlowPathCall.h"
+#include "VirtualRegister.h"
 
 namespace JSC {
 
@@ -1096,7 +1097,7 @@ void JIT::emit_op_enter(Instruction*)
     // registers to zap stale pointers, to avoid unnecessarily prolonging
     // object lifetime and increasing GC pressure.
     for (int i = 0; i < m_codeBlock->m_numVars; ++i)
-        emitStore(localToOperand(i), jsUndefined());
+        emitStore(virtualRegisterForLocal(i).offset(), jsUndefined());
 }
 
 void JIT::emit_op_create_activation(Instruction* currentInstruction)
index 5fec21b..bd5363d 100644 (file)
@@ -1047,7 +1047,7 @@ DEFINE_STUB_FUNCTION(void, optimize)
         for (size_t i = 0; i < mustHandleValues.size(); ++i) {
             int operand = mustHandleValues.operandForIndex(i);
             if (operandIsArgument(operand)
-                && !operandToArgument(operand)
+                && !VirtualRegister(operand).toArgument()
                 && codeBlock->codeType() == FunctionCode
                 && codeBlock->specializationKind() == CodeForConstruct) {
                 // Ugh. If we're in a constructor, the 'this' argument may hold garbage. It will
@@ -1154,7 +1154,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
     
-    ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
+    ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister().offset()).jsValue());
     return JSFunction::create(stackFrame.callFrame, stackFrame.args[0].function(), stackFrame.callFrame->scope());
 }
 
@@ -1931,7 +1931,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
 
     FunctionExecutable* function = stackFrame.args[0].function();
     JSFunction* func = JSFunction::create(callFrame, function, callFrame->scope());
-    ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->uncheckedR(callFrame->codeBlock()->activationRegister()).jsValue());
+    ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->uncheckedR(callFrame->codeBlock()->activationRegister().offset()).jsValue());
 
     return func;
 }
@@ -1959,7 +1959,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
     CallFrame* callerFrame = callFrame->callerFrame();
     ASSERT(callFrame->callerFrame()->codeBlock()->codeType() != FunctionCode
         || !callFrame->callerFrame()->codeBlock()->needsFullScopeChain()
-        || callFrame->callerFrame()->uncheckedR(callFrame->callerFrame()->codeBlock()->activationRegister()).jsValue());
+        || callFrame->callerFrame()->uncheckedR(callFrame->callerFrame()->codeBlock()->activationRegister().offset()).jsValue());
 
     callFrame->setScope(callerFrame->scope());
     callFrame->setReturnPC(static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()));
index 53f4195..60d03bb 100644 (file)
@@ -697,7 +697,7 @@ LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val)
         arguments = Arguments::create(vm, exec);
         LLINT_CHECK_EXCEPTION();
         LLINT_OP(2) = arguments;
-        exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)) = arguments;
+        exec->uncheckedR(unmodifiedArgumentsRegister(VirtualRegister(pc[2].u.operand)).offset()) = arguments;
     }
     
     LLINT_RETURN_PROFILED(op_get_argument_by_val, getByVal(exec, arguments, LLINT_OP_C(3).jsValue()));
@@ -917,7 +917,7 @@ LLINT_SLOW_PATH_DECL(slow_path_new_func)
     CodeBlock* codeBlock = exec->codeBlock();
     ASSERT(codeBlock->codeType() != FunctionCode
            || !codeBlock->needsFullScopeChain()
-           || exec->uncheckedR(codeBlock->activationRegister()).jsValue());
+           || exec->uncheckedR(codeBlock->activationRegister().offset()).jsValue());
 #if LLINT_SLOW_PATH_TRACING
     dataLogF("Creating function!\n");
 #endif
@@ -1128,7 +1128,7 @@ LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments)
 {
     LLINT_BEGIN();
     ASSERT(exec->codeBlock()->usesArguments());
-    Arguments* arguments = jsCast<Arguments*>(exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)).jsValue());
+    Arguments* arguments = jsCast<Arguments*>(exec->uncheckedR(unmodifiedArgumentsRegister(VirtualRegister(pc[1].u.operand)).offset()).jsValue());
     if (JSValue activationValue = LLINT_OP_C(2).jsValue())
         arguments->didTearOffActivation(exec, jsCast<JSActivation*>(activationValue));
     else
index 993e168..d00e371 100644 (file)
@@ -45,7 +45,7 @@ BytecodeSequence::BytecodeSequence(CodeBlock* codeBlock)
         if (!description.length())
             continue;
         out.reset();
-        out.print("arg", i, " (r", argumentToOperand(i), "): ", description);
+        out.print("arg", i, " (r", virtualRegisterForArgument(i).offset(), "): ", description);
         m_header.append(out.toCString());
     }
 #endif // ENABLE(VALUE_PROFILER)
index e7c5795..be6ac59 100644 (file)
@@ -207,7 +207,7 @@ SLOW_PATH_DECL(slow_path_create_arguments)
     JSValue arguments = JSValue(Arguments::create(vm, exec));
     CHECK_EXCEPTION();
     exec->uncheckedR(pc[1].u.operand) = arguments;
-    exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)) = arguments;
+    exec->uncheckedR(unmodifiedArgumentsRegister(VirtualRegister(pc[1].u.operand)).offset()) = arguments;
     END();
 }
 
index 44f257e..a839c94 100644 (file)
@@ -218,13 +218,13 @@ JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, PropertyName
     if (activation->isTornOff() || !(callFrame->codeBlock()->usesArguments() || callFrame->codeBlock()->usesEval()))
         return jsUndefined();
 
-    int argumentsRegister = callFrame->codeBlock()->argumentsRegister();
-    if (JSValue arguments = callFrame->uncheckedR(argumentsRegister).jsValue())
+    VirtualRegister argumentsRegister = callFrame->codeBlock()->argumentsRegister();
+    if (JSValue arguments = callFrame->uncheckedR(argumentsRegister.offset()).jsValue())
         return arguments;
-    int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
+    int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister).offset();
 
     JSValue arguments = JSValue(Arguments::create(callFrame->vm(), callFrame));
-    callFrame->uncheckedR(argumentsRegister) = arguments;
+    callFrame->uncheckedR(argumentsRegister.offset()) = arguments;
     callFrame->uncheckedR(realArgumentsRegister) = arguments;
     
     ASSERT(callFrame->uncheckedR(realArgumentsRegister).jsValue().inherits(Arguments::info()));