Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (134150 => 134151)
--- trunk/Source/_javascript_Core/ChangeLog 2012-11-10 05:16:00 UTC (rev 134150)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-11-10 05:54:11 UTC (rev 134151)
@@ -1,5 +1,47 @@
2012-11-09 Filip Pizlo <fpi...@apple.com>
+ If the DFG ArrayMode says that an access is on an OriginalArray, then the checks should always enforce this
+ https://bugs.webkit.org/show_bug.cgi?id=101720
+
+ Reviewed by Mark Hahnenberg.
+
+ Previously, "original" arrays was just a hint that we could find the structure
+ of the array if we needed to even if the array profile didn't have it due to
+ polymorphism. Now, "original" arrays are a property that is actually checked:
+ if an array access has ArrayMode::arrayClass() == Array::OriginalArray, then we
+ can be sure that the code performing the access is dealing with not just a
+ JSArray, but a JSArray that has no named properties, no indexed accessors, and
+ the ArrayPrototype as its prototype. This will be useful for optimizations that
+ are being done as part of https://bugs.webkit.org/show_bug.cgi?id=101720.
+
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGArrayMode.cpp:
+ (JSC::DFG::ArrayMode::originalArrayStructure):
+ (DFG):
+ (JSC::DFG::ArrayMode::alreadyChecked):
+ * dfg/DFGArrayMode.h:
+ (JSC):
+ (DFG):
+ (JSC::DFG::ArrayMode::withProfile):
+ (ArrayMode):
+ (JSC::DFG::ArrayMode::benefitsFromOriginalArray):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::foldConstants):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::checkArray):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::jumpSlowForUnwantedArrayMode):
+ (JSC::DFG::SpeculativeJIT::checkArray):
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnString):
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray):
+ (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnArguments):
+ (JSC::DFG::SpeculativeJIT::compileGetArgumentsLength):
+
+2012-11-09 Filip Pizlo <fpi...@apple.com>
+
Fix indentation of BooleanPrototype.h
Rubber stamped by Mark Hahnenberg.
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp (134150 => 134151)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp 2012-11-10 05:16:00 UTC (rev 134150)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp 2012-11-10 05:54:11 UTC (rev 134151)
@@ -1452,7 +1452,7 @@
forNode(nodeIndex).clear(); // The result is not a JS value.
break;
case CheckArray: {
- if (node.arrayMode().alreadyChecked(forNode(node.child1()))) {
+ if (node.arrayMode().alreadyChecked(m_graph, node, forNode(node.child1()))) {
m_foundConstants = true;
node.setCanExit(false);
break;
@@ -1508,7 +1508,7 @@
break;
}
case Arrayify: {
- if (node.arrayMode().alreadyChecked(forNode(node.child1()))) {
+ if (node.arrayMode().alreadyChecked(m_graph, node, forNode(node.child1()))) {
m_foundConstants = true;
node.setCanExit(false);
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp (134150 => 134151)
--- trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp 2012-11-10 05:16:00 UTC (rev 134150)
+++ trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp 2012-11-10 05:54:11 UTC (rev 134151)
@@ -29,6 +29,7 @@
#if ENABLE(DFG_JIT)
#include "DFGAbstractValue.h"
+#include "DFGGraph.h"
namespace JSC { namespace DFG {
@@ -200,22 +201,58 @@
}
}
-bool ArrayMode::alreadyChecked(AbstractValue& value, IndexingType shape) const
+Structure* ArrayMode::originalArrayStructure(Graph& graph, const CodeOrigin& codeOrigin) const
{
- if (isJSArray()) {
+ 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);
+ default:
+ CRASH();
+ return 0;
+ }
+}
+
+Structure* ArrayMode::originalArrayStructure(Graph& graph, Node& node) const
+{
+ return originalArrayStructure(graph, node.codeOrigin);
+}
+
+bool ArrayMode::alreadyChecked(Graph& graph, Node& node, 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::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);
+
+ 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 (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape) | asArrayModes(shape | IsArray)))
- return true;
- return value.m_currentKnownStructure.hasSingleton()
- && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape;
}
-bool ArrayMode::alreadyChecked(AbstractValue& value) const
+bool ArrayMode::alreadyChecked(Graph& graph, Node& node, AbstractValue& value) const
{
switch (type()) {
case Array::Generic:
@@ -228,29 +265,36 @@
return speculationChecked(value.m_type, SpecString);
case Array::Int32:
- return alreadyChecked(value, Int32Shape);
+ return alreadyChecked(graph, node, value, Int32Shape);
case Array::Double:
- return alreadyChecked(value, DoubleShape);
+ return alreadyChecked(graph, node, value, DoubleShape);
case Array::Contiguous:
- return alreadyChecked(value, ContiguousShape);
+ return alreadyChecked(graph, node, value, ContiguousShape);
case Array::ArrayStorage:
- return alreadyChecked(value, ArrayStorageShape);
+ return alreadyChecked(graph, node, value, ArrayStorageShape);
case Array::SlowPutArrayStorage:
- if (isJSArray()) {
+ switch (arrayClass()) {
+ case Array::OriginalArray:
+ CRASH();
+ return false;
+
+ 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);
+
+ 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 (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::Arguments:
return speculationChecked(value.m_type, SpecArguments);
Modified: trunk/Source/_javascript_Core/dfg/DFGArrayMode.h (134150 => 134151)
--- trunk/Source/_javascript_Core/dfg/DFGArrayMode.h 2012-11-10 05:16:00 UTC (rev 134150)
+++ trunk/Source/_javascript_Core/dfg/DFGArrayMode.h 2012-11-10 05:54:11 UTC (rev 134151)
@@ -33,9 +33,15 @@
#include "ArrayProfile.h"
#include "SpeculatedType.h"
-namespace JSC { namespace DFG {
+namespace JSC {
+struct CodeOrigin;
+
+namespace DFG {
+
+class Graph;
struct AbstractValue;
+struct Node;
// Use a namespace + enum instead of enum alone to avoid the namespace collision
// that would otherwise occur, since we say things like "Int8Array" and "JSArray"
@@ -161,7 +167,7 @@
mySpeculation = Array::InBounds;
if (isJSArray()) {
- if (profile->usesOriginalArrayStructures())
+ if (profile->usesOriginalArrayStructures() && benefitsFromOriginalArray())
myArrayClass = Array::OriginalArray;
else
myArrayClass = Array::Array;
@@ -183,7 +189,7 @@
ArrayMode refine(SpeculatedType base, SpeculatedType index, SpeculatedType value = SpecNone) const;
- bool alreadyChecked(AbstractValue&) const;
+ bool alreadyChecked(Graph&, Node&, AbstractValue&) const;
const char* toString() const;
@@ -303,6 +309,23 @@
}
}
+ bool benefitsFromOriginalArray() const
+ {
+ switch (type()) {
+ case Array::Int32:
+ case Array::Double:
+ case Array::Contiguous:
+ case Array::ArrayStorage:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // Returns 0 if this is not OriginalArray.
+ Structure* originalArrayStructure(Graph&, const CodeOrigin&) const;
+ Structure* originalArrayStructure(Graph&, Node&) const;
+
bool benefitsFromStructureCheck() const
{
switch (type()) {
@@ -375,7 +398,7 @@
}
}
- bool alreadyChecked(AbstractValue&, IndexingType shape) const;
+ bool alreadyChecked(Graph&, Node&, AbstractValue&, IndexingType shape) const;
union {
struct {
Modified: trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (134150 => 134151)
--- trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2012-11-10 05:16:00 UTC (rev 134150)
+++ trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2012-11-10 05:54:11 UTC (rev 134151)
@@ -116,7 +116,7 @@
case CheckArray:
case Arrayify: {
- if (!node.arrayMode().alreadyChecked(m_state.forNode(node.child1())))
+ if (!node.arrayMode().alreadyChecked(m_graph, node, m_state.forNode(node.child1())))
break;
ASSERT(node.refCount() == 1);
node.setOpAndDefaultFlags(Phantom);
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (134150 => 134151)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2012-11-10 05:16:00 UTC (rev 134150)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2012-11-10 05:54:11 UTC (rev 134151)
@@ -424,31 +424,12 @@
m_graph.ref(array);
+ Structure* structure = arrayMode.originalArrayStructure(m_graph, codeOrigin);
+
if (arrayMode.doesConversion()) {
if (index != NoNode)
m_graph.ref(index);
- Structure* structure = 0;
- if (arrayMode.isJSArrayWithOriginalStructure()) {
- JSGlobalObject* globalObject = m_graph.baselineCodeBlockFor(codeOrigin)->globalObject();
- switch (arrayMode.type()) {
- case Array::Int32:
- structure = globalObject->originalArrayStructureForIndexingType(ArrayWithInt32);
- break;
- case Array::Double:
- structure = globalObject->originalArrayStructureForIndexingType(ArrayWithDouble);
- break;
- case Array::Contiguous:
- structure = globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous);
- break;
- case Array::ArrayStorage:
- structure = globalObject->originalArrayStructureForIndexingType(ArrayWithArrayStorage);
- break;
- default:
- break;
- }
- }
-
if (structure) {
Node arrayify(ArrayifyToStructure, codeOrigin, OpInfo(structure), OpInfo(arrayMode.asWord()), array, index);
arrayify.ref();
@@ -463,11 +444,19 @@
m_insertionSet.append(m_indexInBlock, arrayifyIndex);
}
} else {
- Node checkArray(CheckArray, codeOrigin, OpInfo(arrayMode.asWord()), array);
- checkArray.ref();
- NodeIndex checkArrayIndex = m_graph.size();
- m_graph.append(checkArray);
- m_insertionSet.append(m_indexInBlock, checkArrayIndex);
+ if (structure) {
+ Node checkStructure(CheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(structure)), array);
+ checkStructure.ref();
+ NodeIndex checkStructureIndex = m_graph.size();
+ m_graph.append(checkStructure);
+ m_insertionSet.append(m_indexInBlock, checkStructureIndex);
+ } else {
+ Node checkArray(CheckArray, codeOrigin, OpInfo(arrayMode.asWord()), array);
+ checkArray.ref();
+ NodeIndex checkArrayIndex = m_graph.size();
+ m_graph.append(checkArray);
+ m_insertionSet.append(m_indexInBlock, checkArrayIndex);
+ }
}
if (!storageCheck(arrayMode))
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (134150 => 134151)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2012-11-10 05:16:00 UTC (rev 134150)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2012-11-10 05:54:11 UTC (rev 134151)
@@ -361,13 +361,22 @@
JITCompiler::Jump SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode, IndexingType shape, bool invert)
{
- if (arrayMode.isJSArray()) {
+ switch (arrayMode.arrayClass()) {
+ case Array::OriginalArray: {
+ CRASH();
+ JITCompiler::Jump result; // I already know that VC++ takes unkindly to the _expression_ "return Jump()", so I'm doing it this way in anticipation of someone eventually using VC++ to compile the DFG.
+ return result;
+ }
+
+ case Array::Array:
m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
return m_jit.branch32(
invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(IsArray | shape));
+
+ default:
+ m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
+ return m_jit.branch32(invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(shape));
}
- m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
- return m_jit.branch32(invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(shape));
}
JITCompiler::JumpList SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode, bool invert)
@@ -386,12 +395,13 @@
case Array::ArrayStorage:
case Array::SlowPutArrayStorage: {
+ ASSERT(!arrayMode.isJSArrayWithOriginalStructure());
+
if (arrayMode.isJSArray()) {
if (arrayMode.isSlowPut()) {
if (invert) {
- JITCompiler::Jump slow =
- m_jit.branchTest32(
- MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32(IsArray));
+ JITCompiler::Jump slow = m_jit.branchTest32(
+ MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32(IsArray));
m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
m_jit.sub32(TrustedImm32(ArrayStorageShape), tempGPR);
result.append(
@@ -449,7 +459,7 @@
const TypedArrayDescriptor* result = typedArrayDescriptor(node.arrayMode());
- if (node.arrayMode().alreadyChecked(m_state.forNode(node.child1()))) {
+ if (node.arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1()))) {
noResult(m_compileIndex);
return;
}
@@ -1959,7 +1969,7 @@
GPRReg propertyReg = property.gpr();
GPRReg storageReg = storage.gpr();
- ASSERT(ArrayMode(Array::String).alreadyChecked(m_state.forNode(node.child1())));
+ ASSERT(ArrayMode(Array::String).alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1())));
// unsigned comparison so we can filter out negative indices and indices that are too large
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSString::offsetOfLength())));
@@ -2368,7 +2378,7 @@
GPRTemporary result(this);
GPRReg resultReg = result.gpr();
- ASSERT(node.arrayMode().alreadyChecked(m_state.forNode(node.child1())));
+ ASSERT(node.arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1())));
speculationCheck(
Uncountable, JSValueRegs(), NoNode,
@@ -2518,7 +2528,7 @@
GPRReg propertyReg = property.gpr();
GPRReg storageReg = storage.gpr();
- ASSERT(node.arrayMode().alreadyChecked(m_state.forNode(node.child1())));
+ ASSERT(node.arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1())));
FPRTemporary result(this);
FPRReg resultReg = result.fpr();
@@ -2555,7 +2565,7 @@
SpeculateDoubleOperand valueOp(this, valueUse);
- ASSERT_UNUSED(baseUse, node.arrayMode().alreadyChecked(m_state.forNode(baseUse)));
+ ASSERT_UNUSED(baseUse, node.arrayMode().alreadyChecked(m_jit.graph(), m_jit.graph()[m_compileIndex], m_state.forNode(baseUse)));
GPRTemporary result(this);
@@ -3378,7 +3388,7 @@
if (!m_compileOkay)
return;
- ASSERT(ArrayMode(Array::Arguments).alreadyChecked(m_state.forNode(node.child1())));
+ ASSERT(ArrayMode(Array::Arguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1())));
// Two really lame checks.
speculationCheck(
@@ -3435,7 +3445,7 @@
if (!m_compileOkay)
return;
- ASSERT(ArrayMode(Array::Arguments).alreadyChecked(m_state.forNode(node.child1())));
+ ASSERT(ArrayMode(Array::Arguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1())));
speculationCheck(
Uncountable, JSValueSource(), NoNode,