2 * Copyright (C) 2012-2015 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.
27 #include "DFGArrayMode.h"
31 #include "DFGAbstractValue.h"
33 #include "JSCInlines.h"
35 namespace JSC
{ namespace DFG
{
37 ArrayMode
ArrayMode::fromObserved(const ConcurrentJITLocker
& locker
, ArrayProfile
* profile
, Array::Action action
, bool makeSafe
)
39 Array::Class nonArray
;
40 if (profile
->usesOriginalArrayStructures(locker
))
41 nonArray
= Array::OriginalNonArray
;
43 nonArray
= Array::NonArray
;
45 ArrayModes observed
= profile
->observedArrayModes(locker
);
48 return ArrayMode(Array::Unprofiled
);
49 case asArrayModes(NonArray
):
50 if (action
== Array::Write
&& !profile
->mayInterceptIndexedAccesses(locker
))
51 return ArrayMode(Array::Undecided
, nonArray
, Array::OutOfBounds
, Array::Convert
);
52 return ArrayMode(Array::SelectUsingPredictions
, nonArray
).withSpeculationFromProfile(locker
, profile
, makeSafe
);
54 case asArrayModes(ArrayWithUndecided
):
55 if (action
== Array::Write
)
56 return ArrayMode(Array::Undecided
, Array::Array
, Array::OutOfBounds
, Array::Convert
);
57 return ArrayMode(Array::Generic
);
59 case asArrayModes(NonArray
) | asArrayModes(ArrayWithUndecided
):
60 if (action
== Array::Write
&& !profile
->mayInterceptIndexedAccesses(locker
))
61 return ArrayMode(Array::Undecided
, Array::PossiblyArray
, Array::OutOfBounds
, Array::Convert
);
62 return ArrayMode(Array::SelectUsingPredictions
).withSpeculationFromProfile(locker
, profile
, makeSafe
);
64 case asArrayModes(NonArrayWithInt32
):
65 return ArrayMode(Array::Int32
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
66 case asArrayModes(ArrayWithInt32
):
67 return ArrayMode(Array::Int32
, Array::Array
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
68 case asArrayModes(NonArrayWithInt32
) | asArrayModes(ArrayWithInt32
):
69 return ArrayMode(Array::Int32
, Array::PossiblyArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
71 case asArrayModes(NonArrayWithDouble
):
72 return ArrayMode(Array::Double
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
73 case asArrayModes(ArrayWithDouble
):
74 return ArrayMode(Array::Double
, Array::Array
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
75 case asArrayModes(NonArrayWithDouble
) | asArrayModes(ArrayWithDouble
):
76 return ArrayMode(Array::Double
, Array::PossiblyArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
78 case asArrayModes(NonArrayWithContiguous
):
79 return ArrayMode(Array::Contiguous
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
80 case asArrayModes(ArrayWithContiguous
):
81 return ArrayMode(Array::Contiguous
, Array::Array
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
82 case asArrayModes(NonArrayWithContiguous
) | asArrayModes(ArrayWithContiguous
):
83 return ArrayMode(Array::Contiguous
, Array::PossiblyArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
85 case asArrayModes(NonArrayWithArrayStorage
):
86 return ArrayMode(Array::ArrayStorage
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
87 case asArrayModes(NonArrayWithSlowPutArrayStorage
):
88 case asArrayModes(NonArrayWithArrayStorage
) | asArrayModes(NonArrayWithSlowPutArrayStorage
):
89 return ArrayMode(Array::SlowPutArrayStorage
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
90 case asArrayModes(ArrayWithArrayStorage
):
91 return ArrayMode(Array::ArrayStorage
, Array::Array
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
92 case asArrayModes(ArrayWithSlowPutArrayStorage
):
93 case asArrayModes(ArrayWithArrayStorage
) | asArrayModes(ArrayWithSlowPutArrayStorage
):
94 return ArrayMode(Array::SlowPutArrayStorage
, Array::Array
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
95 case asArrayModes(NonArrayWithArrayStorage
) | asArrayModes(ArrayWithArrayStorage
):
96 return ArrayMode(Array::ArrayStorage
, Array::PossiblyArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
97 case asArrayModes(NonArrayWithSlowPutArrayStorage
) | asArrayModes(ArrayWithSlowPutArrayStorage
):
98 case asArrayModes(NonArrayWithArrayStorage
) | asArrayModes(ArrayWithArrayStorage
) | asArrayModes(NonArrayWithSlowPutArrayStorage
) | asArrayModes(ArrayWithSlowPutArrayStorage
):
99 return ArrayMode(Array::SlowPutArrayStorage
, Array::PossiblyArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
101 return ArrayMode(Array::Int8Array
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
103 return ArrayMode(Array::Int16Array
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
105 return ArrayMode(Array::Int32Array
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
107 return ArrayMode(Array::Uint8Array
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
108 case Uint8ClampedArrayMode
:
109 return ArrayMode(Array::Uint8ClampedArray
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
110 case Uint16ArrayMode
:
111 return ArrayMode(Array::Uint16Array
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
112 case Uint32ArrayMode
:
113 return ArrayMode(Array::Uint32Array
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
114 case Float32ArrayMode
:
115 return ArrayMode(Array::Float32Array
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
116 case Float64ArrayMode
:
117 return ArrayMode(Array::Float64Array
, nonArray
, Array::AsIs
).withProfile(locker
, profile
, makeSafe
);
120 if ((observed
& asArrayModes(NonArray
)) && profile
->mayInterceptIndexedAccesses(locker
))
121 return ArrayMode(Array::SelectUsingPredictions
).withSpeculationFromProfile(locker
, profile
, makeSafe
);
124 Array::Class arrayClass
;
126 if (shouldUseSlowPutArrayStorage(observed
))
127 type
= Array::SlowPutArrayStorage
;
128 else if (shouldUseFastArrayStorage(observed
))
129 type
= Array::ArrayStorage
;
130 else if (shouldUseContiguous(observed
))
131 type
= Array::Contiguous
;
132 else if (shouldUseDouble(observed
))
133 type
= Array::Double
;
134 else if (shouldUseInt32(observed
))
137 type
= Array::Undecided
;
139 if (hasSeenArray(observed
) && hasSeenNonArray(observed
))
140 arrayClass
= Array::PossiblyArray
;
141 else if (hasSeenArray(observed
))
142 arrayClass
= Array::Array
;
143 else if (hasSeenNonArray(observed
))
144 arrayClass
= nonArray
;
146 arrayClass
= Array::PossiblyArray
;
148 return ArrayMode(type
, arrayClass
, Array::Convert
).withProfile(locker
, profile
, makeSafe
);
152 ArrayMode
ArrayMode::refine(
153 Graph
& graph
, Node
* node
,
154 SpeculatedType base
, SpeculatedType index
, SpeculatedType value
) const
156 if (!base
|| !index
) {
157 // It can be that we had a legitimate arrayMode but no incoming predictions. That'll
158 // happen if we inlined code based on, say, a global variable watchpoint, but later
159 // realized that the callsite could not have possibly executed. It may be worthwhile
160 // to fix that, but for now I'm leaving it as-is.
161 return ArrayMode(Array::ForceExit
);
164 if (!isInt32Speculation(index
))
165 return ArrayMode(Array::Generic
);
167 // If we had exited because of an exotic object behavior, then don't try to specialize.
168 if (graph
.hasExitSite(node
->origin
.semantic
, ExoticObjectMode
))
169 return ArrayMode(Array::Generic
);
171 // Note: our profiling currently doesn't give us good information in case we have
172 // an unlikely control flow path that sets the base to a non-cell value. Value
173 // profiling and prediction propagation will probably tell us that the value is
174 // either a cell or not, but that doesn't tell us which is more likely: that this
175 // is an array access on a cell (what we want and can optimize) or that the user is
176 // doing a crazy by-val access on a primitive (we can't easily optimize this and
177 // don't want to). So, for now, we assume that if the base is not a cell according
178 // to value profiling, but the array profile tells us something else, then we
179 // should just trust the array profile.
182 case Array::Undecided
:
184 return withType(Array::ForceExit
);
185 if (isInt32Speculation(value
))
186 return withTypeAndConversion(Array::Int32
, Array::Convert
);
187 if (isFullNumberSpeculation(value
))
188 return withTypeAndConversion(Array::Double
, Array::Convert
);
189 return withTypeAndConversion(Array::Contiguous
, Array::Convert
);
192 if (!value
|| isInt32Speculation(value
))
194 if (isFullNumberSpeculation(value
))
195 return withTypeAndConversion(Array::Double
, Array::Convert
);
196 return withTypeAndConversion(Array::Contiguous
, Array::Convert
);
199 if (!value
|| isFullNumberSpeculation(value
))
201 return withTypeAndConversion(Array::Contiguous
, Array::Convert
);
203 case Array::Contiguous
:
206 case Array::Int8Array
:
207 case Array::Int16Array
:
208 case Array::Int32Array
:
209 case Array::Uint8Array
:
210 case Array::Uint8ClampedArray
:
211 case Array::Uint16Array
:
212 case Array::Uint32Array
:
213 case Array::Float32Array
:
214 case Array::Float64Array
:
215 switch (node
->op()) {
217 if (graph
.hasExitSite(node
->origin
.semantic
, OutOfBounds
) || !isInBounds())
218 return withSpeculation(Array::OutOfBounds
);
219 return withSpeculation(Array::InBounds
);
221 return withSpeculation(Array::InBounds
);
224 case Array::Unprofiled
:
225 case Array::SelectUsingPredictions
: {
228 if (isStringSpeculation(base
))
229 return withType(Array::String
);
231 if (isDirectArgumentsSpeculation(base
) || isScopedArgumentsSpeculation(base
)) {
232 // Handle out-of-bounds accesses as generic accesses.
233 if (graph
.hasExitSite(node
->origin
.semantic
, OutOfBounds
) || !isInBounds())
234 return ArrayMode(Array::Generic
);
236 if (isDirectArgumentsSpeculation(base
))
237 return withType(Array::DirectArguments
);
238 return withType(Array::ScopedArguments
);
242 switch (node
->op()) {
244 if (graph
.hasExitSite(node
->origin
.semantic
, OutOfBounds
) || !isInBounds())
245 result
= withSpeculation(Array::OutOfBounds
);
247 result
= withSpeculation(Array::InBounds
);
251 result
= withSpeculation(Array::InBounds
);
255 if (isInt8ArraySpeculation(base
))
256 return result
.withType(Array::Int8Array
);
258 if (isInt16ArraySpeculation(base
))
259 return result
.withType(Array::Int16Array
);
261 if (isInt32ArraySpeculation(base
))
262 return result
.withType(Array::Int32Array
);
264 if (isUint8ArraySpeculation(base
))
265 return result
.withType(Array::Uint8Array
);
267 if (isUint8ClampedArraySpeculation(base
))
268 return result
.withType(Array::Uint8ClampedArray
);
270 if (isUint16ArraySpeculation(base
))
271 return result
.withType(Array::Uint16Array
);
273 if (isUint32ArraySpeculation(base
))
274 return result
.withType(Array::Uint32Array
);
276 if (isFloat32ArraySpeculation(base
))
277 return result
.withType(Array::Float32Array
);
279 if (isFloat64ArraySpeculation(base
))
280 return result
.withType(Array::Float64Array
);
282 if (type() == Array::Unprofiled
)
283 return ArrayMode(Array::ForceExit
);
284 return ArrayMode(Array::Generic
);
292 Structure
* ArrayMode::originalArrayStructure(Graph
& graph
, const CodeOrigin
& codeOrigin
) const
294 JSGlobalObject
* globalObject
= graph
.globalObjectFor(codeOrigin
);
296 switch (arrayClass()) {
297 case Array::OriginalArray
: {
300 return globalObject
->originalArrayStructureForIndexingType(ArrayWithInt32
);
302 return globalObject
->originalArrayStructureForIndexingType(ArrayWithDouble
);
303 case Array::Contiguous
:
304 return globalObject
->originalArrayStructureForIndexingType(ArrayWithContiguous
);
305 case Array::ArrayStorage
:
306 return globalObject
->originalArrayStructureForIndexingType(ArrayWithArrayStorage
);
313 case Array::OriginalNonArray
: {
314 TypedArrayType type
= typedArrayType();
315 if (type
== NotTypedArray
)
318 return globalObject
->typedArrayStructure(type
);
326 Structure
* ArrayMode::originalArrayStructure(Graph
& graph
, Node
* node
) const
328 return originalArrayStructure(graph
, node
->origin
.semantic
);
331 bool ArrayMode::alreadyChecked(Graph
& graph
, Node
* node
, const AbstractValue
& value
, IndexingType shape
) const
333 switch (arrayClass()) {
334 case Array::OriginalArray
: {
335 if (value
.m_structure
.isTop())
337 for (unsigned i
= value
.m_structure
.size(); i
--;) {
338 Structure
* structure
= value
.m_structure
[i
];
339 if ((structure
->indexingType() & IndexingShapeMask
) != shape
)
341 if (!(structure
->indexingType() & IsArray
))
343 if (!graph
.globalObjectFor(node
->origin
.semantic
)->isOriginalArrayStructure(structure
))
350 if (arrayModesAlreadyChecked(value
.m_arrayModes
, asArrayModes(shape
| IsArray
)))
352 if (value
.m_structure
.isTop())
354 for (unsigned i
= value
.m_structure
.size(); i
--;) {
355 Structure
* structure
= value
.m_structure
[i
];
356 if ((structure
->indexingType() & IndexingShapeMask
) != shape
)
358 if (!(structure
->indexingType() & IsArray
))
365 if (arrayModesAlreadyChecked(value
.m_arrayModes
, asArrayModes(shape
) | asArrayModes(shape
| IsArray
)))
367 if (value
.m_structure
.isTop())
369 for (unsigned i
= value
.m_structure
.size(); i
--;) {
370 Structure
* structure
= value
.m_structure
[i
];
371 if ((structure
->indexingType() & IndexingShapeMask
) != shape
)
378 bool ArrayMode::alreadyChecked(Graph
& graph
, Node
* node
, const AbstractValue
& value
) const
384 case Array::ForceExit
:
388 return speculationChecked(value
.m_type
, SpecString
);
391 return alreadyChecked(graph
, node
, value
, Int32Shape
);
394 return alreadyChecked(graph
, node
, value
, DoubleShape
);
396 case Array::Contiguous
:
397 return alreadyChecked(graph
, node
, value
, ContiguousShape
);
399 case Array::ArrayStorage
:
400 return alreadyChecked(graph
, node
, value
, ArrayStorageShape
);
402 case Array::SlowPutArrayStorage
:
403 switch (arrayClass()) {
404 case Array::OriginalArray
: {
410 if (arrayModesAlreadyChecked(value
.m_arrayModes
, asArrayModes(ArrayWithArrayStorage
) | asArrayModes(ArrayWithSlowPutArrayStorage
)))
412 if (value
.m_structure
.isTop())
414 for (unsigned i
= value
.m_structure
.size(); i
--;) {
415 Structure
* structure
= value
.m_structure
[i
];
416 if (!hasAnyArrayStorage(structure
->indexingType()))
418 if (!(structure
->indexingType() & IsArray
))
425 if (arrayModesAlreadyChecked(value
.m_arrayModes
, asArrayModes(NonArrayWithArrayStorage
) | asArrayModes(ArrayWithArrayStorage
) | asArrayModes(NonArrayWithSlowPutArrayStorage
) | asArrayModes(ArrayWithSlowPutArrayStorage
)))
427 if (value
.m_structure
.isTop())
429 for (unsigned i
= value
.m_structure
.size(); i
--;) {
430 Structure
* structure
= value
.m_structure
[i
];
431 if (!hasAnyArrayStorage(structure
->indexingType()))
437 case Array::DirectArguments
:
438 return speculationChecked(value
.m_type
, SpecDirectArguments
);
440 case Array::ScopedArguments
:
441 return speculationChecked(value
.m_type
, SpecScopedArguments
);
443 case Array::Int8Array
:
444 return speculationChecked(value
.m_type
, SpecInt8Array
);
446 case Array::Int16Array
:
447 return speculationChecked(value
.m_type
, SpecInt16Array
);
449 case Array::Int32Array
:
450 return speculationChecked(value
.m_type
, SpecInt32Array
);
452 case Array::Uint8Array
:
453 return speculationChecked(value
.m_type
, SpecUint8Array
);
455 case Array::Uint8ClampedArray
:
456 return speculationChecked(value
.m_type
, SpecUint8ClampedArray
);
458 case Array::Uint16Array
:
459 return speculationChecked(value
.m_type
, SpecUint16Array
);
461 case Array::Uint32Array
:
462 return speculationChecked(value
.m_type
, SpecUint32Array
);
464 case Array::Float32Array
:
465 return speculationChecked(value
.m_type
, SpecFloat32Array
);
467 case Array::Float64Array
:
468 return speculationChecked(value
.m_type
, SpecFloat64Array
);
470 case Array::SelectUsingPredictions
:
471 case Array::Unprofiled
:
472 case Array::Undecided
:
480 const char* arrayTypeToString(Array::Type type
)
483 case Array::SelectUsingPredictions
:
484 return "SelectUsingPredictions";
485 case Array::Unprofiled
:
489 case Array::ForceExit
:
493 case Array::Undecided
:
499 case Array::Contiguous
:
501 case Array::ArrayStorage
:
502 return "ArrayStorage";
503 case Array::SlowPutArrayStorage
:
504 return "SlowPutArrayStorage";
505 case Array::DirectArguments
:
506 return "DirectArguments";
507 case Array::ScopedArguments
:
508 return "ScopedArguments";
509 case Array::Int8Array
:
511 case Array::Int16Array
:
513 case Array::Int32Array
:
515 case Array::Uint8Array
:
517 case Array::Uint8ClampedArray
:
518 return "Uint8ClampedArray";
519 case Array::Uint16Array
:
520 return "Uint16Array";
521 case Array::Uint32Array
:
522 return "Uint32Array";
523 case Array::Float32Array
:
524 return "Float32Array";
525 case Array::Float64Array
:
526 return "Float64Array";
528 // Better to return something then it is to crash. Remember, this method
529 // is being called from our main diagnostic tool, the IR dumper. It's like
530 // a stack trace. So if we get here then probably something has already
536 const char* arrayClassToString(Array::Class arrayClass
)
538 switch (arrayClass
) {
541 case Array::OriginalArray
:
542 return "OriginalArray";
543 case Array::NonArray
:
545 case Array::OriginalNonArray
:
546 return "OriginalNonArray";
547 case Array::PossiblyArray
:
548 return "PossiblyArray";
554 const char* arraySpeculationToString(Array::Speculation speculation
)
556 switch (speculation
) {
557 case Array::SaneChain
:
559 case Array::InBounds
:
563 case Array::OutOfBounds
:
564 return "OutOfBounds";
570 const char* arrayConversionToString(Array::Conversion conversion
)
572 switch (conversion
) {
582 IndexingType
toIndexingShape(Array::Type type
)
589 case Array::Contiguous
:
590 return ContiguousShape
;
591 case Array::ArrayStorage
:
592 return ArrayStorageShape
;
593 case Array::SlowPutArrayStorage
:
594 return SlowPutArrayStorageShape
;
596 return NoIndexingShape
;
600 TypedArrayType
toTypedArrayType(Array::Type type
)
603 case Array::Int8Array
:
605 case Array::Int16Array
:
607 case Array::Int32Array
:
609 case Array::Uint8Array
:
611 case Array::Uint8ClampedArray
:
612 return TypeUint8Clamped
;
613 case Array::Uint16Array
:
615 case Array::Uint32Array
:
617 case Array::Float32Array
:
619 case Array::Float64Array
:
622 return NotTypedArray
;
626 Array::Type
toArrayType(TypedArrayType type
)
630 return Array::Int8Array
;
632 return Array::Int16Array
;
634 return Array::Int32Array
;
636 return Array::Uint8Array
;
637 case TypeUint8Clamped
:
638 return Array::Uint8ClampedArray
;
640 return Array::Uint16Array
;
642 return Array::Uint32Array
;
644 return Array::Float32Array
;
646 return Array::Float64Array
;
648 return Array::Generic
;
652 bool permitsBoundsCheckLowering(Array::Type type
)
657 case Array::Contiguous
:
658 case Array::Int8Array
:
659 case Array::Int16Array
:
660 case Array::Int32Array
:
661 case Array::Uint8Array
:
662 case Array::Uint8ClampedArray
:
663 case Array::Uint16Array
:
664 case Array::Uint32Array
:
665 case Array::Float32Array
:
666 case Array::Float64Array
:
669 // These don't allow for bounds check lowering either because the bounds
670 // check involves something other than GetArrayLength (like ArrayStorage),
671 // or because the bounds check isn't a speculation (like String, sort of),
672 // or because the type implies an impure access.
677 bool ArrayMode::permitsBoundsCheckLowering() const
679 return DFG::permitsBoundsCheckLowering(type()) && isInBounds();
682 void ArrayMode::dump(PrintStream
& out
) const
684 out
.print(type(), arrayClass(), speculation(), conversion());
687 } } // namespace JSC::DFG
691 void printInternal(PrintStream
& out
, JSC::DFG::Array::Type type
)
693 out
.print(JSC::DFG::arrayTypeToString(type
));
696 void printInternal(PrintStream
& out
, JSC::DFG::Array::Class arrayClass
)
698 out
.print(JSC::DFG::arrayClassToString(arrayClass
));
701 void printInternal(PrintStream
& out
, JSC::DFG::Array::Speculation speculation
)
703 out
.print(JSC::DFG::arraySpeculationToString(speculation
));
706 void printInternal(PrintStream
& out
, JSC::DFG::Array::Conversion conversion
)
708 out
.print(JSC::DFG::arrayConversionToString(conversion
));
713 #endif // ENABLE(DFG_JIT)