Commit 1796ad0f authored by msaboff@apple.com's avatar 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:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@156474 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 44da78ad
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> 2013-09-26 Anders Carlsson <andersca@apple.com>
Weak should have a move constructor and move assignment operator Weak should have a move constructor and move assignment operator
...@@ -168,12 +168,12 @@ CString CodeBlock::registerName(int r) const ...@@ -168,12 +168,12 @@ CString CodeBlock::registerName(int r) const
return constantName(r, getConstant(r)); return constantName(r, getConstant(r));
if (operandIsArgument(r)) { if (operandIsArgument(r)) {
if (!operandToArgument(r)) if (!VirtualRegister(r).toArgument())
return "this"; 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) static CString regexpToSourceString(RegExp* regExp)
...@@ -514,11 +514,11 @@ void CodeBlock::dumpBytecode(PrintStream& out) ...@@ -514,11 +514,11 @@ void CodeBlock::dumpBytecode(PrintStream& out)
if (usesArguments()) { if (usesArguments()) {
out.printf( out.printf(
"; uses arguments, in r%d, r%d", "; uses arguments, in r%d, r%d",
argumentsRegister(), argumentsRegister().offset(),
unmodifiedArgumentsRegister(argumentsRegister())); unmodifiedArgumentsRegister(argumentsRegister()).offset());
} }
if (needsFullScopeChain() && codeType() == FunctionCode) if (needsFullScopeChain() && codeType() == FunctionCode)
out.printf("; activation in r%d", activationRegister()); out.printf("; activation in r%d", activationRegister().offset());
out.printf("\n"); out.printf("\n");
const Instruction* begin = instructions().begin(); const Instruction* begin = instructions().begin();
...@@ -1619,7 +1619,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin ...@@ -1619,7 +1619,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
setConstantRegisters(unlinkedCodeBlock->constantRegisters()); setConstantRegisters(unlinkedCodeBlock->constantRegisters());
if (unlinkedCodeBlock->usesGlobalObject()) 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()); m_functionDecls.grow(unlinkedCodeBlock->numberOfFunctionDecls());
for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) { for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) {
UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i); UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
...@@ -2557,9 +2557,9 @@ void CodeBlock::createActivation(CallFrame* callFrame) ...@@ -2557,9 +2557,9 @@ void CodeBlock::createActivation(CallFrame* callFrame)
{ {
ASSERT(codeType() == FunctionCode); ASSERT(codeType() == FunctionCode);
ASSERT(needsFullScopeChain()); ASSERT(needsFullScopeChain());
ASSERT(!callFrame->uncheckedR(activationRegister()).jsValue()); ASSERT(!callFrame->uncheckedR(activationRegister().offset()).jsValue());
JSActivation* activation = JSActivation::create(callFrame->vm(), callFrame, this); JSActivation* activation = JSActivation::create(callFrame->vm(), callFrame, this);
callFrame->uncheckedR(activationRegister()) = JSValue(activation); callFrame->uncheckedR(activationRegister().offset()) = JSValue(activation);
callFrame->setScope(activation); callFrame->setScope(activation);
} }
...@@ -3327,32 +3327,30 @@ bool CodeBlock::usesOpcode(OpcodeID opcodeID) ...@@ -3327,32 +3327,30 @@ bool CodeBlock::usesOpcode(OpcodeID opcodeID)
return false; return false;
} }
String CodeBlock::nameForRegister(int registerNumber) String CodeBlock::nameForRegister(VirtualRegister virtualRegister)
{ {
ConcurrentJITLocker locker(symbolTable()->m_lock); ConcurrentJITLocker locker(symbolTable()->m_lock);
SymbolTable::Map::iterator end = symbolTable()->end(locker); SymbolTable::Map::iterator end = symbolTable()->end(locker);
for (SymbolTable::Map::iterator ptr = symbolTable()->begin(locker); ptr != end; ++ptr) { 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. // FIXME: This won't work from the compilation thread.
// https://bugs.webkit.org/show_bug.cgi?id=115300 // https://bugs.webkit.org/show_bug.cgi?id=115300
return String(ptr->key); return String(ptr->key);
} }
} }
if (needsActivation() && registerNumber == activationRegister()) if (needsActivation() && virtualRegister == activationRegister())
return ASCIILiteral("activation"); return ASCIILiteral("activation");
if (registerNumber == thisRegister()) if (virtualRegister == thisRegister())
return ASCIILiteral("this"); return ASCIILiteral("this");
if (usesArguments()) { if (usesArguments()) {
if (registerNumber == argumentsRegister()) if (virtualRegister == argumentsRegister())
return ASCIILiteral("arguments"); return ASCIILiteral("arguments");
if (unmodifiedArgumentsRegister(argumentsRegister()) == registerNumber) if (unmodifiedArgumentsRegister(argumentsRegister()) == virtualRegister)
return ASCIILiteral("real arguments"); return ASCIILiteral("real arguments");
} }
if (registerNumber < 0) { if (virtualRegister.isArgument())
int argumentPosition = -registerNumber; return String::format("arguments[%3d]", virtualRegister.toArgument()).impl();
argumentPosition -= JSStack::CallFrameHeaderSize + 1;
return String::format("arguments[%3d]", argumentPosition - 1).impl();
}
return ""; return "";
} }
......
...@@ -71,6 +71,7 @@ ...@@ -71,6 +71,7 @@
#include "StructureStubInfo.h" #include "StructureStubInfo.h"
#include "UnconditionalFinalizer.h" #include "UnconditionalFinalizer.h"
#include "ValueProfile.h" #include "ValueProfile.h"
#include "VirtualRegister.h"
#include "Watchpoint.h" #include "Watchpoint.h"
#include <wtf/FastMalloc.h> #include <wtf/FastMalloc.h>
#include <wtf/PassOwnPtr.h> #include <wtf/PassOwnPtr.h>
...@@ -86,7 +87,7 @@ class ExecState; ...@@ -86,7 +87,7 @@ class ExecState;
class LLIntOffsetsExtractor; class LLIntOffsetsExtractor;
class RepatchBuffer; 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(); } static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
...@@ -148,7 +149,7 @@ public: ...@@ -148,7 +149,7 @@ public:
inline bool isKnownNotImmediate(int index) inline bool isKnownNotImmediate(int index)
{ {
if (index == m_thisRegister && !m_isStrictMode) if (index == m_thisRegister.offset() && !m_isStrictMode)
return true; return true;
if (isConstantRegisterIndex(index)) if (isConstantRegisterIndex(index))
...@@ -298,58 +299,61 @@ public: ...@@ -298,58 +299,61 @@ public:
void setVM(VM* vm) { m_vm = vm; } void setVM(VM* vm) { m_vm = vm; }
VM* vm() { return m_vm; } VM* vm() { return m_vm; }
void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; } void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; }
int thisRegister() const { return m_thisRegister; } VirtualRegister thisRegister() const { return m_thisRegister; }
bool needsFullScopeChain() const { return m_unlinkedCode->needsFullScopeChain(); } bool needsFullScopeChain() const { return m_unlinkedCode->needsFullScopeChain(); }
bool usesEval() const { return m_unlinkedCode->usesEval(); } 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; m_argumentsRegister = argumentsRegister;
ASSERT(usesArguments()); ASSERT(usesArguments());
} }
int argumentsRegister() const VirtualRegister argumentsRegister() const
{ {
ASSERT(usesArguments()); ASSERT(usesArguments());
return m_argumentsRegister; return m_argumentsRegister;
} }
int uncheckedArgumentsRegister() VirtualRegister uncheckedArgumentsRegister()
{ {
if (!usesArguments()) if (!usesArguments())
return InvalidVirtualRegister; return VirtualRegister();
return argumentsRegister(); return argumentsRegister();
} }
void setActivationRegister(int activationRegister) void setActivationRegister(VirtualRegister activationRegister)
{ {
m_activationRegister = activationRegister; m_activationRegister = activationRegister;
} }
int activationRegister() const
VirtualRegister activationRegister() const
{ {
ASSERT(needsFullScopeChain()); ASSERT(needsFullScopeChain());
return m_activationRegister; return m_activationRegister;
} }
int uncheckedActivationRegister()
VirtualRegister uncheckedActivationRegister()
{ {
if (!needsFullScopeChain()) if (!needsFullScopeChain())
return InvalidVirtualRegister; return VirtualRegister();
return activationRegister(); return activationRegister();
} }
bool usesArguments() const { return m_argumentsRegister != (int)InvalidVirtualRegister; }
bool usesArguments() const { return m_argumentsRegister.isValid(); }
bool needsActivation() const bool needsActivation() const
{ {
return m_needsActivation; return m_needsActivation;
} }
bool isCaptured(int operand, InlineCallFrame* inlineCallFrame = 0) const bool isCaptured(VirtualRegister operand, InlineCallFrame* inlineCallFrame = 0) const
{ {
if (operandIsArgument(operand)) if (operand.isArgument())
return operandToArgument(operand) && usesArguments(); return operand.toArgument() && usesArguments();
if (inlineCallFrame) 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" // 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. // in the sense that stores to its location can be observed indirectly.
...@@ -368,8 +372,8 @@ public: ...@@ -368,8 +372,8 @@ public:
if (!symbolTable()) if (!symbolTable())
return false; return false;
return operand <= symbolTable()->captureStart() return operand.offset() <= symbolTable()->captureStart()
&& operand > symbolTable()->captureEnd(); && operand.offset() > symbolTable()->captureEnd();
} }
CodeType codeType() const { return m_unlinkedCode->codeType(); } CodeType codeType() const { return m_unlinkedCode->codeType(); }
...@@ -391,7 +395,7 @@ public: ...@@ -391,7 +395,7 @@ public:
void clearEvalCache(); void clearEvalCache();
String nameForRegister(int registerNumber); String nameForRegister(VirtualRegister);
#if ENABLE(JIT) #if ENABLE(JIT)
void setNumberOfStructureStubInfos(size_t size) { m_structureStubInfos.grow(size); } void setNumberOfStructureStubInfos(size_t size) { m_structureStubInfos.grow(size); }
...@@ -1027,9 +1031,9 @@ private: ...@@ -1027,9 +1031,9 @@ private:
VM* m_vm; VM* m_vm;
RefCountedArray<Instruction> m_instructions; RefCountedArray<Instruction> m_instructions;
int m_thisRegister; VirtualRegister m_thisRegister;
int m_argumentsRegister; VirtualRegister m_argumentsRegister;
int m_activationRegister; VirtualRegister m_activationRegister;
bool m_isStrictMode; bool m_isStrictMode;
bool m_needsActivation; bool m_needsActivation;
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "SpecialPointer.h" #include "SpecialPointer.h"
#include "Structure.h" #include "Structure.h"
#include "StructureChain.h" #include "StructureChain.h"
#include "VirtualRegister.h"
#include <wtf/VectorTraits.h> #include <wtf/VectorTraits.h>
namespace JSC { namespace JSC {
......
...@@ -46,26 +46,26 @@ class LazyOperandValueProfileKey { ...@@ -46,26 +46,26 @@ class LazyOperandValueProfileKey {
public: public:
LazyOperandValueProfileKey() LazyOperandValueProfileKey()
: m_bytecodeOffset(0) // 0 = empty value : 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) LazyOperandValueProfileKey(WTF::HashTableDeletedValueType)
: m_bytecodeOffset(1) // 1 = deleted value : 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_bytecodeOffset(bytecodeOffset)
, m_operand(operand) , m_operand(operand)
{ {
ASSERT(operand != InvalidVirtualRegister); ASSERT(m_operand.isValid());
} }
bool operator!() const bool operator!() const
{ {
return m_operand == InvalidVirtualRegister; return !m_operand.isValid();
} }
bool operator==(const LazyOperandValueProfileKey& other) const bool operator==(const LazyOperandValueProfileKey& other) const
...@@ -76,7 +76,7 @@ public: ...@@ -76,7 +76,7 @@ public:
unsigned hash() const unsigned hash() const
{ {
return WTF::intHash(m_bytecodeOffset) + m_operand; return WTF::intHash(m_bytecodeOffset) + m_operand.offset();
} }
unsigned bytecodeOffset() const unsigned bytecodeOffset() const
...@@ -84,7 +84,8 @@ public: ...@@ -84,7 +84,8 @@ public:
ASSERT(!!*this); ASSERT(!!*this);
return m_bytecodeOffset; return m_bytecodeOffset;
} }
int operand() const
VirtualRegister operand() const
{ {
ASSERT(!!*this); ASSERT(!!*this);
return m_operand; return m_operand;
...@@ -92,11 +93,11 @@ public: ...@@ -92,11 +93,11 @@ public:
bool isHashTableDeletedValue() const bool isHashTableDeletedValue() const
{ {
return m_operand == InvalidVirtualRegister && m_bytecodeOffset; return !m_operand.isValid() && m_bytecodeOffset;
} }
private: private:
unsigned m_bytecodeOffset; unsigned m_bytecodeOffset;
int m_operand; VirtualRegister m_operand;
}; };
struct LazyOperandValueProfileKeyHash { struct LazyOperandValueProfileKeyHash {
...@@ -129,7 +130,7 @@ namespace JSC { ...@@ -129,7 +130,7 @@ namespace JSC {
struct LazyOperandValueProfile : public MinimalValueProfile { struct LazyOperandValueProfile : public MinimalValueProfile {
LazyOperandValueProfile() LazyOperandValueProfile()
: MinimalValueProfile() : MinimalValueProfile()
, m_operand(InvalidVirtualRegister) , m_operand(VirtualRegister())
{ {
} }
...@@ -144,7 +145,7 @@ struct LazyOperandValueProfile : public MinimalValueProfile { ...@@ -144,7 +145,7 @@ struct LazyOperandValueProfile : public MinimalValueProfile {
return LazyOperandValueProfileKey(m_bytecodeOffset, m_operand); return LazyOperandValueProfileKey(m_bytecodeOffset, m_operand);
} }
int m_operand; VirtualRegister m_operand;
typedef SegmentedVector<LazyOperandValueProfile, 8> List; typedef SegmentedVector<LazyOperandValueProfile, 8> List;
}; };
......
...@@ -39,7 +39,7 @@ MethodOfGettingAValueProfile MethodOfGettingAValueProfile::fromLazyOperand( ...@@ -39,7 +39,7 @@ MethodOfGettingAValueProfile MethodOfGettingAValueProfile::fromLazyOperand(
result.m_kind = LazyOperand; result.m_kind = LazyOperand;
result.u.lazyOperand.codeBlock = codeBlock; result.u.lazyOperand.codeBlock = codeBlock;
result.u.lazyOperand.bytecodeOffset = key.bytecodeOffset(); result.u.lazyOperand.bytecodeOffset = key.bytecodeOffset();
result.u.lazyOperand.operand = key.operand(); result.u.lazyOperand.operand = key.operand().offset();
return result; return result;
} }
...@@ -53,7 +53,7 @@ EncodedJSValue* MethodOfGettingAValueProfile::getSpecFailBucket(unsigned index) ...@@ -53,7 +53,7 @@ EncodedJSValue* MethodOfGettingAValueProfile::getSpecFailBucket(unsigned index)
return u.profile->specFailBucket(index); return u.profile->specFailBucket(index);
case LazyOperand: { 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); ConcurrentJITLocker locker(u.lazyOperand.codeBlock->m_lock);
LazyOperandValueProfile* profile = LazyOperandValueProfile* profile =
......
...@@ -28,20 +28,13 @@ ...@@ -28,20 +28,13 @@
#include "CallFrame.h" #include "CallFrame.h"
#include "JSObject.h" #include "JSObject.h"
#include "VirtualRegister.h"
#include <wtf/PrintStream.h> #include <wtf/PrintStream.h>
#include <wtf/Vector.h> #include <wtf/Vector.h>
namespace JSC { 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> struct OperandValueTraits;
template<typename T> template<typename T>
...@@ -143,33 +136,43 @@ public: ...@@ -143,33 +136,43 @@ public:
T& operand(int operand) T& operand(int operand)
{ {
if (operandIsArgument(operand)) { if (operandIsArgument(operand)) {
int argument = operandToArgument(operand); int argument = VirtualRegister(operand).toArgument();
return m_arguments[argument]; 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)); } const T& operand(int operand) const { return const_cast<const T&>(const_cast<Operands*>(this)->operand(operand)); }
bool hasOperand(int operand) const bool hasOperand(int operand) const
{ {
if (operandIsArgument(operand)) if (operandIsArgument(operand))
return true;