a5994fb5cefcb93823889ab86a238d1296d86506
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGArrayMode.cpp
1 /*
2  * Copyright (C) 2012-2015 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 #include "config.h"
27 #include "DFGArrayMode.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGAbstractValue.h"
32 #include "DFGGraph.h"
33 #include "JSCInlines.h"
34
35 namespace JSC { namespace DFG {
36
37 ArrayMode ArrayMode::fromObserved(const ConcurrentJITLocker& locker, ArrayProfile* profile, Array::Action action, bool makeSafe)
38 {
39     Array::Class nonArray;
40     if (profile->usesOriginalArrayStructures(locker))
41         nonArray = Array::OriginalNonArray;
42     else
43         nonArray = Array::NonArray;
44     
45     ArrayModes observed = profile->observedArrayModes(locker);
46     switch (observed) {
47     case 0:
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);
53
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);
58         
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);
63
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);
70
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);
77
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);
84
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);
100
101     default:
102         if ((observed & asArrayModes(NonArray)) && profile->mayInterceptIndexedAccesses(locker))
103             return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe);
104         
105         Array::Type type;
106         Array::Class arrayClass;
107         
108         if (shouldUseSlowPutArrayStorage(observed))
109             type = Array::SlowPutArrayStorage;
110         else if (shouldUseFastArrayStorage(observed))
111             type = Array::ArrayStorage;
112         else if (shouldUseContiguous(observed))
113             type = Array::Contiguous;
114         else if (shouldUseDouble(observed))
115             type = Array::Double;
116         else if (shouldUseInt32(observed))
117             type = Array::Int32;
118         else
119             type = Array::Undecided;
120         
121         if (hasSeenArray(observed) && hasSeenNonArray(observed))
122             arrayClass = Array::PossiblyArray;
123         else if (hasSeenArray(observed))
124             arrayClass = Array::Array;
125         else if (hasSeenNonArray(observed))
126             arrayClass = nonArray;
127         else
128             arrayClass = Array::PossiblyArray;
129         
130         return ArrayMode(type, arrayClass, Array::Convert).withProfile(locker, profile, makeSafe);
131     }
132 }
133
134 ArrayMode ArrayMode::refine(
135     Graph& graph, Node* node,
136     SpeculatedType base, SpeculatedType index, SpeculatedType value,
137     NodeFlags flags) const
138 {
139     if (!base || !index) {
140         // It can be that we had a legitimate arrayMode but no incoming predictions. That'll
141         // happen if we inlined code based on, say, a global variable watchpoint, but later
142         // realized that the callsite could not have possibly executed. It may be worthwhile
143         // to fix that, but for now I'm leaving it as-is.
144         return ArrayMode(Array::ForceExit);
145     }
146     
147     if (!isInt32Speculation(index))
148         return ArrayMode(Array::Generic);
149     
150     // If we had exited because of an exotic object behavior, then don't try to specialize.
151     if (graph.hasExitSite(node->origin.semantic, ExoticObjectMode))
152         return ArrayMode(Array::Generic);
153     
154     // Note: our profiling currently doesn't give us good information in case we have
155     // an unlikely control flow path that sets the base to a non-cell value. Value
156     // profiling and prediction propagation will probably tell us that the value is
157     // either a cell or not, but that doesn't tell us which is more likely: that this
158     // is an array access on a cell (what we want and can optimize) or that the user is
159     // doing a crazy by-val access on a primitive (we can't easily optimize this and
160     // don't want to). So, for now, we assume that if the base is not a cell according
161     // to value profiling, but the array profile tells us something else, then we
162     // should just trust the array profile.
163     
164     switch (type()) {
165     case Array::Undecided:
166         if (!value)
167             return withType(Array::ForceExit);
168         if (isInt32Speculation(value))
169             return withTypeAndConversion(Array::Int32, Array::Convert);
170         if (isFullNumberSpeculation(value))
171             return withTypeAndConversion(Array::Double, Array::Convert);
172         return withTypeAndConversion(Array::Contiguous, Array::Convert);
173         
174     case Array::Int32:
175         if (!value || isInt32Speculation(value))
176             return *this;
177         if (isFullNumberSpeculation(value))
178             return withTypeAndConversion(Array::Double, Array::Convert);
179         return withTypeAndConversion(Array::Contiguous, Array::Convert);
180         
181     case Array::Double:
182         if (flags & NodeBytecodeUsesAsInt)
183             return withTypeAndConversion(Array::Contiguous, Array::RageConvert);
184         if (!value || isFullNumberSpeculation(value))
185             return *this;
186         return withTypeAndConversion(Array::Contiguous, Array::Convert);
187         
188     case Array::Contiguous:
189         if (doesConversion() && (flags & NodeBytecodeUsesAsInt))
190             return withConversion(Array::RageConvert);
191         return *this;
192         
193     case Array::Unprofiled:
194     case Array::SelectUsingPredictions: {
195         base &= ~SpecOther;
196         
197         if (isStringSpeculation(base))
198             return withType(Array::String);
199         
200         if (isDirectArgumentsSpeculation(base) || isScopedArgumentsSpeculation(base)) {
201             // Handle out-of-bounds accesses as generic accesses.
202             if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds())
203                 return ArrayMode(Array::Generic);
204             
205             if (isDirectArgumentsSpeculation(base))
206                 return withType(Array::DirectArguments);
207             return withType(Array::ScopedArguments);
208         }
209         
210         ArrayMode result;
211         switch (node->op()) {
212         case PutByVal:
213             if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds())
214                 result = withSpeculation(Array::OutOfBounds);
215             else
216                 result = withSpeculation(Array::InBounds);
217             break;
218             
219         default:
220             result = withSpeculation(Array::InBounds);
221             break;
222         }
223         
224         if (isInt8ArraySpeculation(base))
225             return result.withType(Array::Int8Array);
226         
227         if (isInt16ArraySpeculation(base))
228             return result.withType(Array::Int16Array);
229         
230         if (isInt32ArraySpeculation(base))
231             return result.withType(Array::Int32Array);
232         
233         if (isUint8ArraySpeculation(base))
234             return result.withType(Array::Uint8Array);
235         
236         if (isUint8ClampedArraySpeculation(base))
237             return result.withType(Array::Uint8ClampedArray);
238         
239         if (isUint16ArraySpeculation(base))
240             return result.withType(Array::Uint16Array);
241         
242         if (isUint32ArraySpeculation(base))
243             return result.withType(Array::Uint32Array);
244         
245         if (isFloat32ArraySpeculation(base))
246             return result.withType(Array::Float32Array);
247         
248         if (isFloat64ArraySpeculation(base))
249             return result.withType(Array::Float64Array);
250
251         if (type() == Array::Unprofiled)
252             return ArrayMode(Array::ForceExit);
253         return ArrayMode(Array::Generic);
254     }
255
256     default:
257         return *this;
258     }
259 }
260
261 Structure* ArrayMode::originalArrayStructure(Graph& graph, const CodeOrigin& codeOrigin) const
262 {
263     JSGlobalObject* globalObject = graph.globalObjectFor(codeOrigin);
264     
265     switch (arrayClass()) {
266     case Array::OriginalArray: {
267         switch (type()) {
268         case Array::Int32:
269             return globalObject->originalArrayStructureForIndexingType(ArrayWithInt32);
270         case Array::Double:
271             return globalObject->originalArrayStructureForIndexingType(ArrayWithDouble);
272         case Array::Contiguous:
273             return globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous);
274         case Array::ArrayStorage:
275             return globalObject->originalArrayStructureForIndexingType(ArrayWithArrayStorage);
276         default:
277             CRASH();
278             return 0;
279         }
280     }
281         
282     case Array::OriginalNonArray: {
283         TypedArrayType type = typedArrayType();
284         if (type == NotTypedArray)
285             return 0;
286         
287         return globalObject->typedArrayStructure(type);
288     }
289         
290     default:
291         return 0;
292     }
293 }
294
295 Structure* ArrayMode::originalArrayStructure(Graph& graph, Node* node) const
296 {
297     return originalArrayStructure(graph, node->origin.semantic);
298 }
299
300 bool ArrayMode::alreadyChecked(Graph& graph, Node* node, AbstractValue& value, IndexingType shape) const
301 {
302     switch (arrayClass()) {
303     case Array::OriginalArray: {
304         if (value.m_structure.isTop())
305             return false;
306         for (unsigned i = value.m_structure.size(); i--;) {
307             Structure* structure = value.m_structure[i];
308             if ((structure->indexingType() & IndexingShapeMask) != shape)
309                 return false;
310             if (!(structure->indexingType() & IsArray))
311                 return false;
312             if (!graph.globalObjectFor(node->origin.semantic)->isOriginalArrayStructure(structure))
313                 return false;
314         }
315         return true;
316     }
317         
318     case Array::Array: {
319         if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape | IsArray)))
320             return true;
321         if (value.m_structure.isTop())
322             return false;
323         for (unsigned i = value.m_structure.size(); i--;) {
324             Structure* structure = value.m_structure[i];
325             if ((structure->indexingType() & IndexingShapeMask) != shape)
326                 return false;
327             if (!(structure->indexingType() & IsArray))
328                 return false;
329         }
330         return true;
331     }
332         
333     default: {
334         if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape) | asArrayModes(shape | IsArray)))
335             return true;
336         if (value.m_structure.isTop())
337             return false;
338         for (unsigned i = value.m_structure.size(); i--;) {
339             Structure* structure = value.m_structure[i];
340             if ((structure->indexingType() & IndexingShapeMask) != shape)
341                 return false;
342         }
343         return true;
344     } }
345 }
346
347 bool ArrayMode::alreadyChecked(Graph& graph, Node* node, AbstractValue& value) const
348 {
349     switch (type()) {
350     case Array::Generic:
351         return true;
352         
353     case Array::ForceExit:
354         return false;
355         
356     case Array::String:
357         return speculationChecked(value.m_type, SpecString);
358         
359     case Array::Int32:
360         return alreadyChecked(graph, node, value, Int32Shape);
361         
362     case Array::Double:
363         return alreadyChecked(graph, node, value, DoubleShape);
364         
365     case Array::Contiguous:
366         return alreadyChecked(graph, node, value, ContiguousShape);
367         
368     case Array::ArrayStorage:
369         return alreadyChecked(graph, node, value, ArrayStorageShape);
370         
371     case Array::SlowPutArrayStorage:
372         switch (arrayClass()) {
373         case Array::OriginalArray: {
374             CRASH();
375             return false;
376         }
377         
378         case Array::Array: {
379             if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))
380                 return true;
381             if (value.m_structure.isTop())
382                 return false;
383             for (unsigned i = value.m_structure.size(); i--;) {
384                 Structure* structure = value.m_structure[i];
385                 if (!hasAnyArrayStorage(structure->indexingType()))
386                     return false;
387                 if (!(structure->indexingType() & IsArray))
388                     return false;
389             }
390             return true;
391         }
392         
393         default: {
394             if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))
395                 return true;
396             if (value.m_structure.isTop())
397                 return false;
398             for (unsigned i = value.m_structure.size(); i--;) {
399                 Structure* structure = value.m_structure[i];
400                 if (!hasAnyArrayStorage(structure->indexingType()))
401                     return false;
402             }
403             return true;
404         } }
405         
406     case Array::DirectArguments:
407         return speculationChecked(value.m_type, SpecDirectArguments);
408         
409     case Array::ScopedArguments:
410         return speculationChecked(value.m_type, SpecScopedArguments);
411         
412     case Array::Int8Array:
413         return speculationChecked(value.m_type, SpecInt8Array);
414         
415     case Array::Int16Array:
416         return speculationChecked(value.m_type, SpecInt16Array);
417         
418     case Array::Int32Array:
419         return speculationChecked(value.m_type, SpecInt32Array);
420         
421     case Array::Uint8Array:
422         return speculationChecked(value.m_type, SpecUint8Array);
423         
424     case Array::Uint8ClampedArray:
425         return speculationChecked(value.m_type, SpecUint8ClampedArray);
426         
427     case Array::Uint16Array:
428         return speculationChecked(value.m_type, SpecUint16Array);
429         
430     case Array::Uint32Array:
431         return speculationChecked(value.m_type, SpecUint32Array);
432
433     case Array::Float32Array:
434         return speculationChecked(value.m_type, SpecFloat32Array);
435
436     case Array::Float64Array:
437         return speculationChecked(value.m_type, SpecFloat64Array);
438         
439     case Array::SelectUsingPredictions:
440     case Array::Unprofiled:
441     case Array::Undecided:
442         break;
443     }
444     
445     CRASH();
446     return false;
447 }
448
449 const char* arrayTypeToString(Array::Type type)
450 {
451     switch (type) {
452     case Array::SelectUsingPredictions:
453         return "SelectUsingPredictions";
454     case Array::Unprofiled:
455         return "Unprofiled";
456     case Array::Generic:
457         return "Generic";
458     case Array::ForceExit:
459         return "ForceExit";
460     case Array::String:
461         return "String";
462     case Array::Undecided:
463         return "Undecided";
464     case Array::Int32:
465         return "Int32";
466     case Array::Double:
467         return "Double";
468     case Array::Contiguous:
469         return "Contiguous";
470     case Array::ArrayStorage:
471         return "ArrayStorage";
472     case Array::SlowPutArrayStorage:
473         return "SlowPutArrayStorage";
474     case Array::DirectArguments:
475         return "DirectArguments";
476     case Array::ScopedArguments:
477         return "ScopedArguments";
478     case Array::Int8Array:
479         return "Int8Array";
480     case Array::Int16Array:
481         return "Int16Array";
482     case Array::Int32Array:
483         return "Int32Array";
484     case Array::Uint8Array:
485         return "Uint8Array";
486     case Array::Uint8ClampedArray:
487         return "Uint8ClampedArray";
488     case Array::Uint16Array:
489         return "Uint16Array";
490     case Array::Uint32Array:
491         return "Uint32Array";
492     case Array::Float32Array:
493         return "Float32Array";
494     case Array::Float64Array:
495         return "Float64Array";
496     default:
497         // Better to return something then it is to crash. Remember, this method
498         // is being called from our main diagnostic tool, the IR dumper. It's like
499         // a stack trace. So if we get here then probably something has already
500         // gone wrong.
501         return "Unknown!";
502     }
503 }
504
505 const char* arrayClassToString(Array::Class arrayClass)
506 {
507     switch (arrayClass) {
508     case Array::Array:
509         return "Array";
510     case Array::OriginalArray:
511         return "OriginalArray";
512     case Array::NonArray:
513         return "NonArray";
514     case Array::OriginalNonArray:
515         return "OriginalNonArray";
516     case Array::PossiblyArray:
517         return "PossiblyArray";
518     default:
519         return "Unknown!";
520     }
521 }
522
523 const char* arraySpeculationToString(Array::Speculation speculation)
524 {
525     switch (speculation) {
526     case Array::SaneChain:
527         return "SaneChain";
528     case Array::InBounds:
529         return "InBounds";
530     case Array::ToHole:
531         return "ToHole";
532     case Array::OutOfBounds:
533         return "OutOfBounds";
534     default:
535         return "Unknown!";
536     }
537 }
538
539 const char* arrayConversionToString(Array::Conversion conversion)
540 {
541     switch (conversion) {
542     case Array::AsIs:
543         return "AsIs";
544     case Array::Convert:
545         return "Convert";
546     case Array::RageConvert:
547         return "RageConvert";
548     default:
549         return "Unknown!";
550     }
551 }
552
553 IndexingType toIndexingShape(Array::Type type)
554 {
555     switch (type) {
556     case Array::Int32:
557         return Int32Shape;
558     case Array::Double:
559         return DoubleShape;
560     case Array::Contiguous:
561         return ContiguousShape;
562     case Array::ArrayStorage:
563         return ArrayStorageShape;
564     case Array::SlowPutArrayStorage:
565         return SlowPutArrayStorageShape;
566     default:
567         return NoIndexingShape;
568     }
569 }
570
571 TypedArrayType toTypedArrayType(Array::Type type)
572 {
573     switch (type) {
574     case Array::Int8Array:
575         return TypeInt8;
576     case Array::Int16Array:
577         return TypeInt16;
578     case Array::Int32Array:
579         return TypeInt32;
580     case Array::Uint8Array:
581         return TypeUint8;
582     case Array::Uint8ClampedArray:
583         return TypeUint8Clamped;
584     case Array::Uint16Array:
585         return TypeUint16;
586     case Array::Uint32Array:
587         return TypeUint32;
588     case Array::Float32Array:
589         return TypeFloat32;
590     case Array::Float64Array:
591         return TypeFloat64;
592     default:
593         return NotTypedArray;
594     }
595 }
596
597 Array::Type toArrayType(TypedArrayType type)
598 {
599     switch (type) {
600     case TypeInt8:
601         return Array::Int8Array;
602     case TypeInt16:
603         return Array::Int16Array;
604     case TypeInt32:
605         return Array::Int32Array;
606     case TypeUint8:
607         return Array::Uint8Array;
608     case TypeUint8Clamped:
609         return Array::Uint8ClampedArray;
610     case TypeUint16:
611         return Array::Uint16Array;
612     case TypeUint32:
613         return Array::Uint32Array;
614     case TypeFloat32:
615         return Array::Float32Array;
616     case TypeFloat64:
617         return Array::Float64Array;
618     default:
619         return Array::Generic;
620     }
621 }
622
623 bool permitsBoundsCheckLowering(Array::Type type)
624 {
625     switch (type) {
626     case Array::Int32:
627     case Array::Double:
628     case Array::Contiguous:
629     case Array::Int8Array:
630     case Array::Int16Array:
631     case Array::Int32Array:
632     case Array::Uint8Array:
633     case Array::Uint8ClampedArray:
634     case Array::Uint16Array:
635     case Array::Uint32Array:
636     case Array::Float32Array:
637     case Array::Float64Array:
638         return true;
639     default:
640         // These don't allow for bounds check lowering either because the bounds
641         // check involves something other than GetArrayLength (like ArrayStorage),
642         // or because the bounds check isn't a speculation (like String, sort of),
643         // or because the type implies an impure access.
644         return false;
645     }
646 }
647
648 bool ArrayMode::permitsBoundsCheckLowering() const
649 {
650     return DFG::permitsBoundsCheckLowering(type()) && isInBounds();
651 }
652
653 void ArrayMode::dump(PrintStream& out) const
654 {
655     out.print(type(), arrayClass(), speculation(), conversion());
656 }
657
658 } } // namespace JSC::DFG
659
660 namespace WTF {
661
662 void printInternal(PrintStream& out, JSC::DFG::Array::Type type)
663 {
664     out.print(JSC::DFG::arrayTypeToString(type));
665 }
666
667 void printInternal(PrintStream& out, JSC::DFG::Array::Class arrayClass)
668 {
669     out.print(JSC::DFG::arrayClassToString(arrayClass));
670 }
671
672 void printInternal(PrintStream& out, JSC::DFG::Array::Speculation speculation)
673 {
674     out.print(JSC::DFG::arraySpeculationToString(speculation));
675 }
676
677 void printInternal(PrintStream& out, JSC::DFG::Array::Conversion conversion)
678 {
679     out.print(JSC::DFG::arrayConversionToString(conversion));
680 }
681
682 } // namespace WTF
683
684 #endif // ENABLE(DFG_JIT)
685