blob: 353fd702211b52a650878807b8bf73d1f7a2b493 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#pragma once
#if ENABLE(DFG_JIT)
#include "DFGCommon.h"
#include "DFGFlushFormat.h"
#include "DFGMinifiedID.h"
#include "DataFormat.h"
#include "SpeculatedType.h"
#include "ValueRecovery.h"
namespace JSC { namespace DFG {
enum ValueSourceKind {
SourceNotSet,
ValueInJSStack,
Int32InJSStack,
Int52InJSStack,
CellInJSStack,
BooleanInJSStack,
DoubleInJSStack,
SourceIsDead,
HaveNode
};
static inline ValueSourceKind dataFormatToValueSourceKind(DataFormat dataFormat)
{
switch (dataFormat) {
case DataFormatInt32:
return Int32InJSStack;
case DataFormatInt52:
return Int52InJSStack;
case DataFormatDouble:
return DoubleInJSStack;
case DataFormatBoolean:
return BooleanInJSStack;
case DataFormatCell:
return CellInJSStack;
case DataFormatDead:
return SourceIsDead;
default:
RELEASE_ASSERT(dataFormat & DataFormatJS);
return ValueInJSStack;
}
}
static inline DataFormat valueSourceKindToDataFormat(ValueSourceKind kind)
{
switch (kind) {
case ValueInJSStack:
return DataFormatJS;
case Int32InJSStack:
return DataFormatInt32;
case Int52InJSStack:
return DataFormatInt52;
case CellInJSStack:
return DataFormatCell;
case BooleanInJSStack:
return DataFormatBoolean;
case DoubleInJSStack:
return DataFormatDouble;
case SourceIsDead:
return DataFormatDead;
default:
return DataFormatNone;
}
}
static inline bool isInJSStack(ValueSourceKind kind)
{
DataFormat format = valueSourceKindToDataFormat(kind);
return format != DataFormatNone && format < DataFormatOSRMarker;
}
// Can this value be recovered without having to look at register allocation state or
// DFG node liveness?
static inline bool isTriviallyRecoverable(ValueSourceKind kind)
{
return valueSourceKindToDataFormat(kind) != DataFormatNone;
}
class ValueSource {
public:
ValueSource()
: m_kind(SourceNotSet)
{
}
explicit ValueSource(ValueSourceKind valueSourceKind)
: m_kind(valueSourceKind)
{
ASSERT(kind() == SourceIsDead);
}
explicit ValueSource(MinifiedID id)
: m_kind(HaveNode)
, m_value(id.bits())
{
ASSERT(!!id);
ASSERT(kind() == HaveNode);
}
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:
case ConflictingFlush:
return ValueSource(SourceIsDead);
case FlushedJSValue:
return ValueSource(ValueInJSStack, where);
case FlushedDouble:
return ValueSource(DoubleInJSStack, where);
case FlushedInt32:
return ValueSource(Int32InJSStack, where);
case FlushedInt52:
return ValueSource(Int52InJSStack, where);
case FlushedCell:
return ValueSource(CellInJSStack, where);
case FlushedBoolean:
return ValueSource(BooleanInJSStack, where);
}
RELEASE_ASSERT_NOT_REACHED();
return ValueSource();
}
static ValueSource forDataFormat(VirtualRegister where, DataFormat dataFormat)
{
return ValueSource(dataFormatToValueSourceKind(dataFormat), where);
}
bool isSet() const
{
return kind() != SourceNotSet;
}
bool operator!() const { return !isSet(); }
ValueSourceKind kind() const
{
return m_kind;
}
bool isInJSStack() const { return JSC::DFG::isInJSStack(kind()); }
bool isTriviallyRecoverable() const { return JSC::DFG::isTriviallyRecoverable(kind()); }
DataFormat dataFormat() const
{
return valueSourceKindToDataFormat(kind());
}
ValueRecovery valueRecovery() const
{
ASSERT(isTriviallyRecoverable());
switch (kind()) {
case SourceIsDead:
return ValueRecovery::constant(jsUndefined());
default:
return ValueRecovery::displacedInJSStack(virtualRegister(), dataFormat());
}
}
MinifiedID id() const
{
ASSERT(kind() == HaveNode);
return MinifiedID::fromBits(m_value);
}
VirtualRegister virtualRegister() const
{
ASSERT(isInJSStack());
return VirtualRegister(m_value);
}
void dump(PrintStream&) const;
void dumpInContext(PrintStream&, DumpContext*) const;
private:
ValueSourceKind m_kind;
uintptr_t m_value;
};
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)