summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
commit32761a6cee1d0dee366b885b7b9c777e67885688 (patch)
treed6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/dfg/DFGArrayMode.cpp
parenta4e969f4965059196ca948db781e52f7cfebf19e (diff)
downloadWebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGArrayMode.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGArrayMode.cpp276
1 files changed, 66 insertions, 210 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
index 87ee3adff..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);
@@ -485,13 +365,10 @@ bool ArrayMode::alreadyChecked(Graph& graph, Node* node, const AbstractValue& va
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::SelectUsingArguments:
+ case Array::Undecided:
break;
}
@@ -504,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:
@@ -526,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:
@@ -548,8 +421,6 @@ 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
@@ -600,6 +471,8 @@ const char* arrayConversionToString(Array::Conversion conversion)
return "AsIs";
case Array::Convert:
return "Convert";
+ case Array::RageConvert:
+ return "RageConvert";
default:
return "Unknown!";
}
@@ -644,9 +517,6 @@ TypedArrayType toTypedArrayType(Array::Type type)
return TypeFloat32;
case Array::Float64Array:
return TypeFloat64;
- case Array::AnyTypedArray:
- RELEASE_ASSERT_NOT_REACHED();
- return NotTypedArray;
default:
return NotTypedArray;
}
@@ -678,19 +548,6 @@ Array::Type toArrayType(TypedArrayType type)
}
}
-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) {
@@ -706,7 +563,6 @@ bool permitsBoundsCheckLowering(Array::Type type)
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