2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef ArrayProfile_h
27 #define ArrayProfile_h
29 #include "ConcurrentJITLock.h"
31 #include "Structure.h"
32 #include <wtf/HashMap.h>
33 #include <wtf/SegmentedVector.h>
38 class LLIntOffsetsExtractor
;
40 // This is a bitfield where each bit represents an type of array access that we have seen.
41 // There are 16 indexing types that use the lower bits.
42 // There are 9 typed array types taking the bits 16 to 25.
43 typedef unsigned ArrayModes
;
45 const ArrayModes Int8ArrayMode
= 1 << 16;
46 const ArrayModes Int16ArrayMode
= 1 << 17;
47 const ArrayModes Int32ArrayMode
= 1 << 18;
48 const ArrayModes Uint8ArrayMode
= 1 << 19;
49 const ArrayModes Uint8ClampedArrayMode
= 1 << 20;
50 const ArrayModes Uint16ArrayMode
= 1 << 21;
51 const ArrayModes Uint32ArrayMode
= 1 << 22;
52 const ArrayModes Float32ArrayMode
= 1 << 23;
53 const ArrayModes Float64ArrayMode
= 1 << 24;
55 #define asArrayModes(type) \
56 (static_cast<unsigned>(1) << static_cast<unsigned>(type))
58 #define ALL_TYPED_ARRAY_MODES \
63 | Uint8ClampedArrayMode \
70 #define ALL_NON_ARRAY_ARRAY_MODES \
71 (asArrayModes(NonArray) \
72 | asArrayModes(NonArrayWithInt32) \
73 | asArrayModes(NonArrayWithDouble) \
74 | asArrayModes(NonArrayWithContiguous) \
75 | asArrayModes(NonArrayWithArrayStorage) \
76 | asArrayModes(NonArrayWithSlowPutArrayStorage) \
77 | ALL_TYPED_ARRAY_MODES)
79 #define ALL_ARRAY_ARRAY_MODES \
80 (asArrayModes(ArrayClass) \
81 | asArrayModes(ArrayWithUndecided) \
82 | asArrayModes(ArrayWithInt32) \
83 | asArrayModes(ArrayWithDouble) \
84 | asArrayModes(ArrayWithContiguous) \
85 | asArrayModes(ArrayWithArrayStorage) \
86 | asArrayModes(ArrayWithSlowPutArrayStorage))
88 #define ALL_ARRAY_MODES (ALL_NON_ARRAY_ARRAY_MODES | ALL_ARRAY_ARRAY_MODES)
90 inline ArrayModes
arrayModeFromStructure(Structure
* structure
)
92 switch (structure
->classInfo()->typedArrayStorageType
) {
96 return Uint8ArrayMode
;
97 case TypeUint8Clamped
:
98 return Uint8ClampedArrayMode
;
100 return Int16ArrayMode
;
102 return Uint16ArrayMode
;
104 return Int32ArrayMode
;
106 return Uint32ArrayMode
;
108 return Float32ArrayMode
;
110 return Float64ArrayMode
;
115 return asArrayModes(structure
->indexingType());
118 void dumpArrayModes(PrintStream
&, ArrayModes
);
119 MAKE_PRINT_ADAPTOR(ArrayModesDump
, ArrayModes
, dumpArrayModes
);
121 inline bool mergeArrayModes(ArrayModes
& left
, ArrayModes right
)
123 ArrayModes newModes
= left
| right
;
124 if (newModes
== left
)
130 inline bool arrayModesAreClearOrTop(ArrayModes modes
)
132 return !modes
|| modes
== ALL_ARRAY_MODES
;
135 // Checks if proven is a subset of expected.
136 inline bool arrayModesAlreadyChecked(ArrayModes proven
, ArrayModes expected
)
138 return (expected
| proven
) == expected
;
141 inline bool arrayModesInclude(ArrayModes arrayModes
, IndexingType shape
)
143 return !!(arrayModes
& (asArrayModes(NonArray
| shape
) | asArrayModes(ArrayClass
| shape
)));
146 inline bool shouldUseSlowPutArrayStorage(ArrayModes arrayModes
)
148 return arrayModesInclude(arrayModes
, SlowPutArrayStorageShape
);
151 inline bool shouldUseFastArrayStorage(ArrayModes arrayModes
)
153 return arrayModesInclude(arrayModes
, ArrayStorageShape
);
156 inline bool shouldUseContiguous(ArrayModes arrayModes
)
158 return arrayModesInclude(arrayModes
, ContiguousShape
);
161 inline bool shouldUseDouble(ArrayModes arrayModes
)
163 return arrayModesInclude(arrayModes
, DoubleShape
);
166 inline bool shouldUseInt32(ArrayModes arrayModes
)
168 return arrayModesInclude(arrayModes
, Int32Shape
);
171 inline bool hasSeenArray(ArrayModes arrayModes
)
173 return arrayModes
& ALL_ARRAY_ARRAY_MODES
;
176 inline bool hasSeenNonArray(ArrayModes arrayModes
)
178 return arrayModes
& ALL_NON_ARRAY_ARRAY_MODES
;
184 : m_bytecodeOffset(std::numeric_limits
<unsigned>::max())
185 , m_lastSeenStructureID(0)
186 , m_mayStoreToHole(false)
187 , m_outOfBounds(false)
188 , m_mayInterceptIndexedAccesses(false)
189 , m_usesOriginalArrayStructures(true)
190 , m_didPerformFirstRunPruning(false)
191 , m_observedArrayModes(0)
195 ArrayProfile(unsigned bytecodeOffset
)
196 : m_bytecodeOffset(bytecodeOffset
)
197 , m_lastSeenStructureID(0)
198 , m_mayStoreToHole(false)
199 , m_outOfBounds(false)
200 , m_mayInterceptIndexedAccesses(false)
201 , m_usesOriginalArrayStructures(true)
202 , m_didPerformFirstRunPruning(false)
203 , m_observedArrayModes(0)
207 unsigned bytecodeOffset() const { return m_bytecodeOffset
; }
209 StructureID
* addressOfLastSeenStructureID() { return &m_lastSeenStructureID
; }
210 ArrayModes
* addressOfArrayModes() { return &m_observedArrayModes
; }
211 bool* addressOfMayStoreToHole() { return &m_mayStoreToHole
; }
213 void setOutOfBounds() { m_outOfBounds
= true; }
214 bool* addressOfOutOfBounds() { return &m_outOfBounds
; }
216 void observeStructure(Structure
* structure
)
218 m_lastSeenStructureID
= structure
->id();
221 void computeUpdatedPrediction(const ConcurrentJITLocker
&, CodeBlock
*);
222 void computeUpdatedPrediction(const ConcurrentJITLocker
&, CodeBlock
*, Structure
* lastSeenStructure
);
224 ArrayModes
observedArrayModes(const ConcurrentJITLocker
&) const { return m_observedArrayModes
; }
225 bool mayInterceptIndexedAccesses(const ConcurrentJITLocker
&) const { return m_mayInterceptIndexedAccesses
; }
227 bool mayStoreToHole(const ConcurrentJITLocker
&) const { return m_mayStoreToHole
; }
228 bool outOfBounds(const ConcurrentJITLocker
&) const { return m_outOfBounds
; }
230 bool usesOriginalArrayStructures(const ConcurrentJITLocker
&) const { return m_usesOriginalArrayStructures
; }
232 CString
briefDescription(const ConcurrentJITLocker
&, CodeBlock
*);
233 CString
briefDescriptionWithoutUpdating(const ConcurrentJITLocker
&);
236 friend class LLIntOffsetsExtractor
;
238 static Structure
* polymorphicStructure() { return static_cast<Structure
*>(reinterpret_cast<void*>(1)); }
240 unsigned m_bytecodeOffset
;
241 StructureID m_lastSeenStructureID
;
242 bool m_mayStoreToHole
; // This flag may become overloaded to indicate other special cases that were encountered during array access, as it depends on indexing type. Since we currently have basically just one indexing type (two variants of ArrayStorage), this flag for now just means exactly what its name implies.
244 bool m_mayInterceptIndexedAccesses
: 1;
245 bool m_usesOriginalArrayStructures
: 1;
246 bool m_didPerformFirstRunPruning
: 1;
247 ArrayModes m_observedArrayModes
;
250 typedef SegmentedVector
<ArrayProfile
, 4> ArrayProfileVector
;
254 #endif // ArrayProfile_h