1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=4 sw=4 et tw=99:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
18 : * May 28, 2008.
19 : *
20 : * The Initial Developer of the Original Code is
21 : * Brendan Eich <brendan@mozilla.org>
22 : *
23 : * Contributor(s):
24 : * David Anderson <danderson@mozilla.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #if !defined jsjaeger_valueinfo_h__ && defined JS_METHODJIT
41 : #define jsjaeger_valueinfo_h__
42 :
43 : #include "jsapi.h"
44 : #include "jsnum.h"
45 : #include "jstypes.h"
46 : #include "methodjit/MachineRegs.h"
47 : #include "methodjit/RematInfo.h"
48 : #include "assembler/assembler/MacroAssembler.h"
49 :
50 : namespace js {
51 : namespace mjit {
52 :
53 : class FrameEntry
54 40806 : {
55 : friend class FrameState;
56 : friend class ImmutableSync;
57 :
58 : public:
59 :
60 : /* Accessors for entries which are known constants. */
61 :
62 18126229 : bool isConstant() const {
63 18126229 : if (isCopy())
64 946278 : return false;
65 17179951 : return data.isConstant();
66 : }
67 :
68 : const jsval_layout &getConstant() const {
69 : JS_ASSERT(isConstant());
70 : return v_;
71 : }
72 :
73 1186940 : Value getValue() const {
74 1186940 : JS_ASSERT(isConstant());
75 1186940 : return IMPL_TO_JSVAL(v_);
76 : }
77 :
78 : #if defined JS_NUNBOX32
79 1228493 : uint32_t getPayload() const {
80 1228493 : JS_ASSERT(isConstant());
81 1228493 : return v_.s.payload.u32;
82 : }
83 : #elif defined JS_PUNBOX64
84 : uint64_t getPayload() const {
85 : JS_ASSERT(isConstant());
86 : return v_.asBits & JSVAL_PAYLOAD_MASK;
87 : }
88 : #endif
89 :
90 : /* For a constant double FrameEntry, truncate to an int32. */
91 1086 : void convertConstantDoubleToInt32(JSContext *cx) {
92 1086 : JS_ASSERT(isType(JSVAL_TYPE_DOUBLE) && isConstant());
93 : int32_t value;
94 1086 : ToInt32(cx, getValue(), &value);
95 :
96 1086 : Value newValue = Int32Value(value);
97 1086 : setConstant(newValue);
98 1086 : }
99 :
100 : /*
101 : * Accessors for entries whose type is known. Any entry can have a known
102 : * type, and constant entries must have one.
103 : */
104 :
105 57562455 : bool isTypeKnown() const {
106 57562455 : return backing()->type.isConstant();
107 : }
108 :
109 : /*
110 : * The known type should not be used in generated code if it is JSVAL_TYPE_DOUBLE.
111 : * In such cases either the value is constant, in memory or in a floating point register.
112 : */
113 13747166 : JSValueType getKnownType() const {
114 13747166 : JS_ASSERT(isTypeKnown());
115 13747166 : return backing()->knownType;
116 : }
117 :
118 : #if defined JS_NUNBOX32
119 1229595 : JSValueTag getKnownTag() const {
120 1229595 : JS_ASSERT(backing()->v_.s.tag != JSVAL_TAG_CLEAR);
121 1229595 : return backing()->v_.s.tag;
122 : }
123 : #elif defined JS_PUNBOX64
124 : JSValueShiftedTag getKnownTag() const {
125 : return JSValueShiftedTag(backing()->v_.asBits & JSVAL_TAG_MASK);
126 : }
127 : #endif
128 :
129 : // Return true iff the type of this value is definitely known to be type_.
130 33910282 : bool isType(JSValueType type_) const {
131 33910282 : return isTypeKnown() && getKnownType() == type_;
132 : }
133 :
134 : // Return true iff the type of this value is definitely known not to be type_.
135 898030 : bool isNotType(JSValueType type_) const {
136 898030 : return isTypeKnown() && getKnownType() != type_;
137 : }
138 :
139 : // Return true if the type of this value is definitely type_, or is unknown
140 : // and thus potentially type_ at runtime.
141 243456 : bool mightBeType(JSValueType type_) const {
142 243456 : return !isNotType(type_);
143 : }
144 :
145 : /* Accessors for entries which are copies of other mutable entries. */
146 :
147 553368983 : bool isCopy() const { return !!copy; }
148 4927126 : bool isCopied() const { return copied != 0; }
149 :
150 73934554 : const FrameEntry *backing() const {
151 73934554 : return isCopy() ? copyOf() : this;
152 : }
153 :
154 80012 : bool hasSameBacking(const FrameEntry *other) const {
155 80012 : return backing() == other->backing();
156 : }
157 :
158 : private:
159 728665 : void setType(JSValueType type_) {
160 728665 : JS_ASSERT(!isCopy() && type_ != JSVAL_TYPE_UNKNOWN);
161 728665 : type.setConstant();
162 : #if defined JS_NUNBOX32
163 728665 : v_.s.tag = JSVAL_TYPE_TO_TAG(type_);
164 : #elif defined JS_PUNBOX64
165 : v_.asBits &= JSVAL_PAYLOAD_MASK;
166 : v_.asBits |= JSVAL_TYPE_TO_SHIFTED_TAG(type_);
167 : #endif
168 728665 : knownType = type_;
169 728665 : }
170 :
171 1392539 : void track(uint32_t index) {
172 1392539 : copied = 0;
173 1392539 : copy = NULL;
174 1392539 : index_ = index;
175 1392539 : tracked = true;
176 1392539 : }
177 :
178 13609932 : void clear() {
179 13609932 : JS_ASSERT(copied == 0);
180 13609932 : if (copy) {
181 769256 : JS_ASSERT(copy->copied != 0);
182 769256 : copy->copied--;
183 769256 : copy = NULL;
184 : }
185 13609932 : }
186 :
187 411511095 : uint32_t trackerIndex() {
188 411511095 : return index_;
189 : }
190 :
191 : /*
192 : * Marks the FE as unsynced & invalid.
193 : */
194 2252214 : void resetUnsynced() {
195 2252214 : clear();
196 2252214 : type.unsync();
197 2252214 : data.unsync();
198 2252214 : type.invalidate();
199 2252214 : data.invalidate();
200 2252214 : }
201 :
202 : /*
203 : * Marks the FE as synced & in memory.
204 : */
205 1786637 : void resetSynced() {
206 1786637 : clear();
207 1786637 : type.setMemory();
208 1786637 : data.setMemory();
209 1786637 : }
210 :
211 : /*
212 : * Marks the FE as having a constant.
213 : */
214 1404162 : void setConstant(const Value &v) {
215 1404162 : clear();
216 1404162 : type.unsync();
217 1404162 : data.unsync();
218 1404162 : type.setConstant();
219 1404162 : data.setConstant();
220 1404162 : v_ = JSVAL_TO_IMPL(v);
221 1404162 : if (v.isDouble())
222 10474 : knownType = JSVAL_TYPE_DOUBLE;
223 : else
224 1393688 : knownType = v.extractNonDoubleType();
225 1404162 : }
226 :
227 13278075 : FrameEntry *copyOf() const {
228 13278075 : JS_ASSERT(isCopy());
229 13278075 : JS_ASSERT_IF(!copy->temporary, copy < this);
230 13278075 : return copy;
231 : }
232 :
233 : /*
234 : * Set copy index.
235 : */
236 830980 : void setCopyOf(FrameEntry *fe) {
237 830980 : clear();
238 830980 : copy = fe;
239 830980 : if (fe) {
240 773364 : type.invalidate();
241 773364 : data.invalidate();
242 773364 : fe->copied++;
243 : }
244 830980 : }
245 :
246 36535809 : inline bool isTracked() const {
247 36535809 : return tracked;
248 : }
249 :
250 1392295 : inline void untrack() {
251 1392295 : tracked = false;
252 1392295 : }
253 :
254 60670 : inline bool dataInRegister(AnyRegisterID reg) const {
255 60670 : JS_ASSERT(!copy);
256 60670 : return reg.isReg()
257 158898 : ? (data.inRegister() && data.reg() == reg.reg())
258 219568 : : (data.inFPRegister() && data.fpreg() == reg.fpreg());
259 : }
260 :
261 : private:
262 : JSValueType knownType;
263 : jsval_layout v_;
264 : RematInfo type;
265 : RematInfo data;
266 : uint32_t index_;
267 : FrameEntry *copy;
268 : bool tracked;
269 : bool temporary;
270 :
271 : /* Number of copies of this entry. */
272 : uint32_t copied;
273 :
274 : /*
275 : * Offset of the last loop in which this entry was written or had a loop
276 : * register assigned.
277 : */
278 : uint32_t lastLoop;
279 : };
280 :
281 : } /* namespace mjit */
282 : } /* namespace js */
283 :
284 : #endif /* jsjaeger_valueinfo_h__ */
285 :
|