1/*
2 * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef DFGValueSource_h
27#define DFGValueSource_h
28
29#include <wtf/Platform.h>
30
31#if ENABLE(DFG_JIT)
32
33#include "DFGCommon.h"
34#include "DFGMinifiedID.h"
35#include "DataFormat.h"
36#include "SpeculatedType.h"
37#include "ValueRecovery.h"
38
39namespace JSC { namespace DFG {
40
41enum ValueSourceKind {
42    SourceNotSet,
43    ValueInJSStack,
44    Int32InJSStack,
45    CellInJSStack,
46    BooleanInJSStack,
47    DoubleInJSStack,
48    ArgumentsSource,
49    SourceIsDead,
50    HaveNode
51};
52
53static inline ValueSourceKind dataFormatToValueSourceKind(DataFormat dataFormat)
54{
55    switch (dataFormat) {
56    case DataFormatInteger:
57        return Int32InJSStack;
58    case DataFormatDouble:
59        return DoubleInJSStack;
60    case DataFormatBoolean:
61        return BooleanInJSStack;
62    case DataFormatCell:
63        return CellInJSStack;
64    case DataFormatDead:
65        return SourceIsDead;
66    case DataFormatArguments:
67        return ArgumentsSource;
68    default:
69        RELEASE_ASSERT(dataFormat & DataFormatJS);
70        return ValueInJSStack;
71    }
72}
73
74static inline DataFormat valueSourceKindToDataFormat(ValueSourceKind kind)
75{
76    switch (kind) {
77    case ValueInJSStack:
78        return DataFormatJS;
79    case Int32InJSStack:
80        return DataFormatInteger;
81    case CellInJSStack:
82        return DataFormatCell;
83    case BooleanInJSStack:
84        return DataFormatBoolean;
85    case DoubleInJSStack:
86        return DataFormatDouble;
87    case ArgumentsSource:
88        return DataFormatArguments;
89    case SourceIsDead:
90        return DataFormatDead;
91    default:
92        return DataFormatNone;
93    }
94}
95
96static inline bool isInJSStack(ValueSourceKind kind)
97{
98    DataFormat format = valueSourceKindToDataFormat(kind);
99    return format != DataFormatNone && format < DataFormatOSRMarker;
100}
101
102// Can this value be recovered without having to look at register allocation state or
103// DFG node liveness?
104static inline bool isTriviallyRecoverable(ValueSourceKind kind)
105{
106    return valueSourceKindToDataFormat(kind) != DataFormatNone;
107}
108
109class ValueSource {
110public:
111    ValueSource()
112        : m_value(idFromKind(SourceNotSet))
113    {
114    }
115
116    explicit ValueSource(ValueSourceKind valueSourceKind)
117        : m_value(idFromKind(valueSourceKind))
118    {
119        ASSERT(kind() != SourceNotSet);
120        ASSERT(kind() != HaveNode);
121    }
122
123    explicit ValueSource(MinifiedID id)
124        : m_value(id)
125    {
126        ASSERT(!!id);
127        ASSERT(kind() == HaveNode);
128    }
129
130    static ValueSource forSpeculation(SpeculatedType prediction)
131    {
132        if (isInt32Speculation(prediction))
133            return ValueSource(Int32InJSStack);
134        if (isArraySpeculation(prediction) || isCellSpeculation(prediction))
135            return ValueSource(CellInJSStack);
136        if (isBooleanSpeculation(prediction))
137            return ValueSource(BooleanInJSStack);
138        return ValueSource(ValueInJSStack);
139    }
140
141    static ValueSource forDataFormat(DataFormat dataFormat)
142    {
143        return ValueSource(dataFormatToValueSourceKind(dataFormat));
144    }
145
146    bool isSet() const
147    {
148        return kindFromID(m_value) != SourceNotSet;
149    }
150
151    ValueSourceKind kind() const
152    {
153        return kindFromID(m_value);
154    }
155
156    bool isInJSStack() const { return JSC::DFG::isInJSStack(kind()); }
157    bool isTriviallyRecoverable() const { return JSC::DFG::isTriviallyRecoverable(kind()); }
158
159    DataFormat dataFormat() const
160    {
161        return valueSourceKindToDataFormat(kind());
162    }
163
164    ValueRecovery valueRecovery() const
165    {
166        ASSERT(isTriviallyRecoverable());
167        switch (kind()) {
168        case ValueInJSStack:
169            return ValueRecovery::alreadyInJSStack();
170
171        case Int32InJSStack:
172            return ValueRecovery::alreadyInJSStackAsUnboxedInt32();
173
174        case CellInJSStack:
175            return ValueRecovery::alreadyInJSStackAsUnboxedCell();
176
177        case BooleanInJSStack:
178            return ValueRecovery::alreadyInJSStackAsUnboxedBoolean();
179
180        case DoubleInJSStack:
181            return ValueRecovery::alreadyInJSStackAsUnboxedDouble();
182
183        case SourceIsDead:
184            return ValueRecovery::constant(jsUndefined());
185
186        case ArgumentsSource:
187            return ValueRecovery::argumentsThatWereNotCreated();
188
189        default:
190            RELEASE_ASSERT_NOT_REACHED();
191            return ValueRecovery();
192        }
193    }
194
195    MinifiedID id() const
196    {
197        ASSERT(kind() == HaveNode);
198        return m_value;
199    }
200
201    void dump(PrintStream&) const;
202
203private:
204    static MinifiedID idFromKind(ValueSourceKind kind)
205    {
206        ASSERT(kind >= SourceNotSet && kind < HaveNode);
207        return MinifiedID::fromBits(MinifiedID::invalidID() - kind);
208    }
209
210    static ValueSourceKind kindFromID(MinifiedID id)
211    {
212        uintptr_t kind = static_cast<uintptr_t>(MinifiedID::invalidID() - id.m_id);
213        if (kind >= static_cast<uintptr_t>(HaveNode))
214            return HaveNode;
215        return static_cast<ValueSourceKind>(kind);
216    }
217
218    MinifiedID m_value;
219};
220
221} } // namespace JSC::DFG
222
223#endif // ENABLE(DFG_JIT)
224
225#endif // DFGValueSource_h
226
227