]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGArrayMode.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / 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 case Int8ArrayMode:
101 return ArrayMode(Array::Int8Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
102 case Int16ArrayMode:
103 return ArrayMode(Array::Int16Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
104 case Int32ArrayMode:
105 return ArrayMode(Array::Int32Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
106 case Uint8ArrayMode:
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);
118
119 default:
120 if ((observed & asArrayModes(NonArray)) && profile->mayInterceptIndexedAccesses(locker))
121 return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe);
122
123 Array::Type type;
124 Array::Class arrayClass;
125
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))
135 type = Array::Int32;
136 else
137 type = Array::Undecided;
138
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;
145 else
146 arrayClass = Array::PossiblyArray;
147
148 return ArrayMode(type, arrayClass, Array::Convert).withProfile(locker, profile, makeSafe);
149 }
150 }
151
152 ArrayMode ArrayMode::refine(
153 Graph& graph, Node* node,
154 SpeculatedType base, SpeculatedType index, SpeculatedType value) const
155 {
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);
162 }
163
164 if (!isInt32Speculation(index))
165 return ArrayMode(Array::Generic);
166
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);
170
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.
180
181 switch (type()) {
182 case Array::Undecided:
183 if (!value)
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);
190
191 case Array::Int32:
192 if (!value || isInt32Speculation(value))
193 return *this;
194 if (isFullNumberSpeculation(value))
195 return withTypeAndConversion(Array::Double, Array::Convert);
196 return withTypeAndConversion(Array::Contiguous, Array::Convert);
197
198 case Array::Double:
199 if (!value || isFullNumberSpeculation(value))
200 return *this;
201 return withTypeAndConversion(Array::Contiguous, Array::Convert);
202
203 case Array::Contiguous:
204 return *this;
205
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()) {
216 case PutByVal:
217 if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds())
218 return withSpeculation(Array::OutOfBounds);
219 return withSpeculation(Array::InBounds);
220 default:
221 return withSpeculation(Array::InBounds);
222 }
223 return *this;
224 case Array::Unprofiled:
225 case Array::SelectUsingPredictions: {
226 base &= ~SpecOther;
227
228 if (isStringSpeculation(base))
229 return withType(Array::String);
230
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);
235
236 if (isDirectArgumentsSpeculation(base))
237 return withType(Array::DirectArguments);
238 return withType(Array::ScopedArguments);
239 }
240
241 ArrayMode result;
242 switch (node->op()) {
243 case PutByVal:
244 if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds())
245 result = withSpeculation(Array::OutOfBounds);
246 else
247 result = withSpeculation(Array::InBounds);
248 break;
249
250 default:
251 result = withSpeculation(Array::InBounds);
252 break;
253 }
254
255 if (isInt8ArraySpeculation(base))
256 return result.withType(Array::Int8Array);
257
258 if (isInt16ArraySpeculation(base))
259 return result.withType(Array::Int16Array);
260
261 if (isInt32ArraySpeculation(base))
262 return result.withType(Array::Int32Array);
263
264 if (isUint8ArraySpeculation(base))
265 return result.withType(Array::Uint8Array);
266
267 if (isUint8ClampedArraySpeculation(base))
268 return result.withType(Array::Uint8ClampedArray);
269
270 if (isUint16ArraySpeculation(base))
271 return result.withType(Array::Uint16Array);
272
273 if (isUint32ArraySpeculation(base))
274 return result.withType(Array::Uint32Array);
275
276 if (isFloat32ArraySpeculation(base))
277 return result.withType(Array::Float32Array);
278
279 if (isFloat64ArraySpeculation(base))
280 return result.withType(Array::Float64Array);
281
282 if (type() == Array::Unprofiled)
283 return ArrayMode(Array::ForceExit);
284 return ArrayMode(Array::Generic);
285 }
286
287 default:
288 return *this;
289 }
290 }
291
292 Structure* ArrayMode::originalArrayStructure(Graph& graph, const CodeOrigin& codeOrigin) const
293 {
294 JSGlobalObject* globalObject = graph.globalObjectFor(codeOrigin);
295
296 switch (arrayClass()) {
297 case Array::OriginalArray: {
298 switch (type()) {
299 case Array::Int32:
300 return globalObject->originalArrayStructureForIndexingType(ArrayWithInt32);
301 case Array::Double:
302 return globalObject->originalArrayStructureForIndexingType(ArrayWithDouble);
303 case Array::Contiguous:
304 return globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous);
305 case Array::ArrayStorage:
306 return globalObject->originalArrayStructureForIndexingType(ArrayWithArrayStorage);
307 default:
308 CRASH();
309 return 0;
310 }
311 }
312
313 case Array::OriginalNonArray: {
314 TypedArrayType type = typedArrayType();
315 if (type == NotTypedArray)
316 return 0;
317
318 return globalObject->typedArrayStructure(type);
319 }
320
321 default:
322 return 0;
323 }
324 }
325
326 Structure* ArrayMode::originalArrayStructure(Graph& graph, Node* node) const
327 {
328 return originalArrayStructure(graph, node->origin.semantic);
329 }
330
331 bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& value, IndexingType shape) const
332 {
333 switch (arrayClass()) {
334 case Array::OriginalArray: {
335 if (value.m_structure.isTop())
336 return false;
337 for (unsigned i = value.m_structure.size(); i--;) {
338 Structure* structure = value.m_structure[i];
339 if ((structure->indexingType() & IndexingShapeMask) != shape)
340 return false;
341 if (!(structure->indexingType() & IsArray))
342 return false;
343 if (!graph.globalObjectFor(node->origin.semantic)->isOriginalArrayStructure(structure))
344 return false;
345 }
346 return true;
347 }
348
349 case Array::Array: {
350 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape | IsArray)))
351 return true;
352 if (value.m_structure.isTop())
353 return false;
354 for (unsigned i = value.m_structure.size(); i--;) {
355 Structure* structure = value.m_structure[i];
356 if ((structure->indexingType() & IndexingShapeMask) != shape)
357 return false;
358 if (!(structure->indexingType() & IsArray))
359 return false;
360 }
361 return true;
362 }
363
364 default: {
365 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape) | asArrayModes(shape | IsArray)))
366 return true;
367 if (value.m_structure.isTop())
368 return false;
369 for (unsigned i = value.m_structure.size(); i--;) {
370 Structure* structure = value.m_structure[i];
371 if ((structure->indexingType() & IndexingShapeMask) != shape)
372 return false;
373 }
374 return true;
375 } }
376 }
377
378 bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& value) const
379 {
380 switch (type()) {
381 case Array::Generic:
382 return true;
383
384 case Array::ForceExit:
385 return false;
386
387 case Array::String:
388 return speculationChecked(value.m_type, SpecString);
389
390 case Array::Int32:
391 return alreadyChecked(graph, node, value, Int32Shape);
392
393 case Array::Double:
394 return alreadyChecked(graph, node, value, DoubleShape);
395
396 case Array::Contiguous:
397 return alreadyChecked(graph, node, value, ContiguousShape);
398
399 case Array::ArrayStorage:
400 return alreadyChecked(graph, node, value, ArrayStorageShape);
401
402 case Array::SlowPutArrayStorage:
403 switch (arrayClass()) {
404 case Array::OriginalArray: {
405 CRASH();
406 return false;
407 }
408
409 case Array::Array: {
410 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))
411 return true;
412 if (value.m_structure.isTop())
413 return false;
414 for (unsigned i = value.m_structure.size(); i--;) {
415 Structure* structure = value.m_structure[i];
416 if (!hasAnyArrayStorage(structure->indexingType()))
417 return false;
418 if (!(structure->indexingType() & IsArray))
419 return false;
420 }
421 return true;
422 }
423
424 default: {
425 if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))
426 return true;
427 if (value.m_structure.isTop())
428 return false;
429 for (unsigned i = value.m_structure.size(); i--;) {
430 Structure* structure = value.m_structure[i];
431 if (!hasAnyArrayStorage(structure->indexingType()))
432 return false;
433 }
434 return true;
435 } }
436
437 case Array::DirectArguments:
438 return speculationChecked(value.m_type, SpecDirectArguments);
439
440 case Array::ScopedArguments:
441 return speculationChecked(value.m_type, SpecScopedArguments);
442
443 case Array::Int8Array:
444 return speculationChecked(value.m_type, SpecInt8Array);
445
446 case Array::Int16Array:
447 return speculationChecked(value.m_type, SpecInt16Array);
448
449 case Array::Int32Array:
450 return speculationChecked(value.m_type, SpecInt32Array);
451
452 case Array::Uint8Array:
453 return speculationChecked(value.m_type, SpecUint8Array);
454
455 case Array::Uint8ClampedArray:
456 return speculationChecked(value.m_type, SpecUint8ClampedArray);
457
458 case Array::Uint16Array:
459 return speculationChecked(value.m_type, SpecUint16Array);
460
461 case Array::Uint32Array:
462 return speculationChecked(value.m_type, SpecUint32Array);
463
464 case Array::Float32Array:
465 return speculationChecked(value.m_type, SpecFloat32Array);
466
467 case Array::Float64Array:
468 return speculationChecked(value.m_type, SpecFloat64Array);
469
470 case Array::SelectUsingPredictions:
471 case Array::Unprofiled:
472 case Array::Undecided:
473 break;
474 }
475
476 CRASH();
477 return false;
478 }
479
480 const char* arrayTypeToString(Array::Type type)
481 {
482 switch (type) {
483 case Array::SelectUsingPredictions:
484 return "SelectUsingPredictions";
485 case Array::Unprofiled:
486 return "Unprofiled";
487 case Array::Generic:
488 return "Generic";
489 case Array::ForceExit:
490 return "ForceExit";
491 case Array::String:
492 return "String";
493 case Array::Undecided:
494 return "Undecided";
495 case Array::Int32:
496 return "Int32";
497 case Array::Double:
498 return "Double";
499 case Array::Contiguous:
500 return "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:
510 return "Int8Array";
511 case Array::Int16Array:
512 return "Int16Array";
513 case Array::Int32Array:
514 return "Int32Array";
515 case Array::Uint8Array:
516 return "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";
527 default:
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
531 // gone wrong.
532 return "Unknown!";
533 }
534 }
535
536 const char* arrayClassToString(Array::Class arrayClass)
537 {
538 switch (arrayClass) {
539 case Array::Array:
540 return "Array";
541 case Array::OriginalArray:
542 return "OriginalArray";
543 case Array::NonArray:
544 return "NonArray";
545 case Array::OriginalNonArray:
546 return "OriginalNonArray";
547 case Array::PossiblyArray:
548 return "PossiblyArray";
549 default:
550 return "Unknown!";
551 }
552 }
553
554 const char* arraySpeculationToString(Array::Speculation speculation)
555 {
556 switch (speculation) {
557 case Array::SaneChain:
558 return "SaneChain";
559 case Array::InBounds:
560 return "InBounds";
561 case Array::ToHole:
562 return "ToHole";
563 case Array::OutOfBounds:
564 return "OutOfBounds";
565 default:
566 return "Unknown!";
567 }
568 }
569
570 const char* arrayConversionToString(Array::Conversion conversion)
571 {
572 switch (conversion) {
573 case Array::AsIs:
574 return "AsIs";
575 case Array::Convert:
576 return "Convert";
577 default:
578 return "Unknown!";
579 }
580 }
581
582 IndexingType toIndexingShape(Array::Type type)
583 {
584 switch (type) {
585 case Array::Int32:
586 return Int32Shape;
587 case Array::Double:
588 return DoubleShape;
589 case Array::Contiguous:
590 return ContiguousShape;
591 case Array::ArrayStorage:
592 return ArrayStorageShape;
593 case Array::SlowPutArrayStorage:
594 return SlowPutArrayStorageShape;
595 default:
596 return NoIndexingShape;
597 }
598 }
599
600 TypedArrayType toTypedArrayType(Array::Type type)
601 {
602 switch (type) {
603 case Array::Int8Array:
604 return TypeInt8;
605 case Array::Int16Array:
606 return TypeInt16;
607 case Array::Int32Array:
608 return TypeInt32;
609 case Array::Uint8Array:
610 return TypeUint8;
611 case Array::Uint8ClampedArray:
612 return TypeUint8Clamped;
613 case Array::Uint16Array:
614 return TypeUint16;
615 case Array::Uint32Array:
616 return TypeUint32;
617 case Array::Float32Array:
618 return TypeFloat32;
619 case Array::Float64Array:
620 return TypeFloat64;
621 default:
622 return NotTypedArray;
623 }
624 }
625
626 Array::Type toArrayType(TypedArrayType type)
627 {
628 switch (type) {
629 case TypeInt8:
630 return Array::Int8Array;
631 case TypeInt16:
632 return Array::Int16Array;
633 case TypeInt32:
634 return Array::Int32Array;
635 case TypeUint8:
636 return Array::Uint8Array;
637 case TypeUint8Clamped:
638 return Array::Uint8ClampedArray;
639 case TypeUint16:
640 return Array::Uint16Array;
641 case TypeUint32:
642 return Array::Uint32Array;
643 case TypeFloat32:
644 return Array::Float32Array;
645 case TypeFloat64:
646 return Array::Float64Array;
647 default:
648 return Array::Generic;
649 }
650 }
651
652 bool permitsBoundsCheckLowering(Array::Type type)
653 {
654 switch (type) {
655 case Array::Int32:
656 case Array::Double:
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:
667 return true;
668 default:
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.
673 return false;
674 }
675 }
676
677 bool ArrayMode::permitsBoundsCheckLowering() const
678 {
679 return DFG::permitsBoundsCheckLowering(type()) && isInBounds();
680 }
681
682 void ArrayMode::dump(PrintStream& out) const
683 {
684 out.print(type(), arrayClass(), speculation(), conversion());
685 }
686
687 } } // namespace JSC::DFG
688
689 namespace WTF {
690
691 void printInternal(PrintStream& out, JSC::DFG::Array::Type type)
692 {
693 out.print(JSC::DFG::arrayTypeToString(type));
694 }
695
696 void printInternal(PrintStream& out, JSC::DFG::Array::Class arrayClass)
697 {
698 out.print(JSC::DFG::arrayClassToString(arrayClass));
699 }
700
701 void printInternal(PrintStream& out, JSC::DFG::Array::Speculation speculation)
702 {
703 out.print(JSC::DFG::arraySpeculationToString(speculation));
704 }
705
706 void printInternal(PrintStream& out, JSC::DFG::Array::Conversion conversion)
707 {
708 out.print(JSC::DFG::arrayConversionToString(conversion));
709 }
710
711 } // namespace WTF
712
713 #endif // ENABLE(DFG_JIT)
714