1/*
2 * Copyright (C) 2012 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 DFGVariableEvent_h
27#define DFGVariableEvent_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 "MacroAssembler.h"
37#include <stdio.h>
38
39namespace JSC { namespace DFG {
40
41enum VariableEventKind {
42    // Marks the beginning of a checkpoint. If you interpret the variable
43    // events starting at a Reset point then you'll get everything you need.
44    Reset,
45
46    // Node births. Points in the code where a node becomes relevant for OSR.
47    // It may be the point where it is actually born (i.e. assigned) or it may
48    // be a later point, if it's only later in the sequence of instructions
49    // that we start to care about this node.
50    BirthToFill,
51    BirthToSpill,
52
53    // Events related to how a node is represented.
54    Fill,
55    Spill,
56
57    // Death of a node - after this we no longer care about this node.
58    Death,
59
60    // A MovHintEvent means that a node is being associated with a bytecode operand,
61    // but that it has not been stored into that operand.
62    MovHintEvent,
63
64    // A SetLocalEvent means that a node's value has actually been stored into the
65    // bytecode operand that it's associated with.
66    SetLocalEvent,
67
68    // Used to indicate an uninitialized VariableEvent. Don't use for other
69    // purposes.
70    InvalidEventKind
71};
72
73union VariableRepresentation {
74    MacroAssembler::RegisterID gpr;
75    MacroAssembler::FPRegisterID fpr;
76#if USE(JSVALUE32_64)
77    struct {
78        MacroAssembler::RegisterID tagGPR;
79        MacroAssembler::RegisterID payloadGPR;
80    } pair;
81#endif
82    int32_t virtualReg;
83};
84
85class VariableEvent {
86public:
87    VariableEvent()
88        : m_kind(InvalidEventKind)
89    {
90    }
91
92    static VariableEvent reset()
93    {
94        VariableEvent event;
95        event.m_kind = Reset;
96        return event;
97    }
98
99    static VariableEvent fillGPR(VariableEventKind kind, MinifiedID id, MacroAssembler::RegisterID gpr, DataFormat dataFormat)
100    {
101        ASSERT(kind == BirthToFill || kind == Fill);
102        ASSERT(dataFormat != DataFormatDouble);
103#if USE(JSVALUE32_64)
104        ASSERT(!(dataFormat & DataFormatJS));
105#endif
106        VariableEvent event;
107        event.m_id = id;
108        event.u.gpr = gpr;
109        event.m_kind = kind;
110        event.m_dataFormat = dataFormat;
111        return event;
112    }
113
114#if USE(JSVALUE32_64)
115    static VariableEvent fillPair(VariableEventKind kind, MinifiedID id, MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR)
116    {
117        ASSERT(kind == BirthToFill || kind == Fill);
118        VariableEvent event;
119        event.m_id = id;
120        event.u.pair.tagGPR = tagGPR;
121        event.u.pair.payloadGPR = payloadGPR;
122        event.m_kind = kind;
123        event.m_dataFormat = DataFormatJS;
124        return event;
125    }
126#endif // USE(JSVALUE32_64)
127
128    static VariableEvent fillFPR(VariableEventKind kind, MinifiedID id, MacroAssembler::FPRegisterID fpr)
129    {
130        ASSERT(kind == BirthToFill || kind == Fill);
131        VariableEvent event;
132        event.m_id = id;
133        event.u.fpr = fpr;
134        event.m_kind = kind;
135        event.m_dataFormat = DataFormatDouble;
136        return event;
137    }
138
139    static VariableEvent spill(VariableEventKind kind, MinifiedID id, VirtualRegister virtualRegister, DataFormat format)
140    {
141        ASSERT(kind == BirthToSpill || kind == Spill);
142        VariableEvent event;
143        event.m_id = id;
144        event.u.virtualReg = virtualRegister;
145        event.m_kind = kind;
146        event.m_dataFormat = format;
147        return event;
148    }
149
150    static VariableEvent death(MinifiedID id)
151    {
152        VariableEvent event;
153        event.m_id = id;
154        event.m_kind = Death;
155        return event;
156    }
157
158    static VariableEvent setLocal(int operand, DataFormat format)
159    {
160        VariableEvent event;
161        event.u.virtualReg = operand;
162        event.m_kind = SetLocalEvent;
163        event.m_dataFormat = format;
164        return event;
165    }
166
167    static VariableEvent movHint(MinifiedID id, int operand)
168    {
169        VariableEvent event;
170        event.m_id = id;
171        event.u.virtualReg = operand;
172        event.m_kind = MovHintEvent;
173        return event;
174    }
175
176    VariableEventKind kind() const
177    {
178        return static_cast<VariableEventKind>(m_kind);
179    }
180
181    MinifiedID id() const
182    {
183        ASSERT(m_kind == BirthToFill || m_kind == Fill
184               || m_kind == BirthToSpill || m_kind == Spill
185               || m_kind == Death || m_kind == MovHintEvent);
186        return m_id;
187    }
188
189    DataFormat dataFormat() const
190    {
191        ASSERT(m_kind == BirthToFill || m_kind == Fill
192               || m_kind == BirthToSpill || m_kind == Spill
193               || m_kind == SetLocalEvent);
194        return static_cast<DataFormat>(m_dataFormat);
195    }
196
197    MacroAssembler::RegisterID gpr() const
198    {
199        ASSERT(m_kind == BirthToFill || m_kind == Fill);
200        ASSERT(m_dataFormat);
201        ASSERT(m_dataFormat != DataFormatDouble);
202#if USE(JSVALUE32_64)
203        ASSERT(!(m_dataFormat & DataFormatJS));
204#endif
205        return u.gpr;
206    }
207
208#if USE(JSVALUE32_64)
209    MacroAssembler::RegisterID tagGPR() const
210    {
211        ASSERT(m_kind == BirthToFill || m_kind == Fill);
212        ASSERT(m_dataFormat & DataFormatJS);
213        return u.pair.tagGPR;
214    }
215    MacroAssembler::RegisterID payloadGPR() const
216    {
217        ASSERT(m_kind == BirthToFill || m_kind == Fill);
218        ASSERT(m_dataFormat & DataFormatJS);
219        return u.pair.payloadGPR;
220    }
221#endif // USE(JSVALUE32_64)
222
223    MacroAssembler::FPRegisterID fpr() const
224    {
225        ASSERT(m_kind == BirthToFill || m_kind == Fill);
226        ASSERT(m_dataFormat == DataFormatDouble);
227        return u.fpr;
228    }
229
230    VirtualRegister virtualRegister() const
231    {
232        ASSERT(m_kind == BirthToSpill || m_kind == Spill);
233        return static_cast<VirtualRegister>(u.virtualReg);
234    }
235
236    int operand() const
237    {
238        ASSERT(m_kind == SetLocalEvent || m_kind == MovHintEvent);
239        return u.virtualReg;
240    }
241
242    const VariableRepresentation& variableRepresentation() const { return u; }
243
244    void dump(PrintStream&) const;
245
246private:
247    void dumpFillInfo(const char* name, PrintStream&) const;
248    void dumpSpillInfo(const char* name, PrintStream&) const;
249
250    MinifiedID m_id;
251
252    // For BirthToFill, Fill:
253    //   - The GPR or FPR, or a GPR pair.
254    // For BirthToSpill, Spill:
255    //   - The virtual register.
256    // For MovHintEvent, SetLocalEvent:
257    //   - The bytecode operand.
258    // For Death:
259    //   - Unused.
260    VariableRepresentation u;
261
262    int8_t m_kind;
263    int8_t m_dataFormat;
264};
265
266} } // namespace JSC::DFG
267
268#endif // ENABLE(DFG_JIT)
269
270#endif // DFGVariableEvent_h
271
272