]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGArrayMode.cpp
JavaScriptCore-7600.1.4.15.12.tar.gz
[apple/javascriptcore.git] / dfg / DFGArrayMode.cpp
CommitLineData
93a37866 1/*
81345200 2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
93a37866
A
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"
81345200 33#include "JSCInlines.h"
93a37866
A
34
35namespace JSC { namespace DFG {
36
81345200 37ArrayMode ArrayMode::fromObserved(const ConcurrentJITLocker& locker, ArrayProfile* profile, Array::Action action, bool makeSafe)
93a37866 38{
81345200
A
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);
93a37866
A
46 switch (observed) {
47 case 0:
48 return ArrayMode(Array::Unprofiled);
49 case asArrayModes(NonArray):
81345200
A
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);
93a37866
A
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):
81345200 60 if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker))
93a37866 61 return ArrayMode(Array::Undecided, Array::PossiblyArray, Array::OutOfBounds, Array::Convert);
81345200 62 return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe);
93a37866
A
63
64 case asArrayModes(NonArrayWithInt32):
81345200 65 return ArrayMode(Array::Int32, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866 66 case asArrayModes(ArrayWithInt32):
81345200 67 return ArrayMode(Array::Int32, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866 68 case asArrayModes(NonArrayWithInt32) | asArrayModes(ArrayWithInt32):
81345200 69 return ArrayMode(Array::Int32, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866
A
70
71 case asArrayModes(NonArrayWithDouble):
81345200 72 return ArrayMode(Array::Double, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866 73 case asArrayModes(ArrayWithDouble):
81345200 74 return ArrayMode(Array::Double, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866 75 case asArrayModes(NonArrayWithDouble) | asArrayModes(ArrayWithDouble):
81345200 76 return ArrayMode(Array::Double, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866
A
77
78 case asArrayModes(NonArrayWithContiguous):
81345200 79 return ArrayMode(Array::Contiguous, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866 80 case asArrayModes(ArrayWithContiguous):
81345200 81 return ArrayMode(Array::Contiguous, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866 82 case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous):
81345200 83 return ArrayMode(Array::Contiguous, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866
A
84
85 case asArrayModes(NonArrayWithArrayStorage):
81345200 86 return ArrayMode(Array::ArrayStorage, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866
A
87 case asArrayModes(NonArrayWithSlowPutArrayStorage):
88 case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage):
81345200 89 return ArrayMode(Array::SlowPutArrayStorage, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866 90 case asArrayModes(ArrayWithArrayStorage):
81345200 91 return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866
A
92 case asArrayModes(ArrayWithSlowPutArrayStorage):
93 case asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
81345200 94 return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866 95 case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage):
81345200 96 return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866
A
97 case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
98 case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
81345200 99 return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe);
93a37866
A
100
101 default:
81345200
A
102 if ((observed & asArrayModes(NonArray)) && profile->mayInterceptIndexedAccesses(locker))
103 return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe);
93a37866
A
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))
81345200 126 arrayClass = nonArray;
93a37866
A
127 else
128 arrayClass = Array::PossiblyArray;
129
81345200 130 return ArrayMode(type, arrayClass, Array::Convert).withProfile(locker, profile, makeSafe);
93a37866
A
131 }
132}
133
81345200
A
134ArrayMode ArrayMode::refine(
135 Graph& graph, Node* node,
136 SpeculatedType base, SpeculatedType index, SpeculatedType value,
137 NodeFlags flags) const
93a37866
A
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 // Note: our profiling currently doesn't give us good information in case we have
151 // an unlikely control flow path that sets the base to a non-cell value. Value
152 // profiling and prediction propagation will probably tell us that the value is
153 // either a cell or not, but that doesn't tell us which is more likely: that this
154 // is an array access on a cell (what we want and can optimize) or that the user is
155 // doing a crazy by-val access on a primitive (we can't easily optimize this and
156 // don't want to). So, for now, we assume that if the base is not a cell according
157 // to value profiling, but the array profile tells us something else, then we
158 // should just trust the array profile.
159
160 switch (type()) {
161 case Array::Unprofiled:
162 return ArrayMode(Array::ForceExit);
163
164 case Array::Undecided:
165 if (!value)
166 return withType(Array::ForceExit);
167 if (isInt32Speculation(value))
168 return withTypeAndConversion(Array::Int32, Array::Convert);
81345200 169 if (isFullNumberSpeculation(value))
93a37866
A
170 return withTypeAndConversion(Array::Double, Array::Convert);
171 return withTypeAndConversion(Array::Contiguous, Array::Convert);
172
173 case Array::Int32:
174 if (!value || isInt32Speculation(value))
175 return *this;
81345200 176 if (isFullNumberSpeculation(value))
93a37866
A
177 return withTypeAndConversion(Array::Double, Array::Convert);
178 return withTypeAndConversion(Array::Contiguous, Array::Convert);
179
180 case Array::Double:
81345200 181 if (flags & NodeBytecodeUsesAsInt)
93a37866 182 return withTypeAndConversion(Array::Contiguous, Array::RageConvert);
81345200 183 if (!value || isFullNumberSpeculation(value))
93a37866
A
184 return *this;
185 return withTypeAndConversion(Array::Contiguous, Array::Convert);
186
187 case Array::Contiguous:
81345200 188 if (doesConversion() && (flags & NodeBytecodeUsesAsInt))
93a37866
A
189 return withConversion(Array::RageConvert);
190 return *this;
191
81345200 192 case Array::SelectUsingPredictions: {
93a37866
A
193 base &= ~SpecOther;
194
195 if (isStringSpeculation(base))
81345200 196 return withType(Array::String);
93a37866
A
197
198 if (isArgumentsSpeculation(base))
81345200
A
199 return withType(Array::Arguments);
200
201 ArrayMode result;
202 switch (node->op()) {
203 case PutByVal:
204 if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds())
205 result = withSpeculation(Array::OutOfBounds);
206 else
207 result = withSpeculation(Array::InBounds);
208 break;
209
210 default:
211 result = withSpeculation(Array::InBounds);
212 break;
213 }
93a37866
A
214
215 if (isInt8ArraySpeculation(base))
81345200 216 return result.withType(Array::Int8Array);
93a37866
A
217
218 if (isInt16ArraySpeculation(base))
81345200 219 return result.withType(Array::Int16Array);
93a37866
A
220
221 if (isInt32ArraySpeculation(base))
81345200 222 return result.withType(Array::Int32Array);
93a37866
A
223
224 if (isUint8ArraySpeculation(base))
81345200 225 return result.withType(Array::Uint8Array);
93a37866
A
226
227 if (isUint8ClampedArraySpeculation(base))
81345200 228 return result.withType(Array::Uint8ClampedArray);
93a37866
A
229
230 if (isUint16ArraySpeculation(base))
81345200 231 return result.withType(Array::Uint16Array);
93a37866
A
232
233 if (isUint32ArraySpeculation(base))
81345200 234 return result.withType(Array::Uint32Array);
93a37866
A
235
236 if (isFloat32ArraySpeculation(base))
81345200 237 return result.withType(Array::Float32Array);
93a37866
A
238
239 if (isFloat64ArraySpeculation(base))
81345200 240 return result.withType(Array::Float64Array);
93a37866
A
241
242 return ArrayMode(Array::Generic);
81345200 243 }
93a37866
A
244
245 default:
246 return *this;
247 }
248}
249
250Structure* ArrayMode::originalArrayStructure(Graph& graph, const CodeOrigin& codeOrigin) const
251{
93a37866
A
252 JSGlobalObject* globalObject = graph.globalObjectFor(codeOrigin);
253
81345200
A
254 switch (arrayClass()) {
255 case Array::OriginalArray: {
256 switch (type()) {
257 case Array::Int32:
258 return globalObject->originalArrayStructureForIndexingType(ArrayWithInt32);
259 case Array::Double:
260 return globalObject->originalArrayStructureForIndexingType(ArrayWithDouble);
261 case Array::Contiguous:
262 return globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous);
263 case Array::ArrayStorage:
264 return globalObject->originalArrayStructureForIndexingType(ArrayWithArrayStorage);
265 default:
266 CRASH();
267 return 0;
268 }
269 }
270
271 case Array::OriginalNonArray: {
272 TypedArrayType type = typedArrayType();
273 if (type == NotTypedArray)
274 return 0;
275
276 return globalObject->typedArrayStructure(type);
277 }
278
93a37866 279 default:
93a37866
A
280 return 0;
281 }
282}
283
284Structure* ArrayMode::originalArrayStructure(Graph& graph, Node* node) const
285{
81345200 286 return originalArrayStructure(graph, node->origin.semantic);
93a37866
A
287}
288
289bool ArrayMode::alreadyChecked(Graph& graph, Node* node, AbstractValue& value, IndexingType shape) const
290{
291 switch (arrayClass()) {
292 case Array::OriginalArray:
293 return value.m_currentKnownStructure.hasSingleton()
294 && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape
295 && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray)
81345200 296 && graph.globalObjectFor(node->origin.semantic)->isOriginalArrayStructure(value.m_currentKnownStructure.singleton());
93a37866
A
297
298 case Array::Array:
299 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape | IsArray)))
300 return true;
301 return value.m_currentKnownStructure.hasSingleton()
302 && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape
303 && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray);
304
305 default:
306 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape) | asArrayModes(shape | IsArray)))
307 return true;
308 return value.m_currentKnownStructure.hasSingleton()
309 && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape;
310 }
311}
312
313bool ArrayMode::alreadyChecked(Graph& graph, Node* node, AbstractValue& value) const
314{
315 switch (type()) {
316 case Array::Generic:
317 return true;
318
319 case Array::ForceExit:
320 return false;
321
322 case Array::String:
323 return speculationChecked(value.m_type, SpecString);
324
325 case Array::Int32:
326 return alreadyChecked(graph, node, value, Int32Shape);
327
328 case Array::Double:
329 return alreadyChecked(graph, node, value, DoubleShape);
330
331 case Array::Contiguous:
332 return alreadyChecked(graph, node, value, ContiguousShape);
333
334 case Array::ArrayStorage:
335 return alreadyChecked(graph, node, value, ArrayStorageShape);
336
337 case Array::SlowPutArrayStorage:
338 switch (arrayClass()) {
339 case Array::OriginalArray:
340 CRASH();
341 return false;
342
343 case Array::Array:
344 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))
345 return true;
346 return value.m_currentKnownStructure.hasSingleton()
81345200 347 && hasAnyArrayStorage(value.m_currentKnownStructure.singleton()->indexingType())
93a37866
A
348 && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray);
349
350 default:
351 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))
352 return true;
353 return value.m_currentKnownStructure.hasSingleton()
81345200 354 && hasAnyArrayStorage(value.m_currentKnownStructure.singleton()->indexingType());
93a37866
A
355 }
356
357 case Array::Arguments:
358 return speculationChecked(value.m_type, SpecArguments);
359
360 case Array::Int8Array:
361 return speculationChecked(value.m_type, SpecInt8Array);
362
363 case Array::Int16Array:
364 return speculationChecked(value.m_type, SpecInt16Array);
365
366 case Array::Int32Array:
367 return speculationChecked(value.m_type, SpecInt32Array);
368
369 case Array::Uint8Array:
370 return speculationChecked(value.m_type, SpecUint8Array);
371
372 case Array::Uint8ClampedArray:
373 return speculationChecked(value.m_type, SpecUint8ClampedArray);
374
375 case Array::Uint16Array:
376 return speculationChecked(value.m_type, SpecUint16Array);
377
378 case Array::Uint32Array:
379 return speculationChecked(value.m_type, SpecUint32Array);
380
381 case Array::Float32Array:
382 return speculationChecked(value.m_type, SpecFloat32Array);
383
384 case Array::Float64Array:
385 return speculationChecked(value.m_type, SpecFloat64Array);
386
387 case Array::SelectUsingPredictions:
388 case Array::Unprofiled:
389 case Array::Undecided:
390 break;
391 }
392
393 CRASH();
394 return false;
395}
396
397const char* arrayTypeToString(Array::Type type)
398{
399 switch (type) {
400 case Array::SelectUsingPredictions:
401 return "SelectUsingPredictions";
402 case Array::Unprofiled:
403 return "Unprofiled";
404 case Array::Generic:
405 return "Generic";
406 case Array::ForceExit:
407 return "ForceExit";
408 case Array::String:
409 return "String";
410 case Array::Undecided:
411 return "Undecided";
412 case Array::Int32:
413 return "Int32";
414 case Array::Double:
415 return "Double";
416 case Array::Contiguous:
417 return "Contiguous";
418 case Array::ArrayStorage:
419 return "ArrayStorage";
420 case Array::SlowPutArrayStorage:
421 return "SlowPutArrayStorage";
422 case Array::Arguments:
423 return "Arguments";
424 case Array::Int8Array:
425 return "Int8Array";
426 case Array::Int16Array:
427 return "Int16Array";
428 case Array::Int32Array:
429 return "Int32Array";
430 case Array::Uint8Array:
431 return "Uint8Array";
432 case Array::Uint8ClampedArray:
433 return "Uint8ClampedArray";
434 case Array::Uint16Array:
435 return "Uint16Array";
436 case Array::Uint32Array:
437 return "Uint32Array";
438 case Array::Float32Array:
439 return "Float32Array";
440 case Array::Float64Array:
441 return "Float64Array";
442 default:
443 // Better to return something then it is to crash. Remember, this method
444 // is being called from our main diagnostic tool, the IR dumper. It's like
445 // a stack trace. So if we get here then probably something has already
446 // gone wrong.
447 return "Unknown!";
448 }
449}
450
451const char* arrayClassToString(Array::Class arrayClass)
452{
453 switch (arrayClass) {
454 case Array::Array:
455 return "Array";
456 case Array::OriginalArray:
457 return "OriginalArray";
458 case Array::NonArray:
459 return "NonArray";
81345200
A
460 case Array::OriginalNonArray:
461 return "OriginalNonArray";
93a37866
A
462 case Array::PossiblyArray:
463 return "PossiblyArray";
464 default:
465 return "Unknown!";
466 }
467}
468
469const char* arraySpeculationToString(Array::Speculation speculation)
470{
471 switch (speculation) {
472 case Array::SaneChain:
473 return "SaneChain";
474 case Array::InBounds:
475 return "InBounds";
476 case Array::ToHole:
477 return "ToHole";
478 case Array::OutOfBounds:
479 return "OutOfBounds";
480 default:
481 return "Unknown!";
482 }
483}
484
485const char* arrayConversionToString(Array::Conversion conversion)
486{
487 switch (conversion) {
488 case Array::AsIs:
489 return "AsIs";
490 case Array::Convert:
491 return "Convert";
492 case Array::RageConvert:
493 return "RageConvert";
494 default:
495 return "Unknown!";
496 }
497}
498
81345200
A
499IndexingType toIndexingShape(Array::Type type)
500{
501 switch (type) {
502 case Array::Int32:
503 return Int32Shape;
504 case Array::Double:
505 return DoubleShape;
506 case Array::Contiguous:
507 return ContiguousShape;
508 case Array::ArrayStorage:
509 return ArrayStorageShape;
510 case Array::SlowPutArrayStorage:
511 return SlowPutArrayStorageShape;
512 default:
513 return NoIndexingShape;
514 }
515}
516
517TypedArrayType toTypedArrayType(Array::Type type)
518{
519 switch (type) {
520 case Array::Int8Array:
521 return TypeInt8;
522 case Array::Int16Array:
523 return TypeInt16;
524 case Array::Int32Array:
525 return TypeInt32;
526 case Array::Uint8Array:
527 return TypeUint8;
528 case Array::Uint8ClampedArray:
529 return TypeUint8Clamped;
530 case Array::Uint16Array:
531 return TypeUint16;
532 case Array::Uint32Array:
533 return TypeUint32;
534 case Array::Float32Array:
535 return TypeFloat32;
536 case Array::Float64Array:
537 return TypeFloat64;
538 default:
539 return NotTypedArray;
540 }
541}
542
543Array::Type toArrayType(TypedArrayType type)
544{
545 switch (type) {
546 case TypeInt8:
547 return Array::Int8Array;
548 case TypeInt16:
549 return Array::Int16Array;
550 case TypeInt32:
551 return Array::Int32Array;
552 case TypeUint8:
553 return Array::Uint8Array;
554 case TypeUint8Clamped:
555 return Array::Uint8ClampedArray;
556 case TypeUint16:
557 return Array::Uint16Array;
558 case TypeUint32:
559 return Array::Uint32Array;
560 case TypeFloat32:
561 return Array::Float32Array;
562 case TypeFloat64:
563 return Array::Float64Array;
564 default:
565 return Array::Generic;
566 }
567}
568
569bool permitsBoundsCheckLowering(Array::Type type)
570{
571 switch (type) {
572 case Array::Int32:
573 case Array::Double:
574 case Array::Contiguous:
575 case Array::Int8Array:
576 case Array::Int16Array:
577 case Array::Int32Array:
578 case Array::Uint8Array:
579 case Array::Uint8ClampedArray:
580 case Array::Uint16Array:
581 case Array::Uint32Array:
582 case Array::Float32Array:
583 case Array::Float64Array:
584 return true;
585 default:
586 // These don't allow for bounds check lowering either because the bounds
587 // check involves something other than GetArrayLength (like ArrayStorage),
588 // or because the bounds check isn't a speculation (like String, sort of),
589 // or because the type implies an impure access.
590 return false;
591 }
592}
593
594bool ArrayMode::permitsBoundsCheckLowering() const
595{
596 return DFG::permitsBoundsCheckLowering(type()) && isInBounds();
597}
598
93a37866
A
599void ArrayMode::dump(PrintStream& out) const
600{
601 out.print(type(), arrayClass(), speculation(), conversion());
602}
603
604} } // namespace JSC::DFG
605
606namespace WTF {
607
608void printInternal(PrintStream& out, JSC::DFG::Array::Type type)
609{
610 out.print(JSC::DFG::arrayTypeToString(type));
611}
612
613void printInternal(PrintStream& out, JSC::DFG::Array::Class arrayClass)
614{
615 out.print(JSC::DFG::arrayClassToString(arrayClass));
616}
617
618void printInternal(PrintStream& out, JSC::DFG::Array::Speculation speculation)
619{
620 out.print(JSC::DFG::arraySpeculationToString(speculation));
621}
622
623void printInternal(PrintStream& out, JSC::DFG::Array::Conversion conversion)
624{
625 out.print(JSC::DFG::arrayConversionToString(conversion));
626}
627
628} // namespace WTF
629
630#endif // ENABLE(DFG_JIT)
631