2 * Copyright (C) 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef DFGArrayMode_h
27 #define DFGArrayMode_h
29 #include <wtf/Platform.h>
33 #include "ArrayProfile.h"
34 #include "DFGNodeFlags.h"
35 #include "SpeculatedType.h"
47 // Use a namespace + enum instead of enum alone to avoid the namespace collision
48 // that would otherwise occur, since we say things like "Int8Array" and "JSArray"
49 // in lots of other places, to mean subtly different things.
57 SelectUsingPredictions
, // Implies that we need predictions to decide. We will never get to the backend in this mode.
58 Unprofiled
, // Implies that array profiling didn't see anything. But that could be because the operands didn't comply with basic type assumptions (base is cell, property is int). This either becomes Generic or ForceExit depending on value profiling.
59 ForceExit
, // Implies that we have no idea how to execute this operation, so we should just give up.
83 NonArray
, // Definitely some object that is not a JSArray.
84 Array
, // Definitely a JSArray, and may or may not have custom properties or have undergone some other bizarre transitions.
85 OriginalArray
, // Definitely a JSArray, and still has one of the primordial JSArray structures for the global object that this code block (possibly inlined code block) belongs to.
86 PossiblyArray
// Some object that may or may not be a JSArray.
90 SaneChain
, // In bounds and the array prototype chain is still intact, i.e. loading a hole doesn't require special treatment.
91 InBounds
, // In bounds and not loading a hole.
92 ToHole
, // Potentially storing to a hole.
93 OutOfBounds
// Out-of-bounds access and anything can happen.
102 const char* arrayTypeToString(Array::Type
);
103 const char* arrayClassToString(Array::Class
);
104 const char* arraySpeculationToString(Array::Speculation
);
105 const char* arrayConversionToString(Array::Conversion
);
111 u
.asBytes
.type
= Array::SelectUsingPredictions
;
112 u
.asBytes
.arrayClass
= Array::NonArray
;
113 u
.asBytes
.speculation
= Array::InBounds
;
114 u
.asBytes
.conversion
= Array::AsIs
;
117 explicit ArrayMode(Array::Type type
)
119 u
.asBytes
.type
= type
;
120 u
.asBytes
.arrayClass
= Array::NonArray
;
121 u
.asBytes
.speculation
= Array::InBounds
;
122 u
.asBytes
.conversion
= Array::AsIs
;
125 ArrayMode(Array::Type type
, Array::Class arrayClass
, Array::Speculation speculation
, Array::Conversion conversion
)
127 u
.asBytes
.type
= type
;
128 u
.asBytes
.arrayClass
= arrayClass
;
129 u
.asBytes
.speculation
= speculation
;
130 u
.asBytes
.conversion
= conversion
;
133 ArrayMode(Array::Type type
, Array::Class arrayClass
, Array::Conversion conversion
)
135 u
.asBytes
.type
= type
;
136 u
.asBytes
.arrayClass
= arrayClass
;
137 u
.asBytes
.speculation
= Array::InBounds
;
138 u
.asBytes
.conversion
= conversion
;
141 Array::Type
type() const { return static_cast<Array::Type
>(u
.asBytes
.type
); }
142 Array::Class
arrayClass() const { return static_cast<Array::Class
>(u
.asBytes
.arrayClass
); }
143 Array::Speculation
speculation() const { return static_cast<Array::Speculation
>(u
.asBytes
.speculation
); }
144 Array::Conversion
conversion() const { return static_cast<Array::Conversion
>(u
.asBytes
.conversion
); }
146 unsigned asWord() const { return u
.asWord
; }
148 static ArrayMode
fromWord(unsigned word
)
150 return ArrayMode(word
);
153 static ArrayMode
fromObserved(ArrayProfile
*, Array::Action
, bool makeSafe
);
155 ArrayMode
withSpeculation(Array::Speculation speculation
) const
157 return ArrayMode(type(), arrayClass(), speculation
, conversion());
160 ArrayMode
withProfile(ArrayProfile
* profile
, bool makeSafe
) const
162 Array::Speculation mySpeculation
;
163 Array::Class myArrayClass
;
166 mySpeculation
= Array::OutOfBounds
;
167 else if (profile
->mayStoreToHole())
168 mySpeculation
= Array::ToHole
;
170 mySpeculation
= Array::InBounds
;
173 if (profile
->usesOriginalArrayStructures() && benefitsFromOriginalArray())
174 myArrayClass
= Array::OriginalArray
;
176 myArrayClass
= Array::Array
;
178 myArrayClass
= arrayClass();
180 return ArrayMode(type(), myArrayClass
, mySpeculation
, conversion());
183 ArrayMode
withType(Array::Type type
) const
185 return ArrayMode(type
, arrayClass(), speculation(), conversion());
188 ArrayMode
withConversion(Array::Conversion conversion
) const
190 return ArrayMode(type(), arrayClass(), speculation(), conversion
);
193 ArrayMode
withTypeAndConversion(Array::Type type
, Array::Conversion conversion
) const
195 return ArrayMode(type
, arrayClass(), speculation(), conversion
);
198 ArrayMode
refine(SpeculatedType base
, SpeculatedType index
, SpeculatedType value
= SpecNone
, NodeFlags
= 0) const;
200 bool alreadyChecked(Graph
&, Node
*, AbstractValue
&) const;
202 void dump(PrintStream
&) const;
204 bool usesButterfly() const
209 case Array::Contiguous
:
210 case Array::ArrayStorage
:
211 case Array::SlowPutArrayStorage
:
218 bool isJSArray() const
220 switch (arrayClass()) {
222 case Array::OriginalArray
:
229 bool isJSArrayWithOriginalStructure() const
231 return arrayClass() == Array::OriginalArray
;
234 bool isSaneChain() const
236 return speculation() == Array::SaneChain
;
239 bool isInBounds() const
241 switch (speculation()) {
242 case Array::SaneChain
:
243 case Array::InBounds
:
250 bool mayStoreToHole() const
252 return !isInBounds();
255 bool isOutOfBounds() const
257 return speculation() == Array::OutOfBounds
;
260 bool isSlowPut() const
262 return type() == Array::SlowPutArrayStorage
;
265 bool canCSEStorage() const
268 case Array::SelectUsingPredictions
:
269 case Array::Unprofiled
:
270 case Array::ForceExit
:
272 case Array::Arguments
:
279 bool lengthNeedsStorage() const
284 ArrayMode
modeForPut() const
288 return ArrayMode(Array::Generic
);
289 #if USE(JSVALUE32_64)
290 case Array::Arguments
:
291 return ArrayMode(Array::Generic
);
298 bool isSpecific() const
301 case Array::SelectUsingPredictions
:
302 case Array::Unprofiled
:
303 case Array::ForceExit
:
305 case Array::Undecided
:
312 bool supportsLength() const
315 case Array::SelectUsingPredictions
:
316 case Array::Unprofiled
:
317 case Array::ForceExit
:
322 case Array::Contiguous
:
323 case Array::ArrayStorage
:
324 case Array::SlowPutArrayStorage
:
331 bool benefitsFromOriginalArray() const
336 case Array::Contiguous
:
337 case Array::ArrayStorage
:
344 // Returns 0 if this is not OriginalArray.
345 Structure
* originalArrayStructure(Graph
&, const CodeOrigin
&) const;
346 Structure
* originalArrayStructure(Graph
&, Node
*) const;
348 bool benefitsFromStructureCheck() const
351 case Array::SelectUsingPredictions
:
352 // It might benefit from structure checks! If it ends up not benefiting, we can just
353 // remove it. The FixupPhase does this: if it finds a CheckStructure just before an
354 // array op and it had turned that array op into either generic or conversion mode,
355 // it will remove the CheckStructure.
357 case Array::Unprofiled
:
358 case Array::ForceExit
:
362 return conversion() == Array::AsIs
;
366 bool doesConversion() const
368 return conversion() != Array::AsIs
;
371 ArrayModes
arrayModesThatPassFiltering() const
375 return ALL_ARRAY_MODES
;
377 return arrayModesWithIndexingShape(Int32Shape
);
379 return arrayModesWithIndexingShape(DoubleShape
);
380 case Array::Contiguous
:
381 return arrayModesWithIndexingShape(ContiguousShape
);
382 case Array::ArrayStorage
:
383 return arrayModesWithIndexingShape(ArrayStorageShape
);
384 case Array::SlowPutArrayStorage
:
385 return arrayModesWithIndexingShape(SlowPutArrayStorageShape
);
387 return asArrayModes(NonArray
);
391 bool getIndexedPropertyStorageMayTriggerGC() const
393 return type() == Array::String
;
396 bool operator==(const ArrayMode
& other
) const
398 return type() == other
.type()
399 && arrayClass() == other
.arrayClass()
400 && speculation() == other
.speculation()
401 && conversion() == other
.conversion();
404 bool operator!=(const ArrayMode
& other
) const
406 return !(*this == other
);
409 explicit ArrayMode(unsigned word
)
414 ArrayModes
arrayModesWithIndexingShape(IndexingType shape
) const
416 switch (arrayClass()) {
417 case Array::NonArray
:
418 return asArrayModes(shape
);
420 case Array::OriginalArray
:
421 return asArrayModes(shape
| IsArray
);
422 case Array::PossiblyArray
:
423 return asArrayModes(shape
) | asArrayModes(shape
| IsArray
);
425 // This is only necessary for C++ compilers that don't understand enums.
430 bool alreadyChecked(Graph
&, Node
*, AbstractValue
&, IndexingType shape
) const;
443 static inline bool canCSEStorage(const ArrayMode
& arrayMode
)
445 return arrayMode
.canCSEStorage();
448 static inline bool lengthNeedsStorage(const ArrayMode
& arrayMode
)
450 return arrayMode
.lengthNeedsStorage();
453 } } // namespace JSC::DFG
458 void printInternal(PrintStream
&, JSC::DFG::Array::Type
);
459 void printInternal(PrintStream
&, JSC::DFG::Array::Class
);
460 void printInternal(PrintStream
&, JSC::DFG::Array::Speculation
);
461 void printInternal(PrintStream
&, JSC::DFG::Array::Conversion
);
465 #endif // ENABLE(DFG_JIT)
467 #endif // DFGArrayMode_h