Commit ee4d8a7a authored by fpizlo@apple.com's avatar fpizlo@apple.com

Variable event stream (for DFG OSR exit) should be explicit about where on the...

Variable event stream (for DFG OSR exit) should be explicit about where on the stack a SetLocal put a value
https://bugs.webkit.org/show_bug.cgi?id=122178

Reviewed by Geoffrey Garen.
        
Now if the DFG stores the value of a variable into the stack explicitly via a SetLocal,
it will record where on the stack it stored the value in addition to recording where on
the stack the bytecode would have done the SetLocal. Previously it just recorded the
format and the bytecode variable. Recording just the bytecode variable is currently fine
since the DFG always executes SetLocal's to the same stack location that the bytecode
would have used. But that prevents stack compression (webkit.org/b/122024) so this patch
allows the SetLocal to say both the bytecode variable that we're speaking of and the
actual stack location to which the SetLocal stored the value.
        
This had to touch a lot of code, so I took the opportunity to also resolve
webkit.org/b/108019.

* bytecode/Operands.h:
(JSC::Operands::hasOperand):
* dfg/DFGFlushFormat.h:
(JSC::DFG::dataFormatFor):
* dfg/DFGMinifiedID.h:
(JSC::DFG::MinifiedID::bits):
(JSC::DFG::MinifiedID::invalidID):
(JSC::DFG::MinifiedID::otherInvalidID):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileMovHint):
(JSC::DFG::SpeculativeJIT::compileInlineStart):
(JSC::DFG::SpeculativeJIT::compileCurrentBlock):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::recordSetLocal):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGValueSource.cpp:
(JSC::DFG::ValueSource::dump):
* dfg/DFGValueSource.h:
(JSC::DFG::ValueSource::ValueSource):
(JSC::DFG::ValueSource::forFlushFormat):
(JSC::DFG::ValueSource::forDataFormat):
(JSC::DFG::ValueSource::isSet):
(JSC::DFG::ValueSource::kind):
(JSC::DFG::ValueSource::valueRecovery):
(JSC::DFG::ValueSource::id):
(JSC::DFG::ValueSource::virtualRegister):
* dfg/DFGVariableEvent.cpp:
(JSC::DFG::VariableEvent::dump):
(JSC::DFG::VariableEvent::dumpSpillInfo):
* dfg/DFGVariableEvent.h:
(JSC::DFG::VariableEvent::fillGPR):
(JSC::DFG::VariableEvent::fillPair):
(JSC::DFG::VariableEvent::fillFPR):
(JSC::DFG::VariableEvent::spill):
(JSC::DFG::VariableEvent::death):
(JSC::DFG::VariableEvent::setLocal):
(JSC::DFG::VariableEvent::movHint):
(JSC::DFG::VariableEvent::id):
(JSC::DFG::VariableEvent::gpr):
(JSC::DFG::VariableEvent::tagGPR):
(JSC::DFG::VariableEvent::payloadGPR):
(JSC::DFG::VariableEvent::fpr):
(JSC::DFG::VariableEvent::spillRegister):
(JSC::DFG::VariableEvent::bytecodeRegister):
(JSC::DFG::VariableEvent::machineRegister):
(JSC::DFG::VariableEvent::variableRepresentation):
* dfg/DFGVariableEventStream.cpp:
(JSC::DFG::VariableEventStream::reconstruct):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@156747 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 0e3c2688
2013-10-01 Filip Pizlo <fpizlo@apple.com>
Variable event stream (for DFG OSR exit) should be explicit about where on the stack a SetLocal put a value
https://bugs.webkit.org/show_bug.cgi?id=122178
Reviewed by Geoffrey Garen.
Now if the DFG stores the value of a variable into the stack explicitly via a SetLocal,
it will record where on the stack it stored the value in addition to recording where on
the stack the bytecode would have done the SetLocal. Previously it just recorded the
format and the bytecode variable. Recording just the bytecode variable is currently fine
since the DFG always executes SetLocal's to the same stack location that the bytecode
would have used. But that prevents stack compression (webkit.org/b/122024) so this patch
allows the SetLocal to say both the bytecode variable that we're speaking of and the
actual stack location to which the SetLocal stored the value.
This had to touch a lot of code, so I took the opportunity to also resolve
webkit.org/b/108019.
* bytecode/Operands.h:
(JSC::Operands::hasOperand):
* dfg/DFGFlushFormat.h:
(JSC::DFG::dataFormatFor):
* dfg/DFGMinifiedID.h:
(JSC::DFG::MinifiedID::bits):
(JSC::DFG::MinifiedID::invalidID):
(JSC::DFG::MinifiedID::otherInvalidID):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileMovHint):
(JSC::DFG::SpeculativeJIT::compileInlineStart):
(JSC::DFG::SpeculativeJIT::compileCurrentBlock):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::recordSetLocal):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGValueSource.cpp:
(JSC::DFG::ValueSource::dump):
* dfg/DFGValueSource.h:
(JSC::DFG::ValueSource::ValueSource):
(JSC::DFG::ValueSource::forFlushFormat):
(JSC::DFG::ValueSource::forDataFormat):
(JSC::DFG::ValueSource::isSet):
(JSC::DFG::ValueSource::kind):
(JSC::DFG::ValueSource::valueRecovery):
(JSC::DFG::ValueSource::id):
(JSC::DFG::ValueSource::virtualRegister):
* dfg/DFGVariableEvent.cpp:
(JSC::DFG::VariableEvent::dump):
(JSC::DFG::VariableEvent::dumpSpillInfo):
* dfg/DFGVariableEvent.h:
(JSC::DFG::VariableEvent::fillGPR):
(JSC::DFG::VariableEvent::fillPair):
(JSC::DFG::VariableEvent::fillFPR):
(JSC::DFG::VariableEvent::spill):
(JSC::DFG::VariableEvent::death):
(JSC::DFG::VariableEvent::setLocal):
(JSC::DFG::VariableEvent::movHint):
(JSC::DFG::VariableEvent::id):
(JSC::DFG::VariableEvent::gpr):
(JSC::DFG::VariableEvent::tagGPR):
(JSC::DFG::VariableEvent::payloadGPR):
(JSC::DFG::VariableEvent::fpr):
(JSC::DFG::VariableEvent::spillRegister):
(JSC::DFG::VariableEvent::bytecodeRegister):
(JSC::DFG::VariableEvent::machineRegister):
(JSC::DFG::VariableEvent::variableRepresentation):
* dfg/DFGVariableEventStream.cpp:
(JSC::DFG::VariableEventStream::reconstruct):
2013-10-01 Nadav Rotem <nrotem@apple.com>
FTL: split overflow checks into non-overflow arithmetic and an additional call to the overflow intrinsic check.
......@@ -156,6 +156,10 @@ public:
return true;
return static_cast<size_t>(VirtualRegister(operand).toLocal()) < numberOfLocals();
}
bool hasOperand(VirtualRegister reg) const
{
return hasOperand(reg.offset());
}
void setOperand(int operand, const T& value)
{
......
......@@ -32,6 +32,7 @@
#include "DFGNodeFlags.h"
#include "DFGUseKind.h"
#include "DataFormat.h"
#include "DumpContext.h"
#include <wtf/PrintStream.h>
......@@ -88,6 +89,28 @@ inline UseKind useKindFor(FlushFormat format)
return UntypedUse;
}
inline DataFormat dataFormatFor(FlushFormat format)
{
switch (format) {
case DeadFlush:
return DataFormatDead;
case FlushedJSValue:
return DataFormatJS;
case FlushedDouble:
return DataFormatDouble;
case FlushedInt32:
return DataFormatInt32;
case FlushedInt52:
return DataFormatInt52;
case FlushedCell:
return DataFormatCell;
case FlushedBoolean:
return DataFormatBoolean;
}
RELEASE_ASSERT_NOT_REACHED();
return DataFormatDead;
}
} } // namespace JSC::DFG
namespace WTF {
......
......@@ -66,20 +66,21 @@ public:
bool isHashTableDeletedValue() const { return m_id == otherInvalidID(); }
private:
friend class MinifiedNode;
friend class ValueSource;
static uintptr_t invalidID() { return static_cast<uintptr_t>(static_cast<intptr_t>(-1)); }
static uintptr_t otherInvalidID() { return static_cast<uintptr_t>(static_cast<intptr_t>(-2)); }
static MinifiedID fromBits(uintptr_t value)
{
MinifiedID result;
result.m_id = value;
return result;
}
uintptr_t bits() const { return m_id; }
private:
friend class MinifiedNode;
static uintptr_t invalidID() { return static_cast<uintptr_t>(static_cast<intptr_t>(-1)); }
static uintptr_t otherInvalidID() { return static_cast<uintptr_t>(static_cast<intptr_t>(-2)); }
uintptr_t m_id;
};
......
......@@ -1520,7 +1520,7 @@ void SpeculativeJIT::compileMovHint(Node* node)
if (child->op() == UInt32ToNumber)
noticeOSRBirth(child->child1().node());
m_stream->appendAndLog(VariableEvent::movHint(MinifiedID(child), node->local().offset()));
m_stream->appendAndLog(VariableEvent::movHint(MinifiedID(child), node->local()));
}
void SpeculativeJIT::compileMovHintAndCheck(Node* node)
......@@ -1537,9 +1537,9 @@ void SpeculativeJIT::compileInlineStart(Node* node)
unsigned argumentPositionStart = node->argumentPositionStart();
for (int i = 0; i < argumentCountIncludingThis; ++i) {
ValueSource source = ValueSource::forFlushFormat(
VirtualRegister(inlineCallFrame->stackOffset + virtualRegisterForArgument(i).offset()),
m_jit.graph().m_argumentPositions[argumentPositionStart + i].flushFormat());
inlineCallFrame->arguments[i] = source.valueRecovery(
inlineCallFrame->stackOffset + virtualRegisterForArgument(i).offset());
inlineCallFrame->arguments[i] = source.valueRecovery();
}
}
......@@ -1581,8 +1581,9 @@ void SpeculativeJIT::compileCurrentBlock()
m_jit.jitAssertHasValidCallFrame();
for (size_t i = 0; i < m_block->variablesAtHead.numberOfArguments(); ++i) {
ValueSource valueSource = ValueSource(ValueInJSStack);
m_stream->appendAndLog(VariableEvent::setLocal(virtualRegisterForArgument(i), valueSource.dataFormat()));
m_stream->appendAndLog(
VariableEvent::setLocal(
virtualRegisterForArgument(i), virtualRegisterForArgument(i), DataFormatJS));
}
m_state.reset();
......@@ -1590,17 +1591,19 @@ void SpeculativeJIT::compileCurrentBlock()
for (size_t i = 0; i < m_block->variablesAtHead.numberOfLocals(); ++i) {
Node* node = m_block->variablesAtHead.local(i);
ValueSource valueSource;
if (!node)
valueSource = ValueSource(SourceIsDead);
else if (node->variableAccessData()->isArgumentsAlias())
valueSource = ValueSource(ArgumentsSource);
continue; // No need to record dead SetLocal's.
VariableAccessData* variable = node->variableAccessData();
DataFormat format;
if (variable->isArgumentsAlias())
format = DataFormatArguments;
else if (!node->refCount())
valueSource = ValueSource(SourceIsDead);
continue; // No need to record dead SetLocal's.
else
valueSource = ValueSource::forFlushFormat(node->variableAccessData()->flushFormat());
// FIXME: Don't emit SetLocal(Dead). https://bugs.webkit.org/show_bug.cgi?id=108019
m_stream->appendAndLog(VariableEvent::setLocal(virtualRegisterForLocal(i), valueSource.dataFormat()));
format = dataFormatFor(variable->flushFormat());
m_stream->appendAndLog(
VariableEvent::setLocal(virtualRegisterForLocal(i), variable->local(), format));
}
m_lastSetOperand = VirtualRegister();
......@@ -1650,7 +1653,7 @@ void SpeculativeJIT::compileCurrentBlock()
case ZombieHint: {
m_lastSetOperand = m_currentNode->local();
m_stream->appendAndLog(VariableEvent::setLocal(m_currentNode->local(), DataFormatDead));
recordSetLocal(DataFormatDead);
break;
}
......
......@@ -2185,9 +2185,16 @@ public:
// flag is cleared, indicating no further code generation should take place.
bool m_compileOkay;
void recordSetLocal(VirtualRegister operand, ValueSource valueSource)
void recordSetLocal(
VirtualRegister bytecodeReg, VirtualRegister machineReg, DataFormat format)
{
m_stream->appendAndLog(VariableEvent::setLocal(operand, valueSource.dataFormat()));
m_stream->appendAndLog(VariableEvent::setLocal(bytecodeReg, machineReg, format));
}
void recordSetLocal(DataFormat format)
{
VariableAccessData* variable = m_currentNode->variableAccessData();
recordSetLocal(variable->local(), variable->local(), format);
}
GenerationInfo& generationInfoFromVirtualRegister(VirtualRegister virtualRegister)
......
......@@ -2026,7 +2026,7 @@ void SpeculativeJIT::compile(Node* node)
// Indicate that it's no longer necessary to retrieve the value of
// this bytecode variable from registers or other locations in the stack,
// but that it is stored as a double.
recordSetLocal(node->local(), ValueSource(DoubleInJSStack));
recordSetLocal(DataFormatDouble);
break;
}
......@@ -2034,7 +2034,7 @@ void SpeculativeJIT::compile(Node* node)
SpeculateInt32Operand value(this, node->child1());
m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->local()));
noResult(node);
recordSetLocal(node->local(), ValueSource(Int32InJSStack));
recordSetLocal(DataFormatInt32);
break;
}
......@@ -2043,7 +2043,7 @@ void SpeculativeJIT::compile(Node* node)
GPRReg cellGPR = cell.gpr();
m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node->local()));
noResult(node);
recordSetLocal(node->local(), ValueSource(CellInJSStack));
recordSetLocal(DataFormatCell);
break;
}
......@@ -2051,7 +2051,7 @@ void SpeculativeJIT::compile(Node* node)
SpeculateBooleanOperand value(this, node->child1());
m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->local()));
noResult(node);
recordSetLocal(node->local(), ValueSource(BooleanInJSStack));
recordSetLocal(DataFormatBoolean);
break;
}
......@@ -2060,7 +2060,7 @@ void SpeculativeJIT::compile(Node* node)
SpeculateDoubleOperand value(this, node->child1(), ManualOperandSpeculation);
m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->local()));
noResult(node);
recordSetLocal(node->local(), ValueSource(DoubleInJSStack));
recordSetLocal(DataFormatDouble);
break;
}
......@@ -2068,7 +2068,7 @@ void SpeculativeJIT::compile(Node* node)
m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node->local()));
m_jit.store32(value.tagGPR(), JITCompiler::tagFor(node->local()));
noResult(node);
recordSetLocal(node->local(), ValueSource(ValueInJSStack));
recordSetLocal(DataFormatJS);
// If we're storing an arguments object that has been optimized away,
// our variable event stream for OSR exit now reflects the optimized
......
......@@ -2333,7 +2333,7 @@ void SpeculativeJIT::compile(Node* node)
// Indicate that it's no longer necessary to retrieve the value of
// this bytecode variable from registers or other locations in the stack,
// but that it is stored as a double.
recordSetLocal(node->local(), ValueSource(DoubleInJSStack));
recordSetLocal(DataFormatDouble);
break;
}
......@@ -2341,7 +2341,7 @@ void SpeculativeJIT::compile(Node* node)
SpeculateInt32Operand value(this, node->child1());
m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->local()));
noResult(node);
recordSetLocal(node->local(), ValueSource(Int32InJSStack));
recordSetLocal(DataFormatInt32);
break;
}
......@@ -2349,7 +2349,7 @@ void SpeculativeJIT::compile(Node* node)
SpeculateInt52Operand value(this, node->child1());
m_jit.store64(value.gpr(), JITCompiler::addressFor(node->local()));
noResult(node);
recordSetLocal(node->local(), ValueSource(Int52InJSStack));
recordSetLocal(DataFormatInt52);
break;
}
......@@ -2358,7 +2358,7 @@ void SpeculativeJIT::compile(Node* node)
GPRReg cellGPR = cell.gpr();
m_jit.store64(cellGPR, JITCompiler::addressFor(node->local()));
noResult(node);
recordSetLocal(node->local(), ValueSource(CellInJSStack));
recordSetLocal(DataFormatCell);
break;
}
......@@ -2366,7 +2366,7 @@ void SpeculativeJIT::compile(Node* node)
SpeculateBooleanOperand boolean(this, node->child1());
m_jit.store64(boolean.gpr(), JITCompiler::addressFor(node->local()));
noResult(node);
recordSetLocal(node->local(), ValueSource(BooleanInJSStack));
recordSetLocal(DataFormatBoolean);
break;
}
......@@ -2375,7 +2375,7 @@ void SpeculativeJIT::compile(Node* node)
m_jit.store64(value.gpr(), JITCompiler::addressFor(node->local()));
noResult(node);
recordSetLocal(node->local(), ValueSource(ValueInJSStack));
recordSetLocal(DataFormatJS);
// If we're storing an arguments object that has been optimized away,
// our variable event stream for OSR exit now reflects the optimized
......
......@@ -40,22 +40,22 @@ void ValueSource::dump(PrintStream& out) const
out.print("IsDead");
break;
case ValueInJSStack:
out.print("InStack");
out.print("JS:r", virtualRegister());
break;
case Int32InJSStack:
out.print("Int32");
out.print("Int32:r", virtualRegister());
break;
case Int52InJSStack:
out.print("Int52");
out.print("Int52:r", virtualRegister());
break;
case CellInJSStack:
out.print("Cell");
out.print("Cell:r", virtualRegister());
break;
case BooleanInJSStack:
out.print("Bool");
out.print("Bool:r", virtualRegister());
break;
case DoubleInJSStack:
out.print("Double");
out.print("Double:r", virtualRegister());
break;
case ArgumentsSource:
out.print("Arguments");
......
......@@ -115,59 +115,67 @@ static inline bool isTriviallyRecoverable(ValueSourceKind kind)
class ValueSource {
public:
ValueSource()
: m_value(idFromKind(SourceNotSet))
: m_kind(SourceNotSet)
{
}
explicit ValueSource(ValueSourceKind valueSourceKind)
: m_value(idFromKind(valueSourceKind))
: m_kind(valueSourceKind)
{
ASSERT(kind() != SourceNotSet);
ASSERT(kind() != HaveNode);
ASSERT(kind() == ArgumentsSource || kind() == SourceIsDead);
}
explicit ValueSource(MinifiedID id)
: m_value(id)
: m_kind(HaveNode)
, m_value(id.bits())
{
ASSERT(!!id);
ASSERT(kind() == HaveNode);
}
static ValueSource forFlushFormat(FlushFormat format)
ValueSource(ValueSourceKind valueSourceKind, VirtualRegister where)
: m_kind(valueSourceKind)
, m_value(static_cast<intptr_t>(where.offset()))
{
ASSERT(kind() != SourceNotSet);
ASSERT(kind() != HaveNode);
}
static ValueSource forFlushFormat(VirtualRegister where, FlushFormat format)
{
switch (format) {
case DeadFlush:
return ValueSource(SourceIsDead);
case FlushedJSValue:
return ValueSource(ValueInJSStack);
return ValueSource(ValueInJSStack, where);
case FlushedDouble:
return ValueSource(DoubleInJSStack);
return ValueSource(DoubleInJSStack, where);
case FlushedInt32:
return ValueSource(Int32InJSStack);
return ValueSource(Int32InJSStack, where);
case FlushedInt52:
return ValueSource(Int52InJSStack);
return ValueSource(Int52InJSStack, where);
case FlushedCell:
return ValueSource(CellInJSStack);
return ValueSource(CellInJSStack, where);
case FlushedBoolean:
return ValueSource(BooleanInJSStack);
return ValueSource(BooleanInJSStack, where);
}
RELEASE_ASSERT_NOT_REACHED();
return ValueSource();
}
static ValueSource forDataFormat(DataFormat dataFormat)
static ValueSource forDataFormat(VirtualRegister where, DataFormat dataFormat)
{
return ValueSource(dataFormatToValueSourceKind(dataFormat));
return ValueSource(dataFormatToValueSourceKind(dataFormat), where);
}
bool isSet() const
{
return kindFromID(m_value) != SourceNotSet;
return kind() != SourceNotSet;
}
ValueSourceKind kind() const
{
return kindFromID(m_value);
return m_kind;
}
bool isInJSStack() const { return JSC::DFG::isInJSStack(kind()); }
......@@ -178,7 +186,7 @@ public:
return valueSourceKindToDataFormat(kind());
}
ValueRecovery valueRecovery(int operand) const
ValueRecovery valueRecovery() const
{
ASSERT(isTriviallyRecoverable());
switch (kind()) {
......@@ -189,34 +197,27 @@ public:
return ValueRecovery::argumentsThatWereNotCreated();
default:
return ValueRecovery::displacedInJSStack(VirtualRegister(operand), dataFormat());
return ValueRecovery::displacedInJSStack(virtualRegister(), dataFormat());
}
}
MinifiedID id() const
{
ASSERT(kind() == HaveNode);
return m_value;
return MinifiedID::fromBits(m_value);
}
void dump(PrintStream&) const;
private:
static MinifiedID idFromKind(ValueSourceKind kind)
VirtualRegister virtualRegister() const
{
ASSERT(kind >= SourceNotSet && kind < HaveNode);
return MinifiedID::fromBits(MinifiedID::invalidID() - kind);
ASSERT(isInJSStack());
return VirtualRegister(m_value);
}
static ValueSourceKind kindFromID(MinifiedID id)
{
uintptr_t kind = static_cast<uintptr_t>(MinifiedID::invalidID() - id.m_id);
if (kind >= static_cast<uintptr_t>(HaveNode))
return HaveNode;
return static_cast<ValueSourceKind>(kind);
}
void dump(PrintStream&) const;
MinifiedID m_value;
private:
ValueSourceKind m_kind;
uintptr_t m_value;
};
} } // namespace JSC::DFG
......
......@@ -55,10 +55,12 @@ void VariableEvent::dump(PrintStream& out) const
out.print("Death(", id(), ")");
break;
case MovHintEvent:
out.print("MovHint(", id(), ", r", operand(), ")");
out.print("MovHint(", id(), ", r", bytecodeRegister(), ")");
break;
case SetLocalEvent:
out.printf("SetLocal(r%d, %s)", operand(), dataFormatToString(dataFormat()));
out.print(
"SetLocal(machine:r", machineRegister(), " -> bytecode:r", bytecodeRegister(),
", ", dataFormatToString(dataFormat()), ")");
break;
default:
RELEASE_ASSERT_NOT_REACHED();
......@@ -82,7 +84,7 @@ void VariableEvent::dumpFillInfo(const char* name, PrintStream& out) const
void VariableEvent::dumpSpillInfo(const char* name, PrintStream& out) const
{
out.print(name, "(", id(), ", r", virtualRegister(), ", ", dataFormatToString(dataFormat()), ")");
out.print(name, "(", id(), ", r", spillRegister(), ", ", dataFormatToString(dataFormat()), ")");
}
} } // namespace JSC::DFG
......
......@@ -61,8 +61,7 @@ enum VariableEventKind {
// but that it has not been stored into that operand.
MovHintEvent,
// A SetLocalEvent means that a node's value has actually been stored into the
// bytecode operand that it's associated with.
// A SetLocalEvent means that a node's value has been stored into the stack.
SetLocalEvent,
// Used to indicate an uninitialized VariableEvent. Don't use for other
......@@ -104,8 +103,8 @@ public:
ASSERT(!(dataFormat & DataFormatJS));
#endif
VariableEvent event;
event.m_id = id;
event.u.gpr = gpr;
event.m_which.id = id.bits();
event.m_representation.gpr = gpr;
event.m_kind = kind;
event.m_dataFormat = dataFormat;
return event;
......@@ -116,9 +115,9 @@ public:
{
ASSERT(kind == BirthToFill || kind == Fill);
VariableEvent event;
event.m_id = id;
event.u.pair.tagGPR = tagGPR;
event.u.pair.payloadGPR = payloadGPR;
event.m_which.id = id.bits();
event.m_representation.pair.tagGPR = tagGPR;
event.m_representation.pair.payloadGPR = payloadGPR;
event.m_kind = kind;
event.m_dataFormat = DataFormatJS;
return event;
......@@ -129,8 +128,8 @@ public:
{
ASSERT(kind == BirthToFill || kind == Fill);
VariableEvent event;
event.m_id = id;
event.u.fpr = fpr;
event.m_which.id = id.bits();
event.m_representation.fpr = fpr;
event.m_kind = kind;
event.m_dataFormat = DataFormatDouble;
return event;
......@@ -140,8 +139,8 @@ public:
{
ASSERT(kind == BirthToSpill || kind == Spill);
VariableEvent event;
event.m_id = id;
event.u.virtualReg = virtualRegister.offset();
event.m_which.id = id.bits();
event.m_representation.virtualReg = virtualRegister.offset();
event.m_kind = kind;
event.m_dataFormat = format;
return event;
......@@ -150,25 +149,27 @@ public:
static VariableEvent death(MinifiedID id)
{
VariableEvent event;
event.m_id = id;
event.m_which.id = id.bits();
event.m_kind = Death;
return event;
}
static VariableEvent setLocal(VirtualRegister virtualRegister, DataFormat format)
static VariableEvent setLocal(
VirtualRegister bytecodeReg, VirtualRegister machineReg, DataFormat format)
{
VariableEvent event;
event.u.virtualReg = virtualRegister.offset();
event.m_which.virtualReg = machineReg.offset();
event.m_representation.virtualReg = bytecodeReg.offset();
event.m_kind = SetLocalEvent;
event.m_dataFormat = format;
return event;
}
static VariableEvent movHint(MinifiedID id, int operand)
static VariableEvent movHint(MinifiedID id, VirtualRegister bytecodeReg)
{
VariableEvent event;
event.m_id = id;<