|  | /* | 
|  | * Copyright (C) 2011, 2013-2015 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 "DFGFlushFormat.h" | 
|  | #include "DFGMinifiedID.h" | 
|  | #include "DataFormat.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(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; | 
|  | unsigned m_value; | 
|  | }; | 
|  |  | 
|  | } } // namespace JSC::DFG | 
|  |  | 
|  | #endif // ENABLE(DFG_JIT) |