diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/dfg/DFGArrayMode.cpp | |
parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
download | qtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz |
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f
Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGArrayMode.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGArrayMode.cpp | 474 |
1 files changed, 369 insertions, 105 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp index ede2ffc2b..87ee3adff 100644 --- a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp +++ b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,73 +28,98 @@ #if ENABLE(DFG_JIT) +#include "ArrayPrototype.h" #include "DFGAbstractValue.h" #include "DFGGraph.h" -#include "Operations.h" +#include "JSCInlines.h" namespace JSC { namespace DFG { -ArrayMode ArrayMode::fromObserved(ArrayProfile* profile, Array::Action action, bool makeSafe) +ArrayMode ArrayMode::fromObserved(const ConcurrentJITLocker& locker, ArrayProfile* profile, Array::Action action, bool makeSafe) { - ArrayModes observed = profile->observedArrayModes(); + Array::Class nonArray; + if (profile->usesOriginalArrayStructures(locker)) + nonArray = Array::OriginalNonArray; + else + nonArray = Array::NonArray; + + ArrayModes observed = profile->observedArrayModes(locker); switch (observed) { case 0: return ArrayMode(Array::Unprofiled); case asArrayModes(NonArray): - if (action == Array::Write && !profile->mayInterceptIndexedAccesses()) - return ArrayMode(Array::Undecided, Array::NonArray, Array::OutOfBounds, Array::Convert); - return ArrayMode(Array::SelectUsingPredictions); + if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker)) + return ArrayMode(Array::SelectUsingArguments, nonArray, Array::OutOfBounds, Array::Convert); + return ArrayMode(Array::SelectUsingPredictions, nonArray).withSpeculationFromProfile(locker, profile, makeSafe); case asArrayModes(ArrayWithUndecided): if (action == Array::Write) - return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::Convert); - return ArrayMode(Array::Generic); + return ArrayMode(Array::SelectUsingArguments, Array::Array, Array::OutOfBounds, Array::Convert); + return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArray) | asArrayModes(ArrayWithUndecided): - if (action == Array::Write && !profile->mayInterceptIndexedAccesses()) - return ArrayMode(Array::Undecided, Array::PossiblyArray, Array::OutOfBounds, Array::Convert); - return ArrayMode(Array::SelectUsingPredictions); + if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker)) + return ArrayMode(Array::SelectUsingArguments, Array::PossiblyArray, Array::OutOfBounds, Array::Convert); + return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithInt32): - return ArrayMode(Array::Int32, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::Int32, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(ArrayWithInt32): - return ArrayMode(Array::Int32, Array::Array, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::Int32, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithInt32) | asArrayModes(ArrayWithInt32): - return ArrayMode(Array::Int32, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::Int32, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithDouble): - return ArrayMode(Array::Double, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::Double, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(ArrayWithDouble): - return ArrayMode(Array::Double, Array::Array, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::Double, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithDouble) | asArrayModes(ArrayWithDouble): - return ArrayMode(Array::Double, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::Double, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithContiguous): - return ArrayMode(Array::Contiguous, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::Contiguous, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(ArrayWithContiguous): - return ArrayMode(Array::Contiguous, Array::Array, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::Contiguous, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous): - return ArrayMode(Array::Contiguous, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::Contiguous, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithArrayStorage): - return ArrayMode(Array::ArrayStorage, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::ArrayStorage, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithSlowPutArrayStorage): case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage): - return ArrayMode(Array::SlowPutArrayStorage, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::SlowPutArrayStorage, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(ArrayWithArrayStorage): - return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(ArrayWithSlowPutArrayStorage): case asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): - return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage): - return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe); case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): - return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); + return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe); + case Int8ArrayMode: + return ArrayMode(Array::Int8Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); + case Int16ArrayMode: + return ArrayMode(Array::Int16Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); + case Int32ArrayMode: + return ArrayMode(Array::Int32Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); + case Uint8ArrayMode: + return ArrayMode(Array::Uint8Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); + case Uint8ClampedArrayMode: + return ArrayMode(Array::Uint8ClampedArray, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); + case Uint16ArrayMode: + return ArrayMode(Array::Uint16Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); + case Uint32ArrayMode: + return ArrayMode(Array::Uint32Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); + case Float32ArrayMode: + return ArrayMode(Array::Float32Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); + case Float64ArrayMode: + return ArrayMode(Array::Float64Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); default: - if ((observed & asArrayModes(NonArray)) && profile->mayInterceptIndexedAccesses()) - return ArrayMode(Array::SelectUsingPredictions); + if ((observed & asArrayModes(NonArray)) && profile->mayInterceptIndexedAccesses(locker)) + return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe); Array::Type type; Array::Class arrayClass; @@ -110,22 +135,24 @@ ArrayMode ArrayMode::fromObserved(ArrayProfile* profile, Array::Action action, b else if (shouldUseInt32(observed)) type = Array::Int32; else - type = Array::Undecided; + type = Array::SelectUsingArguments; if (hasSeenArray(observed) && hasSeenNonArray(observed)) arrayClass = Array::PossiblyArray; else if (hasSeenArray(observed)) arrayClass = Array::Array; else if (hasSeenNonArray(observed)) - arrayClass = Array::NonArray; + arrayClass = nonArray; else arrayClass = Array::PossiblyArray; - return ArrayMode(type, arrayClass, Array::Convert).withProfile(profile, makeSafe); + return ArrayMode(type, arrayClass, Array::Convert).withProfile(locker, profile, makeSafe); } } -ArrayMode ArrayMode::refine(SpeculatedType base, SpeculatedType index, SpeculatedType value, NodeFlags flags) const +ArrayMode ArrayMode::refine( + Graph& graph, Node* node, + SpeculatedType base, SpeculatedType index, SpeculatedType value) const { if (!base || !index) { // It can be that we had a legitimate arrayMode but no incoming predictions. That'll @@ -138,6 +165,10 @@ ArrayMode ArrayMode::refine(SpeculatedType base, SpeculatedType index, Speculate if (!isInt32Speculation(index)) return ArrayMode(Array::Generic); + // If we had exited because of an exotic object behavior, then don't try to specialize. + if (graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) + return ArrayMode(Array::Generic); + // Note: our profiling currently doesn't give us good information in case we have // an unlikely control flow path that sets the base to a non-cell value. Value // profiling and prediction propagation will probably tell us that the value is @@ -149,74 +180,123 @@ ArrayMode ArrayMode::refine(SpeculatedType base, SpeculatedType index, Speculate // should just trust the array profile. switch (type()) { - case Array::Unprofiled: - return ArrayMode(Array::ForceExit); - - case Array::Undecided: + case Array::SelectUsingArguments: if (!value) return withType(Array::ForceExit); if (isInt32Speculation(value)) return withTypeAndConversion(Array::Int32, Array::Convert); - if (isNumberSpeculation(value)) + if (isFullNumberSpeculation(value)) return withTypeAndConversion(Array::Double, Array::Convert); return withTypeAndConversion(Array::Contiguous, Array::Convert); - + case Array::Undecided: { + // If we have an OriginalArray and the JSArray prototype chain is sane, + // any indexed access always return undefined. We have a fast path for that. + JSGlobalObject* globalObject = graph.globalObjectFor(node->origin.semantic); + if (node->op() == GetByVal + && arrayClass() == Array::OriginalArray + && globalObject->arrayPrototypeChainIsSane() + && !graph.hasExitSite(node->origin.semantic, OutOfBounds)) { + graph.watchpoints().addLazily(globalObject->arrayPrototype()->structure()->transitionWatchpointSet()); + graph.watchpoints().addLazily(globalObject->objectPrototype()->structure()->transitionWatchpointSet()); + return withSpeculation(Array::SaneChain); + } + return ArrayMode(Array::Generic); + } case Array::Int32: if (!value || isInt32Speculation(value)) return *this; - if (isNumberSpeculation(value)) + if (isFullNumberSpeculation(value)) return withTypeAndConversion(Array::Double, Array::Convert); return withTypeAndConversion(Array::Contiguous, Array::Convert); case Array::Double: - if (flags & NodeUsedAsInt) - return withTypeAndConversion(Array::Contiguous, Array::RageConvert); - if (!value || isNumberSpeculation(value)) + if (!value || isFullNumberSpeculation(value)) return *this; return withTypeAndConversion(Array::Contiguous, Array::Convert); case Array::Contiguous: - if (doesConversion() && (flags & NodeUsedAsInt)) - return withConversion(Array::RageConvert); return *this; - - case Array::SelectUsingPredictions: + + case Array::Int8Array: + case Array::Int16Array: + case Array::Int32Array: + case Array::Uint8Array: + case Array::Uint8ClampedArray: + case Array::Uint16Array: + case Array::Uint32Array: + case Array::Float32Array: + case Array::Float64Array: + switch (node->op()) { + case PutByVal: + if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds()) + return withSpeculation(Array::OutOfBounds); + return withSpeculation(Array::InBounds); + default: + return withSpeculation(Array::InBounds); + } + return *this; + case Array::Unprofiled: + case Array::SelectUsingPredictions: { base &= ~SpecOther; if (isStringSpeculation(base)) - return ArrayMode(Array::String); + return withType(Array::String); + + if (isDirectArgumentsSpeculation(base) || isScopedArgumentsSpeculation(base)) { + // Handle out-of-bounds accesses as generic accesses. + if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds()) + return ArrayMode(Array::Generic); + + if (isDirectArgumentsSpeculation(base)) + return withType(Array::DirectArguments); + return withType(Array::ScopedArguments); + } - if (isArgumentsSpeculation(base)) - return ArrayMode(Array::Arguments); + ArrayMode result; + switch (node->op()) { + case PutByVal: + if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds()) + result = withSpeculation(Array::OutOfBounds); + else + result = withSpeculation(Array::InBounds); + break; + + default: + result = withSpeculation(Array::InBounds); + break; + } if (isInt8ArraySpeculation(base)) - return ArrayMode(Array::Int8Array); + return result.withType(Array::Int8Array); if (isInt16ArraySpeculation(base)) - return ArrayMode(Array::Int16Array); + return result.withType(Array::Int16Array); if (isInt32ArraySpeculation(base)) - return ArrayMode(Array::Int32Array); + return result.withType(Array::Int32Array); if (isUint8ArraySpeculation(base)) - return ArrayMode(Array::Uint8Array); + return result.withType(Array::Uint8Array); if (isUint8ClampedArraySpeculation(base)) - return ArrayMode(Array::Uint8ClampedArray); + return result.withType(Array::Uint8ClampedArray); if (isUint16ArraySpeculation(base)) - return ArrayMode(Array::Uint16Array); + return result.withType(Array::Uint16Array); if (isUint32ArraySpeculation(base)) - return ArrayMode(Array::Uint32Array); + return result.withType(Array::Uint32Array); if (isFloat32ArraySpeculation(base)) - return ArrayMode(Array::Float32Array); + return result.withType(Array::Float32Array); if (isFloat64ArraySpeculation(base)) - return ArrayMode(Array::Float64Array); + return result.withType(Array::Float64Array); + if (type() == Array::Unprofiled) + return ArrayMode(Array::ForceExit); return ArrayMode(Array::Generic); + } default: return *this; @@ -225,56 +305,93 @@ ArrayMode ArrayMode::refine(SpeculatedType base, SpeculatedType index, Speculate Structure* ArrayMode::originalArrayStructure(Graph& graph, const CodeOrigin& codeOrigin) const { - if (!isJSArrayWithOriginalStructure()) - return 0; - JSGlobalObject* globalObject = graph.globalObjectFor(codeOrigin); - switch (type()) { - case Array::Int32: - return globalObject->originalArrayStructureForIndexingType(ArrayWithInt32); - case Array::Double: - return globalObject->originalArrayStructureForIndexingType(ArrayWithDouble); - case Array::Contiguous: - return globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous); - case Array::ArrayStorage: - return globalObject->originalArrayStructureForIndexingType(ArrayWithArrayStorage); + switch (arrayClass()) { + case Array::OriginalArray: { + switch (type()) { + case Array::Int32: + return globalObject->originalArrayStructureForIndexingType(ArrayWithInt32); + case Array::Double: + return globalObject->originalArrayStructureForIndexingType(ArrayWithDouble); + case Array::Contiguous: + return globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous); + case Array::Undecided: + return globalObject->originalArrayStructureForIndexingType(ArrayWithUndecided); + case Array::ArrayStorage: + return globalObject->originalArrayStructureForIndexingType(ArrayWithArrayStorage); + default: + CRASH(); + return 0; + } + } + + case Array::OriginalNonArray: { + TypedArrayType type = typedArrayType(); + if (type == NotTypedArray) + return 0; + + return globalObject->typedArrayStructure(type); + } + default: - CRASH(); return 0; } } Structure* ArrayMode::originalArrayStructure(Graph& graph, Node* node) const { - return originalArrayStructure(graph, node->codeOrigin); + return originalArrayStructure(graph, node->origin.semantic); } -bool ArrayMode::alreadyChecked(Graph& graph, Node* node, AbstractValue& value, IndexingType shape) const +bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& value, IndexingType shape) const { switch (arrayClass()) { - case Array::OriginalArray: - return value.m_currentKnownStructure.hasSingleton() - && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape - && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray) - && graph.globalObjectFor(node->codeOrigin)->isOriginalArrayStructure(value.m_currentKnownStructure.singleton()); + case Array::OriginalArray: { + if (value.m_structure.isTop()) + return false; + for (unsigned i = value.m_structure.size(); i--;) { + Structure* structure = value.m_structure[i]; + if ((structure->indexingType() & IndexingShapeMask) != shape) + return false; + if (!(structure->indexingType() & IsArray)) + return false; + if (!graph.globalObjectFor(node->origin.semantic)->isOriginalArrayStructure(structure)) + return false; + } + return true; + } - case Array::Array: + case Array::Array: { if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape | IsArray))) return true; - return value.m_currentKnownStructure.hasSingleton() - && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape - && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); + if (value.m_structure.isTop()) + return false; + for (unsigned i = value.m_structure.size(); i--;) { + Structure* structure = value.m_structure[i]; + if ((structure->indexingType() & IndexingShapeMask) != shape) + return false; + if (!(structure->indexingType() & IsArray)) + return false; + } + return true; + } - default: + default: { if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape) | asArrayModes(shape | IsArray))) return true; - return value.m_currentKnownStructure.hasSingleton() - && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape; - } + if (value.m_structure.isTop()) + return false; + for (unsigned i = value.m_structure.size(); i--;) { + Structure* structure = value.m_structure[i]; + if ((structure->indexingType() & IndexingShapeMask) != shape) + return false; + } + return true; + } } } -bool ArrayMode::alreadyChecked(Graph& graph, Node* node, AbstractValue& value) const +bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& value) const { switch (type()) { case Array::Generic: @@ -297,29 +414,50 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, AbstractValue& value) c case Array::ArrayStorage: return alreadyChecked(graph, node, value, ArrayStorageShape); + + case Array::Undecided: + return alreadyChecked(graph, node, value, UndecidedShape); case Array::SlowPutArrayStorage: switch (arrayClass()) { - case Array::OriginalArray: + case Array::OriginalArray: { CRASH(); return false; + } - case Array::Array: + case Array::Array: { 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 (value.m_structure.isTop()) + return false; + for (unsigned i = value.m_structure.size(); i--;) { + Structure* structure = value.m_structure[i]; + if (!hasAnyArrayStorage(structure->indexingType())) + return false; + if (!(structure->indexingType() & IsArray)) + return false; + } + return true; + } - default: + default: { 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()); - } + if (value.m_structure.isTop()) + return false; + for (unsigned i = value.m_structure.size(); i--;) { + Structure* structure = value.m_structure[i]; + if (!hasAnyArrayStorage(structure->indexingType())) + return false; + } + return true; + } } + + case Array::DirectArguments: + return speculationChecked(value.m_type, SpecDirectArguments); - case Array::Arguments: - return speculationChecked(value.m_type, SpecArguments); + case Array::ScopedArguments: + return speculationChecked(value.m_type, SpecScopedArguments); case Array::Int8Array: return speculationChecked(value.m_type, SpecInt8Array); @@ -347,10 +485,13 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, AbstractValue& value) c case Array::Float64Array: return speculationChecked(value.m_type, SpecFloat64Array); - + + case Array::AnyTypedArray: + return speculationChecked(value.m_type, SpecTypedArrayView); + case Array::SelectUsingPredictions: case Array::Unprofiled: - case Array::Undecided: + case Array::SelectUsingArguments: break; } @@ -363,6 +504,8 @@ const char* arrayTypeToString(Array::Type type) switch (type) { case Array::SelectUsingPredictions: return "SelectUsingPredictions"; + case Array::SelectUsingArguments: + return "SelectUsingArguments"; case Array::Unprofiled: return "Unprofiled"; case Array::Generic: @@ -383,8 +526,10 @@ const char* arrayTypeToString(Array::Type type) return "ArrayStorage"; case Array::SlowPutArrayStorage: return "SlowPutArrayStorage"; - case Array::Arguments: - return "Arguments"; + case Array::DirectArguments: + return "DirectArguments"; + case Array::ScopedArguments: + return "ScopedArguments"; case Array::Int8Array: return "Int8Array"; case Array::Int16Array: @@ -403,6 +548,8 @@ const char* arrayTypeToString(Array::Type type) return "Float32Array"; case Array::Float64Array: return "Float64Array"; + case Array::AnyTypedArray: + return "AnyTypedArray"; default: // Better to return something then it is to crash. Remember, this method // is being called from our main diagnostic tool, the IR dumper. It's like @@ -421,6 +568,8 @@ const char* arrayClassToString(Array::Class arrayClass) return "OriginalArray"; case Array::NonArray: return "NonArray"; + case Array::OriginalNonArray: + return "OriginalNonArray"; case Array::PossiblyArray: return "PossiblyArray"; default: @@ -451,13 +600,128 @@ const char* arrayConversionToString(Array::Conversion conversion) return "AsIs"; case Array::Convert: return "Convert"; - case Array::RageConvert: - return "RageConvert"; default: return "Unknown!"; } } +IndexingType toIndexingShape(Array::Type type) +{ + switch (type) { + case Array::Int32: + return Int32Shape; + case Array::Double: + return DoubleShape; + case Array::Contiguous: + return ContiguousShape; + case Array::ArrayStorage: + return ArrayStorageShape; + case Array::SlowPutArrayStorage: + return SlowPutArrayStorageShape; + default: + return NoIndexingShape; + } +} + +TypedArrayType toTypedArrayType(Array::Type type) +{ + switch (type) { + case Array::Int8Array: + return TypeInt8; + case Array::Int16Array: + return TypeInt16; + case Array::Int32Array: + return TypeInt32; + case Array::Uint8Array: + return TypeUint8; + case Array::Uint8ClampedArray: + return TypeUint8Clamped; + case Array::Uint16Array: + return TypeUint16; + case Array::Uint32Array: + return TypeUint32; + case Array::Float32Array: + return TypeFloat32; + case Array::Float64Array: + return TypeFloat64; + case Array::AnyTypedArray: + RELEASE_ASSERT_NOT_REACHED(); + return NotTypedArray; + default: + return NotTypedArray; + } +} + +Array::Type toArrayType(TypedArrayType type) +{ + switch (type) { + case TypeInt8: + return Array::Int8Array; + case TypeInt16: + return Array::Int16Array; + case TypeInt32: + return Array::Int32Array; + case TypeUint8: + return Array::Uint8Array; + case TypeUint8Clamped: + return Array::Uint8ClampedArray; + case TypeUint16: + return Array::Uint16Array; + case TypeUint32: + return Array::Uint32Array; + case TypeFloat32: + return Array::Float32Array; + case TypeFloat64: + return Array::Float64Array; + default: + return Array::Generic; + } +} + +Array::Type refineTypedArrayType(Array::Type oldType, TypedArrayType newType) +{ + if (oldType == Array::Generic) + return oldType; + Array::Type newArrayType = toArrayType(newType); + if (newArrayType == Array::Generic) + return newArrayType; + + if (oldType != newArrayType) + return Array::AnyTypedArray; + return oldType; +} + +bool permitsBoundsCheckLowering(Array::Type type) +{ + switch (type) { + case Array::Int32: + case Array::Double: + case Array::Contiguous: + case Array::Int8Array: + case Array::Int16Array: + case Array::Int32Array: + case Array::Uint8Array: + case Array::Uint8ClampedArray: + case Array::Uint16Array: + case Array::Uint32Array: + case Array::Float32Array: + case Array::Float64Array: + case Array::AnyTypedArray: + return true; + default: + // These don't allow for bounds check lowering either because the bounds + // check involves something other than GetArrayLength (like ArrayStorage), + // or because the bounds check isn't a speculation (like String, sort of), + // or because the type implies an impure access. + return false; + } +} + +bool ArrayMode::permitsBoundsCheckLowering() const +{ + return DFG::permitsBoundsCheckLowering(type()) && isInBounds(); +} + void ArrayMode::dump(PrintStream& out) const { out.print(type(), arrayClass(), speculation(), conversion()); |