blob: 7c9922c906ab44d7b0375f569fcf3e25e4f8d8e6 [file] [log] [blame]
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#if ENABLE(DFG_JIT)
#include "DFGMinifiedID.h"
#include "DataFormat.h"
#include "MacroAssembler.h"
#include "Operands.h"
#include "VirtualRegister.h"
#include <stdio.h>
namespace JSC { namespace DFG {
enum VariableEventKind : uint8_t {
// Marks the beginning of a checkpoint. If you interpret the variable
// events starting at a Reset point then you'll get everything you need.
Reset,
// Node births. Points in the code where a node becomes relevant for OSR.
// It may be the point where it is actually born (i.e. assigned) or it may
// be a later point, if it's only later in the sequence of instructions
// that we start to care about this node.
BirthToFill,
BirthToSpill,
Birth,
// Events related to how a node is represented.
Fill,
Spill,
// Death of a node - after this we no longer care about this node.
Death,
// A MovHintEvent means that a node is being associated with a bytecode operand,
// but that it has not been stored into that operand.
MovHintEvent,
// 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
// purposes.
InvalidEventKind
};
union VariableRepresentation {
VariableRepresentation()
: operand()
{ }
MacroAssembler::RegisterID gpr;
MacroAssembler::FPRegisterID fpr;
#if USE(JSVALUE32_64)
struct {
MacroAssembler::RegisterID tagGPR;
MacroAssembler::RegisterID payloadGPR;
} pair;
#endif
Operand operand;
};
class VariableEvent {
public:
VariableEvent()
: m_kind(InvalidEventKind)
{
}
static VariableEvent reset()
{
VariableEvent event;
event.m_kind = Reset;
return event;
}
static VariableEvent fillGPR(VariableEventKind kind, MinifiedID id, MacroAssembler::RegisterID gpr, DataFormat dataFormat)
{
ASSERT(kind == BirthToFill || kind == Fill);
ASSERT(dataFormat != DataFormatDouble);
#if USE(JSVALUE32_64)
ASSERT(!(dataFormat & DataFormatJS));
#endif
VariableEvent event;
WhichType which;
which.id = id.bits();
VariableRepresentation representation;
representation.gpr = gpr;
event.m_kind = kind;
event.m_dataFormat = dataFormat;
event.m_which = WTFMove(which);
event.m_representation = WTFMove(representation);
return event;
}
#if USE(JSVALUE32_64)
static VariableEvent fillPair(VariableEventKind kind, MinifiedID id, MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR)
{
ASSERT(kind == BirthToFill || kind == Fill);
VariableEvent event;
WhichType which;
which.id = id.bits();
VariableRepresentation representation;
representation.pair.tagGPR = tagGPR;
representation.pair.payloadGPR = payloadGPR;
event.m_kind = kind;
event.m_dataFormat = DataFormatJS;
event.m_which = WTFMove(which);
event.m_representation = WTFMove(representation);
return event;
}
#endif // USE(JSVALUE32_64)
static VariableEvent fillFPR(VariableEventKind kind, MinifiedID id, MacroAssembler::FPRegisterID fpr)
{
ASSERT(kind == BirthToFill || kind == Fill);
VariableEvent event;
WhichType which;
which.id = id.bits();
VariableRepresentation representation;
representation.fpr = fpr;
event.m_kind = kind;
event.m_dataFormat = DataFormatDouble;
event.m_which = WTFMove(which);
event.m_representation = WTFMove(representation);
return event;
}
static VariableEvent birth(MinifiedID id)
{
VariableEvent event;
WhichType which;
which.id = id.bits();
event.m_kind = Birth;
event.m_which = WTFMove(which);
return event;
}
static VariableEvent spill(VariableEventKind kind, MinifiedID id, VirtualRegister virtualRegister, DataFormat format)
{
ASSERT(kind == BirthToSpill || kind == Spill);
VariableEvent event;
WhichType which;
which.id = id.bits();
VariableRepresentation representation;
representation.operand = virtualRegister;
event.m_kind = kind;
event.m_dataFormat = format;
event.m_which = WTFMove(which);
event.m_representation = WTFMove(representation);
return event;
}
static VariableEvent death(MinifiedID id)
{
VariableEvent event;
WhichType which;
which.id = id.bits();
event.m_kind = Death;
event.m_which = WTFMove(which);
return event;
}
static VariableEvent setLocal(
Operand bytecodeOperand, VirtualRegister machineReg, DataFormat format)
{
VariableEvent event;
WhichType which;
which.virtualReg = machineReg.offset();
VariableRepresentation representation;
representation.operand = bytecodeOperand;
event.m_kind = SetLocalEvent;
event.m_dataFormat = format;
event.m_which = WTFMove(which);
event.m_representation = WTFMove(representation);
return event;
}
static VariableEvent movHint(MinifiedID id, Operand bytecodeReg)
{
VariableEvent event;
WhichType which;
which.id = id.bits();
VariableRepresentation representation;
representation.operand = bytecodeReg;
event.m_kind = MovHintEvent;
event.m_which = WTFMove(which);
event.m_representation = WTFMove(representation);
return event;
}
VariableEventKind kind() const
{
return static_cast<VariableEventKind>(m_kind);
}
MinifiedID id() const
{
ASSERT(
m_kind == BirthToFill || m_kind == Fill || m_kind == BirthToSpill || m_kind == Spill
|| m_kind == Death || m_kind == MovHintEvent || m_kind == Birth);
return MinifiedID::fromBits(m_which.get().id);
}
DataFormat dataFormat() const
{
ASSERT(
m_kind == BirthToFill || m_kind == Fill || m_kind == BirthToSpill || m_kind == Spill
|| m_kind == SetLocalEvent);
return m_dataFormat;
}
MacroAssembler::RegisterID gpr() const
{
ASSERT(m_kind == BirthToFill || m_kind == Fill);
ASSERT(m_dataFormat);
ASSERT(m_dataFormat != DataFormatDouble);
#if USE(JSVALUE32_64)
ASSERT(!(m_dataFormat & DataFormatJS));
#endif
return m_representation.get().gpr;
}
#if USE(JSVALUE32_64)
MacroAssembler::RegisterID tagGPR() const
{
ASSERT(m_kind == BirthToFill || m_kind == Fill);
ASSERT(m_dataFormat & DataFormatJS);
return m_representation.get().pair.tagGPR;
}
MacroAssembler::RegisterID payloadGPR() const
{
ASSERT(m_kind == BirthToFill || m_kind == Fill);
ASSERT(m_dataFormat & DataFormatJS);
return m_representation.get().pair.payloadGPR;
}
#endif // USE(JSVALUE32_64)
MacroAssembler::FPRegisterID fpr() const
{
ASSERT(m_kind == BirthToFill || m_kind == Fill);
ASSERT(m_dataFormat == DataFormatDouble);
return m_representation.get().fpr;
}
VirtualRegister spillRegister() const
{
ASSERT(m_kind == BirthToSpill || m_kind == Spill);
return m_representation.get().operand.virtualRegister();
}
Operand operand() const
{
ASSERT(m_kind == SetLocalEvent || m_kind == MovHintEvent);
return m_representation.get().operand;
}
VirtualRegister machineRegister() const
{
ASSERT(m_kind == SetLocalEvent);
return VirtualRegister(m_which.get().virtualReg);
}
VariableRepresentation variableRepresentation() const { return m_representation.get(); }
void dump(PrintStream&) const;
private:
void dumpFillInfo(const char* name, PrintStream&) const;
void dumpSpillInfo(const char* name, PrintStream&) const;
union WhichType {
int virtualReg;
unsigned id;
};
Packed<WhichType> m_which;
// For BirthToFill, Fill:
// - The GPR or FPR, or a GPR pair.
// For BirthToSpill, Spill:
// - The virtual register.
// For MovHintEvent, SetLocalEvent:
// - The bytecode operand.
// For Death:
// - Unused.
Packed<VariableRepresentation> m_representation;
VariableEventKind m_kind;
DataFormat m_dataFormat { DataFormatNone };
};
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)