[JSC] Do not use asArrayModes() with Structures because it discards TypedArray inform...
authoryusukesuzuki@slowstart.org <yusukesuzuki@slowstart.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Jan 2019 22:31:06 +0000 (22:31 +0000)
committeryusukesuzuki@slowstart.org <yusukesuzuki@slowstart.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 14 Jan 2019 22:31:06 +0000 (22:31 +0000)
https://bugs.webkit.org/show_bug.cgi?id=193372

Reviewed by Saam Barati.

JSTests:

* stress/typed-array-array-modes-profile.js: Added.
(foo):

Source/JavaScriptCore:

When RegisteredStructureSet is filtered with AbstractValue, we use structure, SpeculationType, and ArrayModes.
However, we use asArrayModes() function with IndexingMode to compute the ArrayModes in AbstractValue. This is
wrong since this discards TypedArray ArrayModes. As a result, if RegisteredStructureSet with TypedArrays is
filtered with ArrayModes of AbstractValue populated from TypedArrays, we filter all the structures out since
AbstractValue's ArrayModes become NonArray, which is wrong with the TypedArrays' ArrayModes. This leads to
incorrect FTL code generation with MultiGetByOffset etc. nodes because,

1. AI think that this MultiGetByOffset never succeeds since all the values of RegisteredStructureSet are filtered out by the AbstractValue.
2. AI says the state of MultiGetByOffset is invalid since AI think it never succeeds.
3. So subsequent code becomes FTL crash code since AI think the execution should do OSR exit.
4. Then, FTL emits the code for MultiGetByOffset, and emits crash after that.
5. But in reality, the incoming value can match to the one of the RegisteredStructureSet value since (1)'s structures are incorrectly filtered by the incorrect ArrayModes.
6. Then, the execution goes on, and falls into the FTL crash.

This patch fixes the incorrect ArrayModes calculation by the following changes

1. Rename asArrayModes to asArrayModesIgnoringTypedArrays.
2. Fix incorrect asArrayModesIgnoringTypedArrays use in our code. Use arrayModesFromStructure instead.
3. Fix OSR exit code which stores incorrect ArrayModes to the profiles.

* bytecode/ArrayProfile.cpp:
(JSC::dumpArrayModes):
(JSC::ArrayProfile::computeUpdatedPrediction):
* bytecode/ArrayProfile.h:
(JSC::asArrayModesIgnoringTypedArrays):
(JSC::arrayModesFromStructure):
(JSC::arrayModesIncludeIgnoringTypedArrays):
(JSC::shouldUseSlowPutArrayStorage):
(JSC::shouldUseFastArrayStorage):
(JSC::shouldUseContiguous):
(JSC::shouldUseDouble):
(JSC::shouldUseInt32):
(JSC::asArrayModes): Deleted.
(JSC::arrayModeFromStructure): Deleted.
(JSC::arrayModesInclude): Deleted.
* dfg/DFGAbstractValue.cpp:
(JSC::DFG::AbstractValue::observeTransitions):
(JSC::DFG::AbstractValue::set):
(JSC::DFG::AbstractValue::mergeOSREntryValue):
(JSC::DFG::AbstractValue::contains const):
* dfg/DFGAbstractValue.h:
(JSC::DFG::AbstractValue::observeTransition):
(JSC::DFG::AbstractValue::validate const):
(JSC::DFG::AbstractValue::observeIndexingTypeTransition):
* dfg/DFGArrayMode.cpp:
(JSC::DFG::ArrayMode::fromObserved):
(JSC::DFG::ArrayMode::alreadyChecked const):
* dfg/DFGArrayMode.h:
(JSC::DFG::ArrayMode::structureWouldPassArrayModeFiltering):
(JSC::DFG::ArrayMode::arrayModesThatPassFiltering const):
(JSC::DFG::ArrayMode::arrayModesWithIndexingShape const):
* dfg/DFGOSRExit.cpp:
(JSC::DFG::OSRExit::executeOSRExit):
(JSC::DFG::OSRExit::compileExit):
* dfg/DFGRegisteredStructureSet.cpp:
(JSC::DFG::RegisteredStructureSet::filterArrayModes):
(JSC::DFG::RegisteredStructureSet::arrayModesFromStructures const):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileStub):
* jit/JITInlines.h:
(JSC::JIT::chooseArrayMode):
(JSC::arrayProfileSaw): Deleted.
* runtime/JSType.h:
(JSC::isTypedArrayType):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239951 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
JSTests/ChangeLog
JSTests/stress/typed-array-array-modes-profile.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/ArrayProfile.cpp
Source/JavaScriptCore/bytecode/ArrayProfile.h
Source/JavaScriptCore/dfg/DFGAbstractValue.cpp
Source/JavaScriptCore/dfg/DFGAbstractValue.h
Source/JavaScriptCore/dfg/DFGArrayMode.cpp
Source/JavaScriptCore/dfg/DFGArrayMode.h
Source/JavaScriptCore/dfg/DFGOSRExit.cpp
Source/JavaScriptCore/dfg/DFGRegisteredStructureSet.cpp
Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
Source/JavaScriptCore/jit/JITInlines.h
Source/JavaScriptCore/runtime/JSType.h

index bbcd257..b1f15c1 100644 (file)
@@ -1,3 +1,13 @@
+2019-01-14  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
+
+        [JSC] Do not use asArrayModes() with Structures because it discards TypedArray information
+        https://bugs.webkit.org/show_bug.cgi?id=193372
+
+        Reviewed by Saam Barati.
+
+        * stress/typed-array-array-modes-profile.js: Added.
+        (foo):
+
 2019-01-14  Mark Lam  <mark.lam@apple.com>
 
         Fix all CLoop JSC test failures (including some LLInt bugs due to recent bytecode format change).
diff --git a/JSTests/stress/typed-array-array-modes-profile.js b/JSTests/stress/typed-array-array-modes-profile.js
new file mode 100644 (file)
index 0000000..b927339
--- /dev/null
@@ -0,0 +1,18 @@
+function foo(o) {
+    for (var i = 0; i < 100; ++i) {
+        o.f = o.f;
+    }
+}
+
+let typedArrays = [
+    Uint8Array,
+    Uint32Array,
+    Uint8Array,
+];
+
+for (let constructor of typedArrays) {
+    let a = new constructor(0);
+    for (let i = 0; i < 10000; i++) {
+        foo(a);
+    }
+}
index b7d459c..cc5b392 100644 (file)
@@ -1,3 +1,75 @@
+2019-01-14  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
+
+        [JSC] Do not use asArrayModes() with Structures because it discards TypedArray information
+        https://bugs.webkit.org/show_bug.cgi?id=193372
+
+        Reviewed by Saam Barati.
+
+        When RegisteredStructureSet is filtered with AbstractValue, we use structure, SpeculationType, and ArrayModes.
+        However, we use asArrayModes() function with IndexingMode to compute the ArrayModes in AbstractValue. This is
+        wrong since this discards TypedArray ArrayModes. As a result, if RegisteredStructureSet with TypedArrays is
+        filtered with ArrayModes of AbstractValue populated from TypedArrays, we filter all the structures out since
+        AbstractValue's ArrayModes become NonArray, which is wrong with the TypedArrays' ArrayModes. This leads to
+        incorrect FTL code generation with MultiGetByOffset etc. nodes because,
+
+        1. AI think that this MultiGetByOffset never succeeds since all the values of RegisteredStructureSet are filtered out by the AbstractValue.
+        2. AI says the state of MultiGetByOffset is invalid since AI think it never succeeds.
+        3. So subsequent code becomes FTL crash code since AI think the execution should do OSR exit.
+        4. Then, FTL emits the code for MultiGetByOffset, and emits crash after that.
+        5. But in reality, the incoming value can match to the one of the RegisteredStructureSet value since (1)'s structures are incorrectly filtered by the incorrect ArrayModes.
+        6. Then, the execution goes on, and falls into the FTL crash.
+
+        This patch fixes the incorrect ArrayModes calculation by the following changes
+
+        1. Rename asArrayModes to asArrayModesIgnoringTypedArrays.
+        2. Fix incorrect asArrayModesIgnoringTypedArrays use in our code. Use arrayModesFromStructure instead.
+        3. Fix OSR exit code which stores incorrect ArrayModes to the profiles.
+
+        * bytecode/ArrayProfile.cpp:
+        (JSC::dumpArrayModes):
+        (JSC::ArrayProfile::computeUpdatedPrediction):
+        * bytecode/ArrayProfile.h:
+        (JSC::asArrayModesIgnoringTypedArrays):
+        (JSC::arrayModesFromStructure):
+        (JSC::arrayModesIncludeIgnoringTypedArrays):
+        (JSC::shouldUseSlowPutArrayStorage):
+        (JSC::shouldUseFastArrayStorage):
+        (JSC::shouldUseContiguous):
+        (JSC::shouldUseDouble):
+        (JSC::shouldUseInt32):
+        (JSC::asArrayModes): Deleted.
+        (JSC::arrayModeFromStructure): Deleted.
+        (JSC::arrayModesInclude): Deleted.
+        * dfg/DFGAbstractValue.cpp:
+        (JSC::DFG::AbstractValue::observeTransitions):
+        (JSC::DFG::AbstractValue::set):
+        (JSC::DFG::AbstractValue::mergeOSREntryValue):
+        (JSC::DFG::AbstractValue::contains const):
+        * dfg/DFGAbstractValue.h:
+        (JSC::DFG::AbstractValue::observeTransition):
+        (JSC::DFG::AbstractValue::validate const):
+        (JSC::DFG::AbstractValue::observeIndexingTypeTransition):
+        * dfg/DFGArrayMode.cpp:
+        (JSC::DFG::ArrayMode::fromObserved):
+        (JSC::DFG::ArrayMode::alreadyChecked const):
+        * dfg/DFGArrayMode.h:
+        (JSC::DFG::ArrayMode::structureWouldPassArrayModeFiltering):
+        (JSC::DFG::ArrayMode::arrayModesThatPassFiltering const):
+        (JSC::DFG::ArrayMode::arrayModesWithIndexingShape const):
+        * dfg/DFGOSRExit.cpp:
+        (JSC::DFG::OSRExit::executeOSRExit):
+        (JSC::DFG::OSRExit::compileExit):
+        * dfg/DFGRegisteredStructureSet.cpp:
+        (JSC::DFG::RegisteredStructureSet::filterArrayModes):
+        (JSC::DFG::RegisteredStructureSet::arrayModesFromStructures const):
+        * ftl/FTLOSRExitCompiler.cpp:
+        (JSC::FTL::compileStub):
+        * jit/JITInlines.h:
+        (JSC::JIT::chooseArrayMode):
+        (JSC::arrayProfileSaw): Deleted.
+        * runtime/JSType.h:
+        (JSC::isTypedArrayType):
+
 2019-01-14  Mark Lam  <mark.lam@apple.com>
 
         Re-enable ability to build --cloop builds.
index f2ff9af..c00aef2 100644 (file)
@@ -37,6 +37,19 @@ namespace JSC {
 const char* const ArrayProfile::s_typeName = "ArrayProfile";
 #endif
 
+// Keep in sync with the order of TypedArrayType.
+const ArrayModes typedArrayModes[NumberOfTypedArrayTypesExcludingDataView] = {
+    Int8ArrayMode,
+    Uint8ArrayMode,
+    Uint8ClampedArrayMode,
+    Int16ArrayMode,
+    Uint16ArrayMode,
+    Int32ArrayMode,
+    Uint32ArrayMode,
+    Float32ArrayMode,
+    Float64ArrayMode,
+};
+
 void dumpArrayModes(PrintStream& out, ArrayModes arrayModes)
 {
     if (!arrayModes) {
@@ -50,37 +63,37 @@ void dumpArrayModes(PrintStream& out, ArrayModes arrayModes)
     }
     
     CommaPrinter comma("|");
-    if (arrayModes & asArrayModes(NonArray))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(NonArray))
         out.print(comma, "NonArray");
-    if (arrayModes & asArrayModes(NonArrayWithInt32))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(NonArrayWithInt32))
         out.print(comma, "NonArrayWithInt32");
-    if (arrayModes & asArrayModes(NonArrayWithDouble))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(NonArrayWithDouble))
         out.print(comma, "NonArrayWithDouble");
-    if (arrayModes & asArrayModes(NonArrayWithContiguous))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(NonArrayWithContiguous))
         out.print(comma, "NonArrayWithContiguous");
-    if (arrayModes & asArrayModes(NonArrayWithArrayStorage))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage))
         out.print(comma, "NonArrayWithArrayStorage");
-    if (arrayModes & asArrayModes(NonArrayWithSlowPutArrayStorage))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage))
         out.print(comma, "NonArrayWithSlowPutArrayStorage");
-    if (arrayModes & asArrayModes(ArrayClass))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(ArrayClass))
         out.print(comma, "ArrayClass");
-    if (arrayModes & asArrayModes(ArrayWithUndecided))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(ArrayWithUndecided))
         out.print(comma, "ArrayWithUndecided");
-    if (arrayModes & asArrayModes(ArrayWithInt32))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(ArrayWithInt32))
         out.print(comma, "ArrayWithInt32");
-    if (arrayModes & asArrayModes(ArrayWithDouble))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(ArrayWithDouble))
         out.print(comma, "ArrayWithDouble");
-    if (arrayModes & asArrayModes(ArrayWithContiguous))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(ArrayWithContiguous))
         out.print(comma, "ArrayWithContiguous");
-    if (arrayModes & asArrayModes(ArrayWithArrayStorage))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage))
         out.print(comma, "ArrayWithArrayStorage");
-    if (arrayModes & asArrayModes(ArrayWithSlowPutArrayStorage))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage))
         out.print(comma, "ArrayWithSlowPutArrayStorage");
-    if (arrayModes & asArrayModes(CopyOnWriteArrayWithInt32))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithInt32))
         out.print(comma, "CopyOnWriteArrayWithInt32");
-    if (arrayModes & asArrayModes(CopyOnWriteArrayWithDouble))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithDouble))
         out.print(comma, "CopyOnWriteArrayWithDouble");
-    if (arrayModes & asArrayModes(CopyOnWriteArrayWithContiguous))
+    if (arrayModes & asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithContiguous))
         out.print(comma, "CopyOnWriteArrayWithContiguous");
 
     if (arrayModes & Int8ArrayMode)
@@ -115,11 +128,11 @@ void ArrayProfile::computeUpdatedPrediction(const ConcurrentJSLocker& locker, Co
 
 void ArrayProfile::computeUpdatedPrediction(const ConcurrentJSLocker&, CodeBlock* codeBlock, Structure* lastSeenStructure)
 {
-    m_observedArrayModes |= arrayModeFromStructure(lastSeenStructure);
+    m_observedArrayModes |= arrayModesFromStructure(lastSeenStructure);
     
     if (!m_didPerformFirstRunPruning
         && hasTwoOrMoreBitsSet(m_observedArrayModes)) {
-        m_observedArrayModes = arrayModeFromStructure(lastSeenStructure);
+        m_observedArrayModes = arrayModesFromStructure(lastSeenStructure);
         m_didPerformFirstRunPruning = true;
     }
     
index b9d9f37..ee204e1 100644 (file)
@@ -58,7 +58,9 @@ const ArrayModes Uint32ArrayMode = 1 << 27;
 const ArrayModes Float32ArrayMode = 1 << 28;
 const ArrayModes Float64ArrayMode = 1 << 29;
 
-constexpr ArrayModes asArrayModes(IndexingType indexingMode)
+extern const ArrayModes typedArrayModes[NumberOfTypedArrayTypesExcludingDataView];
+
+constexpr ArrayModes asArrayModesIgnoringTypedArrays(IndexingType indexingMode)
 {
     return static_cast<unsigned>(1) << static_cast<unsigned>(indexingMode);
 }
@@ -76,12 +78,12 @@ constexpr ArrayModes asArrayModes(IndexingType indexingMode)
     )
 
 #define ALL_NON_ARRAY_ARRAY_MODES                       \
-    (asArrayModes(NonArray)                             \
-    | asArrayModes(NonArrayWithInt32)                   \
-    | asArrayModes(NonArrayWithDouble)                  \
-    | asArrayModes(NonArrayWithContiguous)              \
-    | asArrayModes(NonArrayWithArrayStorage)            \
-    | asArrayModes(NonArrayWithSlowPutArrayStorage)     \
+    (asArrayModesIgnoringTypedArrays(NonArray)                             \
+    | asArrayModesIgnoringTypedArrays(NonArrayWithInt32)                   \
+    | asArrayModesIgnoringTypedArrays(NonArrayWithDouble)                  \
+    | asArrayModesIgnoringTypedArrays(NonArrayWithContiguous)              \
+    | asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage)            \
+    | asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage)     \
     | ALL_TYPED_ARRAY_MODES)
 
 #define ALL_COPY_ON_WRITE_ARRAY_MODES                   \
@@ -90,13 +92,13 @@ constexpr ArrayModes asArrayModes(IndexingType indexingMode)
     | CopyOnWriteArrayWithContiguousArrayMode)
 
 #define ALL_WRITABLE_ARRAY_ARRAY_MODES                  \
-    (asArrayModes(ArrayClass)                           \
-    | asArrayModes(ArrayWithUndecided)                  \
-    | asArrayModes(ArrayWithInt32)                      \
-    | asArrayModes(ArrayWithDouble)                     \
-    | asArrayModes(ArrayWithContiguous)                 \
-    | asArrayModes(ArrayWithArrayStorage)               \
-    | asArrayModes(ArrayWithSlowPutArrayStorage))
+    (asArrayModesIgnoringTypedArrays(ArrayClass)                           \
+    | asArrayModesIgnoringTypedArrays(ArrayWithUndecided)                  \
+    | asArrayModesIgnoringTypedArrays(ArrayWithInt32)                      \
+    | asArrayModesIgnoringTypedArrays(ArrayWithDouble)                     \
+    | asArrayModesIgnoringTypedArrays(ArrayWithContiguous)                 \
+    | asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage)               \
+    | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage))
 
 #define ALL_ARRAY_ARRAY_MODES                           \
     (ALL_WRITABLE_ARRAY_ARRAY_MODES                     \
@@ -104,33 +106,12 @@ constexpr ArrayModes asArrayModes(IndexingType indexingMode)
 
 #define ALL_ARRAY_MODES (ALL_NON_ARRAY_ARRAY_MODES | ALL_ARRAY_ARRAY_MODES)
 
-inline ArrayModes arrayModeFromStructure(Structure* structure)
+inline ArrayModes arrayModesFromStructure(Structure* structure)
 {
-    switch (structure->classInfo()->typedArrayStorageType) {
-    case TypeInt8:
-        return Int8ArrayMode;
-    case TypeUint8:
-        return Uint8ArrayMode;
-    case TypeUint8Clamped:
-        return Uint8ClampedArrayMode;
-    case TypeInt16:
-        return Int16ArrayMode;
-    case TypeUint16:
-        return Uint16ArrayMode;
-    case TypeInt32:
-        return Int32ArrayMode;
-    case TypeUint32:
-        return Uint32ArrayMode;
-    case TypeFloat32:
-        return Float32ArrayMode;
-    case TypeFloat64:
-        return Float64ArrayMode;
-    case TypeDataView:
-    case NotTypedArray:
-        break;
-    }
-
-    return asArrayModes(structure->indexingMode());
+    JSType type = structure->typeInfo().type();
+    if (isTypedArrayType(type))
+        return typedArrayModes[type - FirstTypedArrayType];
+    return asArrayModesIgnoringTypedArrays(structure->indexingMode());
 }
 
 void dumpArrayModes(PrintStream&, ArrayModes);
@@ -156,37 +137,37 @@ inline bool arrayModesAlreadyChecked(ArrayModes proven, ArrayModes expected)
     return (expected | proven) == expected;
 }
 
-inline bool arrayModesInclude(ArrayModes arrayModes, IndexingType shape)
+inline bool arrayModesIncludeIgnoringTypedArrays(ArrayModes arrayModes, IndexingType shape)
 {
-    ArrayModes modes = asArrayModes(NonArray | shape) | asArrayModes(ArrayClass | shape);
+    ArrayModes modes = asArrayModesIgnoringTypedArrays(NonArray | shape) | asArrayModesIgnoringTypedArrays(ArrayClass | shape);
     if (hasInt32(shape) || hasDouble(shape) || hasContiguous(shape))
-        modes |= asArrayModes(ArrayClass | shape | CopyOnWrite);
+        modes |= asArrayModesIgnoringTypedArrays(ArrayClass | shape | CopyOnWrite);
     return !!(arrayModes & modes);
 }
 
 inline bool shouldUseSlowPutArrayStorage(ArrayModes arrayModes)
 {
-    return arrayModesInclude(arrayModes, SlowPutArrayStorageShape);
+    return arrayModesIncludeIgnoringTypedArrays(arrayModes, SlowPutArrayStorageShape);
 }
 
 inline bool shouldUseFastArrayStorage(ArrayModes arrayModes)
 {
-    return arrayModesInclude(arrayModes, ArrayStorageShape);
+    return arrayModesIncludeIgnoringTypedArrays(arrayModes, ArrayStorageShape);
 }
 
 inline bool shouldUseContiguous(ArrayModes arrayModes)
 {
-    return arrayModesInclude(arrayModes, ContiguousShape);
+    return arrayModesIncludeIgnoringTypedArrays(arrayModes, ContiguousShape);
 }
 
 inline bool shouldUseDouble(ArrayModes arrayModes)
 {
-    return arrayModesInclude(arrayModes, DoubleShape);
+    return arrayModesIncludeIgnoringTypedArrays(arrayModes, DoubleShape);
 }
 
 inline bool shouldUseInt32(ArrayModes arrayModes)
 {
-    return arrayModesInclude(arrayModes, Int32Shape);
+    return arrayModesIncludeIgnoringTypedArrays(arrayModes, Int32Shape);
 }
 
 inline bool hasSeenArray(ArrayModes arrayModes)
index e4e501f..ae2f15f 100644 (file)
@@ -40,8 +40,8 @@ void AbstractValue::observeTransitions(const TransitionVector& vector)
         m_structure.observeTransitions(vector);
         ArrayModes newModes = 0;
         for (unsigned i = vector.size(); i--;) {
-            if (m_arrayModes & asArrayModes(vector[i].previous->indexingType()))
-                newModes |= asArrayModes(vector[i].next->indexingType());
+            if (m_arrayModes & arrayModesFromStructure(vector[i].previous.get()))
+                newModes |= arrayModesFromStructure(vector[i].next.get());
         }
         m_arrayModes |= newModes;
     }
@@ -60,7 +60,7 @@ void AbstractValue::set(Graph& graph, const FrozenValue& value, StructureClobber
                 m_arrayModes = ALL_ARRAY_MODES;
                 m_structure.clobber();
             } else
-                m_arrayModes = asArrayModes(structure->indexingMode());
+                m_arrayModes = arrayModesFromStructure(structure);
         } else {
             m_structure.makeTop();
             m_arrayModes = ALL_ARRAY_MODES;
@@ -87,7 +87,7 @@ void AbstractValue::set(Graph& graph, RegisteredStructure structure)
     RELEASE_ASSERT(structure);
     
     m_structure = structure;
-    m_arrayModes = asArrayModes(structure->indexingMode());
+    m_arrayModes = arrayModesFromStructure(structure.get());
     m_type = speculationFromStructure(structure.get());
     m_value = JSValue();
     
@@ -228,7 +228,7 @@ bool AbstractValue::mergeOSREntryValue(Graph& graph, JSValue value)
         FrozenValue* frozenValue = graph.freeze(value);
         if (frozenValue->pointsToHeap()) {
             m_structure = graph.registerStructure(frozenValue->structure());
-            m_arrayModes = asArrayModes(frozenValue->structure()->indexingMode());
+            m_arrayModes = arrayModesFromStructure(frozenValue->structure());
         } else {
             m_structure.clear();
             m_arrayModes = 0;
@@ -240,7 +240,7 @@ bool AbstractValue::mergeOSREntryValue(Graph& graph, JSValue value)
         mergeSpeculation(m_type, speculationFromValue(value));
         if (!!value && value.isCell()) {
             RegisteredStructure structure = graph.registerStructure(value.asCell()->structure(graph.m_vm));
-            mergeArrayModes(m_arrayModes, asArrayModes(structure->indexingMode()));
+            mergeArrayModes(m_arrayModes, arrayModesFromStructure(structure.get()));
             m_structure.merge(RegisteredStructureSet(structure));
         }
         if (m_value != value)
@@ -365,7 +365,7 @@ FiltrationResult AbstractValue::filterByValue(const FrozenValue& value)
 bool AbstractValue::contains(RegisteredStructure structure) const
 {
     return couldBeType(speculationFromStructure(structure.get()))
-        && (m_arrayModes & arrayModeFromStructure(structure.get()))
+        && (m_arrayModes & arrayModesFromStructure(structure.get()))
         && m_structure.contains(structure);
 }
 
index 294efb8..107046f 100644 (file)
@@ -137,7 +137,7 @@ struct AbstractValue {
     {
         if (m_type & SpecCell) {
             m_structure.observeTransition(from, to);
-            observeIndexingTypeTransition(from->indexingType(), to->indexingType());
+            observeIndexingTypeTransition(arrayModesFromStructure(from.get()), arrayModesFromStructure(to.get()));
         }
         checkConsistency();
     }
@@ -397,7 +397,7 @@ struct AbstractValue {
             ASSERT(m_type & SpecCell);
             Structure* structure = value.asCell()->structure();
             return m_structure.contains(structure)
-                && (m_arrayModes & asArrayModes(structure->indexingMode()));
+                && (m_arrayModes & arrayModesFromStructure(structure));
         }
         
         return true;
@@ -492,10 +492,10 @@ private:
         m_arrayModes = ALL_ARRAY_MODES;
     }
     
-    void observeIndexingTypeTransition(IndexingType from, IndexingType to)
+    void observeIndexingTypeTransition(ArrayModes from, ArrayModes to)
     {
-        if (m_arrayModes & asArrayModes(from))
-            m_arrayModes |= asArrayModes(to);
+        if (m_arrayModes & from)
+            m_arrayModes |= to;
     }
     
     bool validateType(JSValue value) const
index dfd68e6..f926cc1 100644 (file)
@@ -47,17 +47,17 @@ ArrayMode ArrayMode::fromObserved(const ConcurrentJSLocker& locker, ArrayProfile
         Array::Class isArray;
         Array::Conversion converts;
 
-        RELEASE_ASSERT((observed & (asArrayModes(toIndexingShape(type)) | asArrayModes(toIndexingShape(type) | ArrayClass) | asArrayModes(toIndexingShape(type) | ArrayClass | CopyOnWrite))) == observed);
+        RELEASE_ASSERT((observed & (asArrayModesIgnoringTypedArrays(toIndexingShape(type)) | asArrayModesIgnoringTypedArrays(toIndexingShape(type) | ArrayClass) | asArrayModesIgnoringTypedArrays(toIndexingShape(type) | ArrayClass | CopyOnWrite))) == observed);
 
-        if (observed & asArrayModes(toIndexingShape(type))) {
-            if ((observed & asArrayModes(toIndexingShape(type))) == observed)
+        if (observed & asArrayModesIgnoringTypedArrays(toIndexingShape(type))) {
+            if ((observed & asArrayModesIgnoringTypedArrays(toIndexingShape(type))) == observed)
                 isArray = nonArray;
             else
                 isArray = Array::PossiblyArray;
         } else
             isArray = Array::Array;
 
-        if (action == Array::Write && (observed & asArrayModes(toIndexingShape(type) | ArrayClass | CopyOnWrite)))
+        if (action == Array::Write && (observed & asArrayModesIgnoringTypedArrays(toIndexingShape(type) | ArrayClass | CopyOnWrite)))
             converts = Array::Convert;
         else
             converts = Array::AsIs;
@@ -69,62 +69,62 @@ ArrayMode ArrayMode::fromObserved(const ConcurrentJSLocker& locker, ArrayProfile
     switch (observed) {
     case 0:
         return ArrayMode(Array::Unprofiled);
-    case asArrayModes(NonArray):
+    case asArrayModesIgnoringTypedArrays(NonArray):
         if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker))
             return ArrayMode(Array::SelectUsingArguments, nonArray, Array::OutOfBounds, Array::Convert, action);
         return ArrayMode(Array::SelectUsingPredictions, nonArray, action).withSpeculationFromProfile(locker, profile, makeSafe);
 
-    case asArrayModes(ArrayWithUndecided):
+    case asArrayModesIgnoringTypedArrays(ArrayWithUndecided):
         if (action == Array::Write)
             return ArrayMode(Array::SelectUsingArguments, Array::Array, Array::OutOfBounds, Array::Convert, action);
         return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::AsIs, action).withProfile(locker, profile, makeSafe);
         
-    case asArrayModes(NonArray) | asArrayModes(ArrayWithUndecided):
+    case asArrayModesIgnoringTypedArrays(NonArray) | asArrayModesIgnoringTypedArrays(ArrayWithUndecided):
         if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker))
             return ArrayMode(Array::SelectUsingArguments, Array::PossiblyArray, Array::OutOfBounds, Array::Convert, action);
         return ArrayMode(Array::SelectUsingPredictions, action).withSpeculationFromProfile(locker, profile, makeSafe);
 
-    case asArrayModes(NonArrayWithInt32):
-    case asArrayModes(ArrayWithInt32):
-    case asArrayModes(CopyOnWriteArrayWithInt32):
-    case asArrayModes(NonArrayWithInt32) | asArrayModes(ArrayWithInt32):
-    case asArrayModes(NonArrayWithInt32) | asArrayModes(CopyOnWriteArrayWithInt32):
-    case asArrayModes(ArrayWithInt32) | asArrayModes(CopyOnWriteArrayWithInt32):
-    case asArrayModes(NonArrayWithInt32) | asArrayModes(ArrayWithInt32) | asArrayModes(CopyOnWriteArrayWithInt32):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithInt32):
+    case asArrayModesIgnoringTypedArrays(ArrayWithInt32):
+    case asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithInt32):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithInt32) | asArrayModesIgnoringTypedArrays(ArrayWithInt32):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithInt32) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithInt32):
+    case asArrayModesIgnoringTypedArrays(ArrayWithInt32) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithInt32):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithInt32) | asArrayModesIgnoringTypedArrays(ArrayWithInt32) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithInt32):
         return handleContiguousModes(Array::Int32, observed);
 
-    case asArrayModes(NonArrayWithDouble):
-    case asArrayModes(ArrayWithDouble):
-    case asArrayModes(CopyOnWriteArrayWithDouble):
-    case asArrayModes(NonArrayWithDouble) | asArrayModes(ArrayWithDouble):
-    case asArrayModes(NonArrayWithDouble) | asArrayModes(CopyOnWriteArrayWithDouble):
-    case asArrayModes(ArrayWithDouble) | asArrayModes(CopyOnWriteArrayWithDouble):
-    case asArrayModes(NonArrayWithDouble) | asArrayModes(ArrayWithDouble) | asArrayModes(CopyOnWriteArrayWithDouble):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithDouble):
+    case asArrayModesIgnoringTypedArrays(ArrayWithDouble):
+    case asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithDouble):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithDouble) | asArrayModesIgnoringTypedArrays(ArrayWithDouble):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithDouble) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithDouble):
+    case asArrayModesIgnoringTypedArrays(ArrayWithDouble) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithDouble):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithDouble) | asArrayModesIgnoringTypedArrays(ArrayWithDouble) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithDouble):
         return handleContiguousModes(Array::Double, observed);
 
-    case asArrayModes(NonArrayWithContiguous):
-    case asArrayModes(ArrayWithContiguous):
-    case asArrayModes(CopyOnWriteArrayWithContiguous):
-    case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous):
-    case asArrayModes(NonArrayWithContiguous) | asArrayModes(CopyOnWriteArrayWithContiguous):
-    case asArrayModes(ArrayWithContiguous) | asArrayModes(CopyOnWriteArrayWithContiguous):
-    case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous) | asArrayModes(CopyOnWriteArrayWithContiguous):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithContiguous):
+    case asArrayModesIgnoringTypedArrays(ArrayWithContiguous):
+    case asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithContiguous):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithContiguous) | asArrayModesIgnoringTypedArrays(ArrayWithContiguous):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithContiguous) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithContiguous):
+    case asArrayModesIgnoringTypedArrays(ArrayWithContiguous) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithContiguous):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithContiguous) | asArrayModesIgnoringTypedArrays(ArrayWithContiguous) | asArrayModesIgnoringTypedArrays(CopyOnWriteArrayWithContiguous):
         return handleContiguousModes(Array::Contiguous, observed);
 
-    case asArrayModes(NonArrayWithArrayStorage):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage):
         return ArrayMode(Array::ArrayStorage, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
-    case asArrayModes(NonArrayWithSlowPutArrayStorage):
-    case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage):
         return ArrayMode(Array::SlowPutArrayStorage, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
-    case asArrayModes(ArrayWithArrayStorage):
+    case asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage):
         return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs, action).withProfile(locker, profile, makeSafe);
-    case asArrayModes(ArrayWithSlowPutArrayStorage):
-    case asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
+    case asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
+    case asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
         return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs, action).withProfile(locker, profile, makeSafe);
-    case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage):
         return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
-    case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
-    case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
+    case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
         return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     case Int8ArrayMode:
         return ArrayMode(Array::Int8Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
@@ -150,7 +150,7 @@ ArrayMode ArrayMode::fromObserved(const ConcurrentJSLocker& locker, ArrayProfile
         if (observed & ALL_TYPED_ARRAY_MODES)
             return ArrayMode(Array::Generic, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
 
-        if ((observed & asArrayModes(NonArray)) && profile->mayInterceptIndexedAccesses(locker))
+        if ((observed & asArrayModesIgnoringTypedArrays(NonArray)) && profile->mayInterceptIndexedAccesses(locker))
             return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe);
         
         Array::Type type;
@@ -438,7 +438,7 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& va
     }
         
     case Array::Array: {
-        if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape | IsArray)))
+        if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModesIgnoringTypedArrays(shape | IsArray)))
             return true;
         if (value.m_structure.isTop())
             return false;
@@ -455,7 +455,7 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& va
     }
         
     default: {
-        if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape) | asArrayModes(shape | IsArray)))
+        if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModesIgnoringTypedArrays(shape) | asArrayModesIgnoringTypedArrays(shape | IsArray)))
             return true;
         if (value.m_structure.isTop())
             return false;
@@ -505,7 +505,7 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& va
         }
         
         case Array::Array: {
-            if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))
+            if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage)))
                 return true;
             if (value.m_structure.isTop())
                 return false;
@@ -520,7 +520,7 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& va
         }
         
         default: {
-            if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage)))
+            if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage)))
                 return true;
             if (value.m_structure.isTop())
                 return false;
index 0ac2ecc..c23b098 100644 (file)
@@ -420,7 +420,7 @@ public:
 
     bool structureWouldPassArrayModeFiltering(Structure* structure)
     {
-        return arrayModesAlreadyChecked(arrayModeFromStructure(structure), arrayModesThatPassFiltering());
+        return arrayModesAlreadyChecked(arrayModesFromStructure(structure), arrayModesThatPassFiltering());
     }
     
     ArrayModes arrayModesThatPassFiltering() const
@@ -445,8 +445,28 @@ public:
         case Array::DirectArguments:
         case Array::ScopedArguments:
             return arrayModesWithIndexingShapes(ArrayStorageShape, NonArray);
+        case Array::Int8Array:
+            return Int8ArrayMode;
+        case Array::Int16Array:
+            return Int16ArrayMode;
+        case Array::Int32Array:
+            return Int32ArrayMode;
+        case Array::Uint8Array:
+            return Uint8ArrayMode;
+        case Array::Uint8ClampedArray:
+            return Uint8ClampedArrayMode;
+        case Array::Uint16Array:
+            return Uint16ArrayMode;
+        case Array::Uint32Array:
+            return Uint32ArrayMode;
+        case Array::Float32Array:
+            return Float32ArrayMode;
+        case Array::Float64Array:
+            return Float64ArrayMode;
+        case Array::AnyTypedArray:
+            return ALL_TYPED_ARRAY_MODES;
         default:
-            return asArrayModes(NonArray);
+            return asArrayModesIgnoringTypedArrays(NonArray);
         }
 
         if (action() == Array::Write)
@@ -497,20 +517,20 @@ private:
         switch (arrayClass()) {
         case Array::NonArray:
         case Array::OriginalNonArray:
-            return asArrayModes(shape);
+            return asArrayModesIgnoringTypedArrays(shape);
         case Array::OriginalCopyOnWriteArray:
             ASSERT(hasInt32(shape) || hasDouble(shape) || hasContiguous(shape));
-            return asArrayModes(shape | IsArray) | asArrayModes(shape | IsArray | CopyOnWrite);
+            return asArrayModesIgnoringTypedArrays(shape | IsArray) | asArrayModesIgnoringTypedArrays(shape | IsArray | CopyOnWrite);
         case Array::Array:
             if (hasInt32(shape) || hasDouble(shape) || hasContiguous(shape))
-                return asArrayModes(shape | IsArray) | asArrayModes(shape | IsArray | CopyOnWrite);
+                return asArrayModesIgnoringTypedArrays(shape | IsArray) | asArrayModesIgnoringTypedArrays(shape | IsArray | CopyOnWrite);
             FALLTHROUGH;
         case Array::OriginalArray:
-            return asArrayModes(shape | IsArray);
+            return asArrayModesIgnoringTypedArrays(shape | IsArray);
         case Array::PossiblyArray:
             if (hasInt32(shape) || hasDouble(shape) || hasContiguous(shape))
-                return asArrayModes(shape) | asArrayModes(shape | IsArray) | asArrayModes(shape | IsArray | CopyOnWrite);
-            return asArrayModes(shape) | asArrayModes(shape | IsArray);
+                return asArrayModesIgnoringTypedArrays(shape) | asArrayModesIgnoringTypedArrays(shape | IsArray) | asArrayModesIgnoringTypedArrays(shape | IsArray | CopyOnWrite);
+            return asArrayModesIgnoringTypedArrays(shape) | asArrayModesIgnoringTypedArrays(shape | IsArray);
         default:
             // This is only necessary for C++ compilers that don't understand enums.
             return 0;
index 6d464f3..1aedef6 100644 (file)
@@ -507,7 +507,7 @@ void OSRExit::executeOSRExit(Context& context)
             ASSERT(exit.m_kind == BadCache || exit.m_kind == BadIndexingType);
             Structure* structure = profiledValue.asCell()->structure(vm);
             arrayProfile->observeStructure(structure);
-            arrayProfile->observeArrayMode(asArrayModes(structure->indexingMode()));
+            arrayProfile->observeArrayMode(arrayModesFromStructure(structure));
         }
         if (extraInitializationLevel <= ExtraInitializationLevel::ArrayProfileUpdate)
             break;
@@ -1185,6 +1185,15 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
 
                 jit.load32(AssemblyHelpers::Address(value, JSCell::structureIDOffset()), scratch1);
                 jit.store32(scratch1, arrayProfile->addressOfLastSeenStructureID());
+
+                jit.load8(AssemblyHelpers::Address(value, JSCell::typeInfoTypeOffset()), scratch2);
+                jit.sub32(AssemblyHelpers::TrustedImm32(FirstTypedArrayType), scratch2);
+                auto notTypedArray = jit.branch32(MacroAssembler::AboveOrEqual, scratch2, AssemblyHelpers::TrustedImm32(NumberOfTypedArrayTypesExcludingDataView));
+                jit.move(AssemblyHelpers::TrustedImmPtr(typedArrayModes), scratch1);
+                jit.load32(AssemblyHelpers::BaseIndex(scratch1, scratch2, AssemblyHelpers::TimesFour), scratch2);
+                auto storeArrayModes = jit.jump();
+
+                notTypedArray.link(&jit);
 #if USE(JSVALUE64)
                 jit.load8(AssemblyHelpers::Address(value, JSCell::indexingTypeAndMiscOffset()), scratch1);
 #else
@@ -1193,6 +1202,7 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
                 jit.and32(AssemblyHelpers::TrustedImm32(IndexingModeMask), scratch1);
                 jit.move(AssemblyHelpers::TrustedImm32(1), scratch2);
                 jit.lshift32(scratch1, scratch2);
+                storeArrayModes.link(&jit);
                 jit.or32(scratch2, AssemblyHelpers::AbsoluteAddress(arrayProfile->addressOfArrayModes()));
 
                 if (isARM64()) {
index 2e166a6..75b0f05 100644 (file)
@@ -53,7 +53,7 @@ void RegisteredStructureSet::filterArrayModes(ArrayModes arrayModes)
 {
     genericFilter(
         [&] (RegisteredStructure structure) -> bool {
-            return arrayModes & arrayModeFromStructure(structure.get());
+            return arrayModes & arrayModesFromStructure(structure.get());
         });
 }
 
@@ -79,7 +79,7 @@ ArrayModes RegisteredStructureSet::arrayModesFromStructures() const
     ArrayModes result = 0;
     forEach(
         [&] (RegisteredStructure structure) {
-            mergeArrayModes(result, asArrayModes(structure->indexingMode()));
+            mergeArrayModes(result, arrayModesFromStructure(structure.get()));
         });
     return result;
 }
index f066d0b..8adffa0 100644 (file)
@@ -277,10 +277,20 @@ static void compileStub(
             if (ArrayProfile* arrayProfile = jit.baselineCodeBlockFor(codeOrigin)->getArrayProfile(codeOrigin.bytecodeIndex)) {
                 jit.load32(MacroAssembler::Address(GPRInfo::regT0, JSCell::structureIDOffset()), GPRInfo::regT1);
                 jit.store32(GPRInfo::regT1, arrayProfile->addressOfLastSeenStructureID());
+
+                jit.load8(MacroAssembler::Address(GPRInfo::regT0, JSCell::typeInfoTypeOffset()), GPRInfo::regT2);
+                jit.sub32(MacroAssembler::TrustedImm32(FirstTypedArrayType), GPRInfo::regT2);
+                auto notTypedArray = jit.branch32(MacroAssembler::AboveOrEqual, GPRInfo::regT2, MacroAssembler::TrustedImm32(NumberOfTypedArrayTypesExcludingDataView));
+                jit.move(MacroAssembler::TrustedImmPtr(typedArrayModes), GPRInfo::regT1);
+                jit.load32(MacroAssembler::BaseIndex(GPRInfo::regT1, GPRInfo::regT2, MacroAssembler::TimesFour), GPRInfo::regT2);
+                auto storeArrayModes = jit.jump();
+
+                notTypedArray.link(&jit);
                 jit.load8(MacroAssembler::Address(GPRInfo::regT0, JSCell::indexingTypeAndMiscOffset()), GPRInfo::regT1);
                 jit.and32(MacroAssembler::TrustedImm32(IndexingModeMask), GPRInfo::regT1);
                 jit.move(MacroAssembler::TrustedImm32(1), GPRInfo::regT2);
                 jit.lshift32(GPRInfo::regT1, GPRInfo::regT2);
+                storeArrayModes.link(&jit);
                 jit.or32(GPRInfo::regT2, MacroAssembler::AbsoluteAddress(arrayProfile->addressOfArrayModes()));
             }
         }
index 9ea8deb..f54bfe9 100644 (file)
@@ -364,13 +364,12 @@ inline void JIT::emitArrayProfileOutOfBoundsSpecialCase(ArrayProfile* arrayProfi
     store8(TrustedImm32(1), arrayProfile->addressOfOutOfBounds());
 }
 
-static inline bool arrayProfileSaw(ArrayModes arrayModes, IndexingType capability)
-{
-    return arrayModesInclude(arrayModes, capability);
-}
-
 inline JITArrayMode JIT::chooseArrayMode(ArrayProfile* profile)
 {
+    auto arrayProfileSaw = [] (ArrayModes arrayModes, IndexingType capability) {
+        return arrayModesIncludeIgnoringTypedArrays(arrayModes, capability);
+    };
+
     ConcurrentJSLocker locker(m_codeBlock->m_lock);
     profile->computeUpdatedPrediction(locker, m_codeBlock);
     ArrayModes arrayModes = profile->observedArrayModes(locker);
index 3af768b..ee9092b 100644 (file)
@@ -117,12 +117,12 @@ enum JSType : uint8_t {
     MaxJSType = 0b11111111,
 };
 
-static const uint32_t FirstTypedArrayType = Int8ArrayType;
-static const uint32_t LastTypedArrayType = DataViewType;
+static constexpr uint32_t FirstTypedArrayType = Int8ArrayType;
+static constexpr uint32_t LastTypedArrayType = DataViewType;
 
 // LastObjectType should be MaxJSType (not LastJSCObjectType) since embedders can add their extended object types after the enums listed in JSType.
-static const uint32_t FirstObjectType = ObjectType;
-static const uint32_t LastObjectType = MaxJSType;
+static constexpr uint32_t FirstObjectType = ObjectType;
+static constexpr uint32_t LastObjectType = MaxJSType;
 
 static constexpr uint32_t NumberOfTypedArrayTypes = LastTypedArrayType - FirstTypedArrayType + 1;
 static constexpr uint32_t NumberOfTypedArrayTypesExcludingDataView = NumberOfTypedArrayTypes - 1;
@@ -130,6 +130,11 @@ static constexpr uint32_t NumberOfTypedArrayTypesExcludingDataView = NumberOfTyp
 static_assert(sizeof(JSType) == sizeof(uint8_t), "sizeof(JSType) is one byte.");
 static_assert(LastJSCObjectType < 128, "The highest bit is reserved for embedder's extension.");
 
+inline constexpr bool isTypedArrayType(JSType type)
+{
+    return (static_cast<uint32_t>(type) - FirstTypedArrayType) < NumberOfTypedArrayTypesExcludingDataView;
+}
+
 } // namespace JSC
 
 namespace WTF {