diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
commit | 41386e9cb918eed93b3f13648cbef387e371e451 (patch) | |
tree | a97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/JavaScriptCore/dfg/DFGArrayMode.cpp | |
parent | e15dd966d523731101f70ccf768bba12435a0208 (diff) | |
download | WebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz |
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGArrayMode.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGArrayMode.cpp | 252 |
1 files changed, 65 insertions, 187 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp index 75fd6d144..ef9b1c494 100644 --- a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp +++ b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2013 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,10 +28,9 @@ #if ENABLE(DFG_JIT) -#include "ArrayPrototype.h" #include "DFGAbstractValue.h" #include "DFGGraph.h" -#include "JSCInlines.h" +#include "Operations.h" namespace JSC { namespace DFG { @@ -49,18 +48,18 @@ ArrayMode ArrayMode::fromObserved(const ConcurrentJITLocker& locker, ArrayProfil return ArrayMode(Array::Unprofiled); case asArrayModes(NonArray): 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); + return ArrayMode(Array::Undecided, nonArray, Array::OutOfBounds, Array::Convert); + return ArrayMode(Array::SelectUsingPredictions, nonArray); case asArrayModes(ArrayWithUndecided): if (action == Array::Write) - return ArrayMode(Array::SelectUsingArguments, Array::Array, Array::OutOfBounds, Array::Convert); - return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::AsIs).withProfile(locker, profile, makeSafe); + return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::Convert); + return ArrayMode(Array::Generic); case asArrayModes(NonArray) | asArrayModes(ArrayWithUndecided): 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); + return ArrayMode(Array::Undecided, Array::PossiblyArray, Array::OutOfBounds, Array::Convert); + return ArrayMode(Array::SelectUsingPredictions); case asArrayModes(NonArrayWithInt32): return ArrayMode(Array::Int32, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe); @@ -98,28 +97,10 @@ ArrayMode ArrayMode::fromObserved(const ConcurrentJITLocker& locker, ArrayProfil case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): 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(locker)) - return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe); + return ArrayMode(Array::SelectUsingPredictions); Array::Type type; Array::Class arrayClass; @@ -135,7 +116,7 @@ ArrayMode ArrayMode::fromObserved(const ConcurrentJITLocker& locker, ArrayProfil else if (shouldUseInt32(observed)) type = Array::Int32; else - type = Array::SelectUsingArguments; + type = Array::Undecided; if (hasSeenArray(observed) && hasSeenNonArray(observed)) arrayClass = Array::PossiblyArray; @@ -150,9 +131,7 @@ ArrayMode ArrayMode::fromObserved(const ConcurrentJITLocker& locker, ArrayProfil } } -ArrayMode ArrayMode::refine( - Graph& graph, Node* node, - SpeculatedType base, SpeculatedType index, SpeculatedType value) const +ArrayMode ArrayMode::refine(SpeculatedType base, SpeculatedType index, SpeculatedType value, NodeFlags flags) const { if (!base || !index) { // It can be that we had a legitimate arrayMode but no incoming predictions. That'll @@ -165,10 +144,6 @@ ArrayMode ArrayMode::refine( 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 @@ -180,7 +155,10 @@ ArrayMode ArrayMode::refine( // should just trust the array profile. switch (type()) { - case Array::SelectUsingArguments: + case Array::Unprofiled: + return ArrayMode(Array::ForceExit); + + case Array::Undecided: if (!value) return withType(Array::ForceExit); if (isInt32Speculation(value)) @@ -188,20 +166,7 @@ ArrayMode ArrayMode::refine( 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; @@ -210,93 +175,54 @@ ArrayMode ArrayMode::refine( return withTypeAndConversion(Array::Contiguous, Array::Convert); case Array::Double: + if (flags & NodeBytecodeUsesAsInt) + return withTypeAndConversion(Array::Contiguous, Array::RageConvert); if (!value || isFullNumberSpeculation(value)) return *this; return withTypeAndConversion(Array::Contiguous, Array::Convert); case Array::Contiguous: + if (doesConversion() && (flags & NodeBytecodeUsesAsInt)) + return withConversion(Array::RageConvert); return *this; - - 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: { + + case Array::SelectUsingPredictions: base &= ~SpecOther; if (isStringSpeculation(base)) 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); - } - - 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 (isArgumentsSpeculation(base)) + return withType(Array::Arguments); if (isInt8ArraySpeculation(base)) - return result.withType(Array::Int8Array); + return withType(Array::Int8Array); if (isInt16ArraySpeculation(base)) - return result.withType(Array::Int16Array); + return withType(Array::Int16Array); if (isInt32ArraySpeculation(base)) - return result.withType(Array::Int32Array); + return withType(Array::Int32Array); if (isUint8ArraySpeculation(base)) - return result.withType(Array::Uint8Array); + return withType(Array::Uint8Array); if (isUint8ClampedArraySpeculation(base)) - return result.withType(Array::Uint8ClampedArray); + return withType(Array::Uint8ClampedArray); if (isUint16ArraySpeculation(base)) - return result.withType(Array::Uint16Array); + return withType(Array::Uint16Array); if (isUint32ArraySpeculation(base)) - return result.withType(Array::Uint32Array); + return withType(Array::Uint32Array); if (isFloat32ArraySpeculation(base)) - return result.withType(Array::Float32Array); + return withType(Array::Float32Array); if (isFloat64ArraySpeculation(base)) - return result.withType(Array::Float64Array); + return withType(Array::Float64Array); - if (type() == Array::Unprofiled) - return ArrayMode(Array::ForceExit); return ArrayMode(Array::Generic); - } default: return *this; @@ -316,8 +242,6 @@ Structure* ArrayMode::originalArrayStructure(Graph& graph, const CodeOrigin& cod 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: @@ -341,57 +265,34 @@ Structure* ArrayMode::originalArrayStructure(Graph& graph, const CodeOrigin& cod Structure* ArrayMode::originalArrayStructure(Graph& graph, Node* node) const { - return originalArrayStructure(graph, node->origin.semantic); + return originalArrayStructure(graph, node->codeOrigin); } -bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& value, IndexingType shape) const +bool ArrayMode::alreadyChecked(Graph& graph, Node* node, AbstractValue& value, IndexingType shape) const { switch (arrayClass()) { - 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::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::Array: { + case Array::Array: if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape | IsArray))) return true; - 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; - } + return value.m_currentKnownStructure.hasSingleton() + && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape + && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); - default: { + default: if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape) | asArrayModes(shape | IsArray))) return true; - 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; - } } + return value.m_currentKnownStructure.hasSingleton() + && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape; + } } -bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& value) const +bool ArrayMode::alreadyChecked(Graph& graph, Node* node, AbstractValue& value) const { switch (type()) { case Array::Generic: @@ -414,50 +315,29 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& va 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; - 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; - } + return value.m_currentKnownStructure.hasSingleton() + && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()) + && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); - default: { + default: if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage))) return true; - 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); + return value.m_currentKnownStructure.hasSingleton() + && hasArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()); + } - case Array::ScopedArguments: - return speculationChecked(value.m_type, SpecScopedArguments); + case Array::Arguments: + return speculationChecked(value.m_type, SpecArguments); case Array::Int8Array: return speculationChecked(value.m_type, SpecInt8Array); @@ -488,7 +368,7 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& va case Array::SelectUsingPredictions: case Array::Unprofiled: - case Array::SelectUsingArguments: + case Array::Undecided: break; } @@ -501,8 +381,6 @@ 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: @@ -523,10 +401,8 @@ const char* arrayTypeToString(Array::Type type) return "ArrayStorage"; case Array::SlowPutArrayStorage: return "SlowPutArrayStorage"; - case Array::DirectArguments: - return "DirectArguments"; - case Array::ScopedArguments: - return "ScopedArguments"; + case Array::Arguments: + return "Arguments"; case Array::Int8Array: return "Int8Array"; case Array::Int16Array: @@ -595,6 +471,8 @@ const char* arrayConversionToString(Array::Conversion conversion) return "AsIs"; case Array::Convert: return "Convert"; + case Array::RageConvert: + return "RageConvert"; default: return "Unknown!"; } |