diff options
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGArrayMode.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGArrayMode.cpp | 273 |
1 files changed, 128 insertions, 145 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp index a3aafde01..699902a16 100644 --- a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp +++ b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp @@ -32,126 +32,126 @@ namespace JSC { namespace DFG { -Array::Mode fromObserved(ArrayProfile* profile, Array::Action action, bool makeSafe) +ArrayMode ArrayMode::fromObserved(ArrayProfile* profile, Array::Action action, bool makeSafe) { switch (profile->observedArrayModes()) { case 0: - return Array::Unprofiled; + return ArrayMode(Array::Unprofiled); case asArrayModes(NonArray): if (action == Array::Write && !profile->mayInterceptIndexedAccesses()) - return Array::ToContiguous; // FIXME: we don't know whether to go to contiguous or array storage. We're making a static guess here. In future we should use exit profiling for this. - return Array::SelectUsingPredictions; + return ArrayMode(Array::Contiguous, Array::NonArray, Array::OutOfBounds, Array::Convert); // FIXME: we don't know whether to go to contiguous or array storage. We're making a static guess here. In future we should use exit profiling for this. + return ArrayMode(Array::SelectUsingPredictions); case asArrayModes(NonArrayWithContiguous): - return makeSafe ? Array::ContiguousOutOfBounds : (profile->mayStoreToHole() ? Array::ContiguousToTail : Array::Contiguous); + return ArrayMode(Array::Contiguous, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(ArrayWithContiguous): - return makeSafe ? Array::ArrayWithContiguousOutOfBounds : (profile->mayStoreToHole() ? Array::ArrayWithContiguousToTail : Array::ArrayWithContiguous); + return ArrayMode(Array::Contiguous, Array::Array, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous): - return makeSafe ? Array::PossiblyArrayWithContiguousOutOfBounds : (profile->mayStoreToHole() ? Array::PossiblyArrayWithContiguousToTail : Array::PossiblyArrayWithContiguous); + return ArrayMode(Array::Contiguous, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithArrayStorage): - return makeSafe ? Array::ArrayStorageOutOfBounds : (profile->mayStoreToHole() ? Array::ArrayStorageToHole : Array::ArrayStorage); + return ArrayMode(Array::ArrayStorage, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithSlowPutArrayStorage): case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage): - return Array::SlowPutArrayStorage; + return ArrayMode(Array::SlowPutArrayStorage, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(ArrayWithArrayStorage): - return makeSafe ? Array::ArrayWithArrayStorageOutOfBounds : (profile->mayStoreToHole() ? Array::ArrayWithArrayStorageToHole : Array::ArrayWithArrayStorage); + return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(ArrayWithSlowPutArrayStorage): case asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): - return Array::ArrayWithSlowPutArrayStorage; + return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage): - return makeSafe ? Array::PossiblyArrayWithArrayStorageOutOfBounds : (profile->mayStoreToHole() ? Array::PossiblyArrayWithArrayStorageToHole : Array::PossiblyArrayWithArrayStorage); + return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): - return Array::PossiblyArrayWithSlowPutArrayStorage; + return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage): - return Array::ToArrayStorage; + return ArrayMode(Array::ArrayStorage, Array::NonArray, Array::Convert).withProfile(profile, makeSafe); case asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage): - return Array::ArrayToArrayStorage; + return ArrayMode(Array::ArrayStorage, Array::Array, Array::Convert).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage): - return Array::PossiblyArrayToArrayStorage; + return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::Convert).withProfile(profile, makeSafe); case asArrayModes(NonArray) | asArrayModes(NonArrayWithContiguous): if (action == Array::Write && !profile->mayInterceptIndexedAccesses()) - return Array::ToContiguous; - return Array::SelectUsingPredictions; + return ArrayMode(Array::Contiguous, Array::NonArray, Array::OutOfBounds, Array::Convert); + return ArrayMode(Array::SelectUsingPredictions); case asArrayModes(NonArray) | asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage): case asArrayModes(NonArray) | asArrayModes(NonArrayWithArrayStorage): if (action == Array::Write && !profile->mayInterceptIndexedAccesses()) - return Array::ToArrayStorage; - return Array::SelectUsingPredictions; + return ArrayMode(Array::ArrayStorage, Array::NonArray, Array::OutOfBounds, Array::Convert); + return ArrayMode(Array::SelectUsingPredictions); case asArrayModes(NonArray) | asArrayModes(NonArrayWithSlowPutArrayStorage): case asArrayModes(NonArray) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage): if (action == Array::Write && !profile->mayInterceptIndexedAccesses()) - return Array::ToSlowPutArrayStorage; - return Array::SelectUsingPredictions; + return ArrayMode(Array::SlowPutArrayStorage, Array::NonArray, Array::OutOfBounds, Array::Convert); + return ArrayMode(Array::SelectUsingPredictions); default: // We know that this is possibly a kind of array for which, though there is no // useful data in the array profile, we may be able to extract useful data from // the value profiles of the inputs. Hence, we leave it as undecided, and let // the predictions propagator decide later. - return Array::SelectUsingPredictions; + return ArrayMode(Array::SelectUsingPredictions); } } -Array::Mode refineArrayMode(Array::Mode arrayMode, SpeculatedType base, SpeculatedType index) +ArrayMode ArrayMode::refine(SpeculatedType base, SpeculatedType index) const { if (!base || !index) { // It can be that we had a legitimate arrayMode but no incoming predictions. That'll // happen if we inlined code based on, say, a global variable watchpoint, but later // realized that the callsite could not have possibly executed. It may be worthwhile // to fix that, but for now I'm leaving it as-is. - return Array::ForceExit; + return ArrayMode(Array::ForceExit); } if (!isInt32Speculation(index) || !isCellSpeculation(base)) - return Array::Generic; + return ArrayMode(Array::Generic); - if (arrayMode == Array::Unprofiled) { + if (type() == Array::Unprofiled) { // If the indexing type wasn't recorded in the array profile but the values are // base=cell property=int, then we know that this access didn't execute. - return Array::ForceExit; + return ArrayMode(Array::ForceExit); } - if (arrayMode != Array::SelectUsingPredictions) - return arrayMode; + if (type() != Array::SelectUsingPredictions) + return *this; if (isStringSpeculation(base)) - return Array::String; + return ArrayMode(Array::String); if (isArgumentsSpeculation(base)) - return Array::Arguments; + return ArrayMode(Array::Arguments); if (isInt8ArraySpeculation(base)) - return Array::Int8Array; + return ArrayMode(Array::Int8Array); if (isInt16ArraySpeculation(base)) - return Array::Int16Array; + return ArrayMode(Array::Int16Array); if (isInt32ArraySpeculation(base)) - return Array::Int32Array; + return ArrayMode(Array::Int32Array); if (isUint8ArraySpeculation(base)) - return Array::Uint8Array; + return ArrayMode(Array::Uint8Array); if (isUint8ClampedArraySpeculation(base)) - return Array::Uint8ClampedArray; + return ArrayMode(Array::Uint8ClampedArray); if (isUint16ArraySpeculation(base)) - return Array::Uint16Array; + return ArrayMode(Array::Uint16Array); if (isUint32ArraySpeculation(base)) - return Array::Uint32Array; + return ArrayMode(Array::Uint32Array); if (isFloat32ArraySpeculation(base)) - return Array::Float32Array; + return ArrayMode(Array::Float32Array); if (isFloat64ArraySpeculation(base)) - return Array::Float64Array; + return ArrayMode(Array::Float64Array); - return Array::Generic; + return ArrayMode(Array::Generic); } -bool modeAlreadyChecked(AbstractValue& value, Array::Mode arrayMode) +bool ArrayMode::alreadyChecked(AbstractValue& value) const { - switch (arrayMode) { + switch (type()) { case Array::Generic: return true; @@ -159,109 +159,89 @@ bool modeAlreadyChecked(AbstractValue& value, Array::Mode arrayMode) return false; case Array::String: - return isStringSpeculation(value.m_type); + return speculationChecked(value.m_type, SpecString); case Array::Contiguous: - case Array::ContiguousToTail: - case Array::ContiguousOutOfBounds: - case Array::PossiblyArrayWithContiguous: - case Array::PossiblyArrayWithContiguousToTail: - case Array::PossiblyArrayWithContiguousOutOfBounds: - case Array::ToContiguous: + if (isJSArray()) { + if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithContiguous))) + return true; + return value.m_currentKnownStructure.hasSingleton() + && hasContiguous(value.m_currentKnownStructure.singleton()->indexingType()) + && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); + } if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous))) return true; return value.m_currentKnownStructure.hasSingleton() && hasContiguous(value.m_currentKnownStructure.singleton()->indexingType()); - case Array::ArrayWithContiguous: - case Array::ArrayWithContiguousToTail: - case Array::ArrayWithContiguousOutOfBounds: - if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithContiguous))) - return true; - return value.m_currentKnownStructure.hasSingleton() - && hasContiguous(value.m_currentKnownStructure.singleton()->indexingType()) - && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); - case Array::ArrayStorage: - case Array::ArrayStorageToHole: - case Array::ArrayStorageOutOfBounds: - case Array::PossiblyArrayWithArrayStorage: - case Array::PossiblyArrayWithArrayStorageToHole: - case Array::PossiblyArrayWithArrayStorageOutOfBounds: - case Array::ToArrayStorage: - case Array::PossiblyArrayToArrayStorage: + if (isJSArray()) { + if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage))) + return true; + return value.m_currentKnownStructure.hasSingleton() + && hasFastArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()) + && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); + } if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage))) return true; return value.m_currentKnownStructure.hasSingleton() && hasFastArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()); case Array::SlowPutArrayStorage: - case Array::PossiblyArrayWithSlowPutArrayStorage: - case Array::ToSlowPutArrayStorage: + if (isJSArray()) { + if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage))) + return true; + return value.m_currentKnownStructure.hasSingleton() + && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()) + && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); + } if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage))) return true; return value.m_currentKnownStructure.hasSingleton() && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()); - case Array::ArrayWithArrayStorage: - case Array::ArrayWithArrayStorageToHole: - case Array::ArrayWithArrayStorageOutOfBounds: - case Array::ArrayToArrayStorage: - if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage))) - return true; - return value.m_currentKnownStructure.hasSingleton() - && hasFastArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()) - && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); - - case Array::ArrayWithSlowPutArrayStorage: - if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage))) - return true; - return value.m_currentKnownStructure.hasSingleton() - && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()) - && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); - case Array::Arguments: - return isArgumentsSpeculation(value.m_type); + return speculationChecked(value.m_type, SpecArguments); case Array::Int8Array: - return isInt8ArraySpeculation(value.m_type); + return speculationChecked(value.m_type, SpecInt8Array); case Array::Int16Array: - return isInt16ArraySpeculation(value.m_type); + return speculationChecked(value.m_type, SpecInt16Array); case Array::Int32Array: - return isInt32ArraySpeculation(value.m_type); + return speculationChecked(value.m_type, SpecInt32Array); case Array::Uint8Array: - return isUint8ArraySpeculation(value.m_type); + return speculationChecked(value.m_type, SpecUint8Array); case Array::Uint8ClampedArray: - return isUint8ClampedArraySpeculation(value.m_type); + return speculationChecked(value.m_type, SpecUint8ClampedArray); case Array::Uint16Array: - return isUint16ArraySpeculation(value.m_type); + return speculationChecked(value.m_type, SpecUint16Array); case Array::Uint32Array: - return isUint32ArraySpeculation(value.m_type); + return speculationChecked(value.m_type, SpecUint32Array); case Array::Float32Array: - return isFloat32ArraySpeculation(value.m_type); + return speculationChecked(value.m_type, SpecFloat32Array); case Array::Float64Array: - return isFloat64ArraySpeculation(value.m_type); + return speculationChecked(value.m_type, SpecFloat64Array); case Array::SelectUsingPredictions: case Array::Unprofiled: break; } - ASSERT_NOT_REACHED(); + CRASH(); return false; } -const char* modeToString(Array::Mode mode) +const char* arrayTypeToString(Array::Type type) { - switch (mode) { + switch (type) { case Array::SelectUsingPredictions: return "SelectUsingPredictions"; case Array::Unprofiled: @@ -274,56 +254,10 @@ const char* modeToString(Array::Mode mode) return "String"; case Array::Contiguous: return "Contiguous"; - case Array::ContiguousToTail: - return "ContiguousToTail"; - case Array::ContiguousOutOfBounds: - return "ContiguousOutOfBounds"; - case Array::ArrayWithContiguous: - return "ArrayWithContiguous"; - case Array::ArrayWithContiguousToTail: - return "ArrayWithContiguousToTail"; - case Array::ArrayWithContiguousOutOfBounds: - return "ArrayWithContiguousOutOfBounds"; - case Array::PossiblyArrayWithContiguous: - return "PossiblyArrayWithContiguous"; - case Array::PossiblyArrayWithContiguousToTail: - return "PossiblyArrayWithContiguousToTail"; - case Array::PossiblyArrayWithContiguousOutOfBounds: - return "PossiblyArrayWithContiguousOutOfBounds"; case Array::ArrayStorage: return "ArrayStorage"; - case Array::ArrayStorageToHole: - return "ArrayStorageToHole"; case Array::SlowPutArrayStorage: return "SlowPutArrayStorage"; - case Array::ArrayStorageOutOfBounds: - return "ArrayStorageOutOfBounds"; - case Array::ArrayWithArrayStorage: - return "ArrayWithArrayStorage"; - case Array::ArrayWithArrayStorageToHole: - return "ArrayWithArrayStorageToHole"; - case Array::ArrayWithSlowPutArrayStorage: - return "ArrayWithSlowPutArrayStorage"; - case Array::ArrayWithArrayStorageOutOfBounds: - return "ArrayWithArrayStorageOutOfBounds"; - case Array::PossiblyArrayWithArrayStorage: - return "PossiblyArrayWithArrayStorage"; - case Array::PossiblyArrayWithArrayStorageToHole: - return "PossiblyArrayWithArrayStorageToHole"; - case Array::PossiblyArrayWithSlowPutArrayStorage: - return "PossiblyArrayWithSlowPutArrayStorage"; - case Array::PossiblyArrayWithArrayStorageOutOfBounds: - return "PossiblyArrayWithArrayStorageOutOfBounds"; - case Array::ToContiguous: - return "ToContiguous"; - case Array::ToArrayStorage: - return "ToArrayStorage"; - case Array::ToSlowPutArrayStorage: - return "ToSlowPutArrayStorage"; - case Array::ArrayToArrayStorage: - return "ArrayToArrayStorage"; - case Array::PossiblyArrayToArrayStorage: - return "PossiblyArrayToArrayStorage"; case Array::Arguments: return "Arguments"; case Array::Int8Array: @@ -353,6 +287,55 @@ const char* modeToString(Array::Mode mode) } } +const char* arrayClassToString(Array::Class arrayClass) +{ + switch (arrayClass) { + case Array::Array: + return "Array"; + case Array::OriginalArray: + return "OriginalArray"; + case Array::NonArray: + return "NonArray"; + case Array::PossiblyArray: + return "PossiblyArray"; + default: + return "Unknown!"; + } +} + +const char* arraySpeculationToString(Array::Speculation speculation) +{ + switch (speculation) { + case Array::InBounds: + return "InBounds"; + case Array::ToHole: + return "ToHole"; + case Array::OutOfBounds: + return "OutOfBounds"; + default: + return "Unknown!"; + } +} + +const char* arrayConversionToString(Array::Conversion conversion) +{ + switch (conversion) { + case Array::AsIs: + return "AsIs"; + case Array::Convert: + return "Convert"; + default: + return "Unknown!"; + } +} + +const char* ArrayMode::toString() const +{ + static char buffer[256]; + snprintf(buffer, sizeof(buffer), "%s%s%s%s", arrayTypeToString(type()), arrayClassToString(arrayClass()), arraySpeculationToString(speculation()), arrayConversionToString(conversion())); + return buffer; +} + } } // namespace JSC::DFG #endif // ENABLE(DFG_JIT) |