Diff
Modified: trunk/LayoutTests/ChangeLog (154304 => 154305)
--- trunk/LayoutTests/ChangeLog 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/LayoutTests/ChangeLog 2013-08-19 23:16:01 UTC (rev 154305)
@@ -1,5 +1,20 @@
2013-08-18 Filip Pizlo <[email protected]>
+ DFG should inline typedArray.byteOffset
+ https://bugs.webkit.org/show_bug.cgi?id=119962
+
+ Reviewed by Oliver Hunt.
+
+ * fast/js/dfg-byteOffset-neuter.html: Added.
+ * fast/js/dfg-byteOffset-neuter-expected.txt: Added.
+ * fast/js/regress/ArrayBuffer-Int32Array-byteOffset-expected.txt: Added.
+ * fast/js/regress/ArrayBuffer-Int32Array-byteOffset.html: Added.
+ * fast/js/regress/script-tests/ArrayBuffer-Int32Array-byteOffset.js: Added.
+ * fast/js/script-tests/dfg-byteOffset-neuter.js: Added.
+ (foo):
+
+2013-08-18 Filip Pizlo <[email protected]>
+
<https://webkit.org/b/119994> DFG new Array() inlining could get confused about global objects
Reviewed by Geoffrey Garen.
Added: trunk/LayoutTests/fast/js/dfg-byteOffset-neuter-expected.txt (0 => 154305)
--- trunk/LayoutTests/fast/js/dfg-byteOffset-neuter-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-byteOffset-neuter-expected.txt 2013-08-19 23:16:01 UTC (rev 154305)
@@ -0,0 +1,10 @@
+Tests that byteOffset does the right thing for neutered views.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS foo(array) is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/js/dfg-byteOffset-neuter.html (0 => 154305)
--- trunk/LayoutTests/fast/js/dfg-byteOffset-neuter.html (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-byteOffset-neuter.html 2013-08-19 23:16:01 UTC (rev 154305)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/js/regress/ArrayBuffer-Int32Array-byteOffset-expected.txt (0 => 154305)
--- trunk/LayoutTests/fast/js/regress/ArrayBuffer-Int32Array-byteOffset-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/js/regress/ArrayBuffer-Int32Array-byteOffset-expected.txt 2013-08-19 23:16:01 UTC (rev 154305)
@@ -0,0 +1,10 @@
+JSRegress/ArrayBuffer-Int32Array-byteOffset
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/js/regress/ArrayBuffer-Int32Array-byteOffset.html (0 => 154305)
--- trunk/LayoutTests/fast/js/regress/ArrayBuffer-Int32Array-byteOffset.html (rev 0)
+++ trunk/LayoutTests/fast/js/regress/ArrayBuffer-Int32Array-byteOffset.html 2013-08-19 23:16:01 UTC (rev 154305)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/fast/js/regress/script-tests/ArrayBuffer-Int32Array-byteOffset.js (0 => 154305)
--- trunk/LayoutTests/fast/js/regress/script-tests/ArrayBuffer-Int32Array-byteOffset.js (rev 0)
+++ trunk/LayoutTests/fast/js/regress/script-tests/ArrayBuffer-Int32Array-byteOffset.js 2013-08-19 23:16:01 UTC (rev 154305)
@@ -0,0 +1,12 @@
+var result = 0;
+var buffer = new ArrayBuffer(10);
+var array1 = new Int32Array(buffer, 4, 1);
+var array2 = new Uint32Array(10);
+
+for (var i = 0; i < 1000000; ++i) {
+ result += array1.byteOffset;
+ result += array2.byteOffset;
+}
+
+if (result != 4000000)
+ throw "Error: wrong result: " + result;
Added: trunk/LayoutTests/fast/js/script-tests/dfg-byteOffset-neuter.js (0 => 154305)
--- trunk/LayoutTests/fast/js/script-tests/dfg-byteOffset-neuter.js (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/dfg-byteOffset-neuter.js 2013-08-19 23:16:01 UTC (rev 154305)
@@ -0,0 +1,18 @@
+description(
+"Tests that byteOffset does the right thing for neutered views."
+);
+
+function foo(o) {
+ return o.byteOffset;
+}
+
+var array = new Int8Array(new ArrayBuffer(100));
+
+noInline(foo);
+while (!dfgCompiled({f:foo}))
+ foo(array);
+
+window.postMessage(array, "*", [array.buffer]);
+
+shouldBe("foo(array)", "0");
+
Modified: trunk/Source/_javascript_Core/ChangeLog (154304 => 154305)
--- trunk/Source/_javascript_Core/ChangeLog 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/ChangeLog 2013-08-19 23:16:01 UTC (rev 154305)
@@ -1,3 +1,61 @@
+2013-08-17 Filip Pizlo <[email protected]>
+
+ DFG should inline typedArray.byteOffset
+ https://bugs.webkit.org/show_bug.cgi?id=119962
+
+ Reviewed by Oliver Hunt.
+
+ This adds a new node, GetTypedArrayByteOffset, which inlines
+ typedArray.byteOffset.
+
+ Also, I improved a bunch of the clobbering logic related to typed arrays
+ and clobbering in general. For example, PutByOffset/PutStructure are not
+ clobber-world so they can be handled by most default cases in CSE. Also,
+ It's better to use the 'Class_field' notation for typed arrays now that
+ they no longer involve magical descriptor thingies.
+
+ * bytecode/SpeculatedType.h:
+ * dfg/DFGAbstractHeap.h:
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::::executeEffects):
+ * dfg/DFGArrayMode.h:
+ (JSC::DFG::neverNeedsStorage):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::getByValLoadElimination):
+ (JSC::DFG::CSEPhase::getByOffsetLoadElimination):
+ (JSC::DFG::CSEPhase::getPropertyStorageLoadElimination):
+ (JSC::DFG::CSEPhase::checkArrayElimination):
+ (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination):
+ (JSC::DFG::CSEPhase::getTypedArrayByteOffsetLoadElimination):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ (JSC::DFG::FixupPhase::attemptToMakeGetTypedArrayByteLength):
+ (JSC::DFG::FixupPhase::convertToGetArrayLength):
+ (JSC::DFG::FixupPhase::attemptToMakeGetTypedArrayByteOffset):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileGetTypedArrayByteOffset):
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGTypeCheckHoistingPhase.cpp:
+ (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
+ * runtime/ArrayBuffer.h:
+ (JSC::ArrayBuffer::offsetOfData):
+ * runtime/Butterfly.h:
+ (JSC::Butterfly::offsetOfArrayBuffer):
+ * runtime/IndexingHeader.h:
+ (JSC::IndexingHeader::offsetOfArrayBuffer):
+
2013-08-18 Filip Pizlo <[email protected]>
<https://webkit.org/b/119994> DFG new Array() inlining could get confused about global objects
Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.h (154304 => 154305)
--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.h 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.h 2013-08-19 23:16:01 UTC (rev 154305)
@@ -51,6 +51,7 @@
static const SpeculatedType SpecUint32Array = 0x00000400; // It's definitely an Uint32Array or one of its subclasses.
static const SpeculatedType SpecFloat32Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses.
static const SpeculatedType SpecFloat64Array = 0x00001000; // It's definitely an Uint16Array or one of its subclasses.
+static const SpeculatedType SpecTypedArrayView = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array;
static const SpeculatedType SpecArguments = 0x00002000; // It's definitely an Arguments object.
static const SpeculatedType SpecStringObject = 0x00004000; // It's definitely a StringObject.
static const SpeculatedType SpecObjectOther = 0x00008000; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractHeap.h (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractHeap.h 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractHeap.h 2013-08-19 23:16:01 UTC (rev 154305)
@@ -48,8 +48,13 @@
macro(Arguments_overrideLength) \
macro(Arguments_registers) \
macro(Arguments_slowArguments) \
+ macro(ArrayBuffer_data) \
+ macro(Butterfly_arrayBuffer) \
macro(Butterfly_publicLength) \
macro(Butterfly_vectorLength) \
+ macro(JSArrayBufferView_length) \
+ macro(JSArrayBufferView_mode) \
+ macro(JSArrayBufferView_vector) \
macro(JSCell_structure) \
macro(JSFunction_executable) \
macro(JSFunction_scopeChain) \
@@ -61,9 +66,7 @@
macro(IndexedContiguousProperties) \
macro(ArrayStorageProperties) \
macro(Variables) \
- macro(TypedArrayStoragePointer) \
macro(TypedArrayProperties) \
- macro(TypedArrayLength) \
macro(GCState) \
macro(RegExpState) \
macro(InternalState) \
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2013-08-19 23:16:01 UTC (rev 154305)
@@ -1376,6 +1376,12 @@
forNode(node).clear();
break;
}
+
+ case GetTypedArrayByteOffset: {
+ forNode(node).setType(SpecInt32);
+ break;
+ }
+
case GetByOffset: {
forNode(node).makeTop();
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGArrayMode.h (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGArrayMode.h 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGArrayMode.h 2013-08-19 23:16:01 UTC (rev 154305)
@@ -445,6 +445,11 @@
return arrayMode.lengthNeedsStorage();
}
+static inline bool neverNeedsStorage(const ArrayMode&)
+{
+ return false;
+}
+
} } // namespace JSC::DFG
namespace WTF {
Modified: trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp 2013-08-19 23:16:01 UTC (rev 154305)
@@ -396,13 +396,6 @@
// typed arrays! An Int32Array can alias a Float64Array for example, and so on.
return 0;
}
- case PutStructure:
- case PutByOffset:
- // GetByVal currently always speculates that it's accessing an
- // array with an integer index, which means that it's impossible
- // for a structure change or a put to property storage to affect
- // the GetByVal.
- break;
default:
if (m_graph.clobbersWorld(node))
return 0;
@@ -634,10 +627,6 @@
}
break;
- case PutStructure:
- // Changing the structure cannot change the outcome of a property get.
- break;
-
case PutByVal:
case PutByValAlias:
if (m_graph.byValIsPure(node)) {
@@ -724,12 +713,6 @@
// pointer of any object, including ours.
return 0;
- case PutByOffset:
- case PutStructure:
- // Changing the structure or putting to the storage cannot
- // change the property storage pointer.
- break;
-
case PutByVal:
case PutByValAlias:
if (m_graph.byValIsPure(node)) {
@@ -763,12 +746,6 @@
break;
switch (node->op()) {
- case PutByOffset:
- case PutStructure:
- // Changing the structure or putting to the storage cannot
- // change the property storage pointer.
- break;
-
case CheckArray:
if (node->child1() == child1 && node->arrayMode() == arrayMode)
return true;
@@ -803,12 +780,29 @@
break;
}
- case PutByOffset:
- case PutStructure:
- // Changing the structure or putting to the storage cannot
- // change the property storage pointer.
+ default:
+ if (m_graph.clobbersWorld(node))
+ return 0;
break;
-
+ }
+ }
+ return 0;
+ }
+
+ Node* getTypedArrayByteOffsetLoadElimination(Node* child1)
+ {
+ for (unsigned i = m_indexInBlock; i--;) {
+ Node* node = m_currentBlock->at(i);
+ if (node == child1)
+ break;
+
+ switch (node->op()) {
+ case GetTypedArrayByteOffset: {
+ if (node->child1() == child1)
+ return node;
+ break;
+ }
+
default:
if (m_graph.clobbersWorld(node))
return 0;
@@ -1343,6 +1337,13 @@
setReplacement(getIndexedPropertyStorageLoadElimination(node->child1().node(), node->arrayMode()));
break;
}
+
+ case GetTypedArrayByteOffset: {
+ if (cseMode == StoreElimination)
+ break;
+ setReplacement(getTypedArrayByteOffsetLoadElimination(node->child1().node()));
+ break;
+ }
case GetButterfly:
if (cseMode == StoreElimination)
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2013-08-19 23:16:01 UTC (rev 154305)
@@ -290,6 +290,8 @@
case Array::Float32Array:
case Array::Float64Array:
read(TypedArrayProperties);
+ read(JSArrayBufferView_vector);
+ read(JSArrayBufferView_length);
return;
}
RELEASE_ASSERT_NOT_REACHED();
@@ -377,6 +379,8 @@
case Array::Uint32Array:
case Array::Float32Array:
case Array::Float64Array:
+ read(JSArrayBufferView_vector);
+ read(JSArrayBufferView_length);
write(TypedArrayProperties);
return;
}
@@ -425,9 +429,16 @@
case GetIndexedPropertyStorage:
if (node->arrayMode().type() == Array::String)
return;
- read(TypedArrayStoragePointer);
+ read(JSArrayBufferView_vector);
return;
+ case GetTypedArrayByteOffset:
+ read(JSArrayBufferView_vector);
+ read(JSArrayBufferView_mode);
+ read(Butterfly_arrayBuffer);
+ read(ArrayBuffer_data);
+ return;
+
case GetByOffset:
read(AbstractHeap(NamedProperties, graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber));
return;
@@ -456,7 +467,7 @@
return;
default:
- read(TypedArrayLength);
+ read(JSArrayBufferView_length);
return;
}
}
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2013-08-19 23:16:01 UTC (rev 154305)
@@ -729,14 +729,19 @@
case GetByIdFlush: {
if (!node->child1()->shouldSpeculateCell())
break;
- if (m_graph.identifiers()[node->identifierNumber()] == vm().propertyNames->length.impl()) {
+ StringImpl* impl = m_graph.identifiers()[node->identifierNumber()];
+ if (impl == vm().propertyNames->length.impl()) {
attemptToMakeGetArrayLength(node);
break;
}
- if (m_graph.identifiers()[node->identifierNumber()] == vm().propertyNames->byteLength.impl()) {
- attemptToMakeGetByteLength(node);
+ if (impl == vm().propertyNames->byteLength.impl()) {
+ attemptToMakeGetTypedArrayByteLength(node);
break;
}
+ if (impl == vm().propertyNames->byteOffset.impl()) {
+ attemptToMakeGetTypedArrayByteOffset(node);
+ break;
+ }
setUseKindAndUnboxIfProfitable<CellUse>(node->child1());
break;
}
@@ -825,6 +830,7 @@
case GetArgument:
case PhantomPutStructure:
case GetIndexedPropertyStorage:
+ case GetTypedArrayByteOffset:
case LastNodeType:
case MovHint:
case MovHintAndCheck:
@@ -1452,7 +1458,7 @@
return true;
}
- bool attemptToMakeGetByteLength(Node* node)
+ bool attemptToMakeGetTypedArrayByteLength(Node* node)
{
if (!isInt32Speculation(node->prediction()))
return false;
@@ -1476,7 +1482,6 @@
// We can use a BitLShift here because typed arrays will never have a byteLength
// that overflows int32.
node->setOp(BitLShift);
- ASSERT(node->flags() & NodeMustGenerate);
node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
observeUseKindOnNode(length, Int32Use);
observeUseKindOnNode(shiftAmount, Int32Use);
@@ -1488,7 +1493,6 @@
void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
{
node->setOp(GetArrayLength);
- ASSERT(node->flags() & NodeMustGenerate);
node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
node->setArrayMode(arrayMode);
@@ -1507,6 +1511,25 @@
m_indexInBlock, SpecInt32, GetArrayLength, codeOrigin,
OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
}
+
+ bool attemptToMakeGetTypedArrayByteOffset(Node* node)
+ {
+ if (!isInt32Speculation(node->prediction()))
+ return false;
+
+ TypedArrayType type = typedArrayTypeFromSpeculation(node->child1()->prediction());
+ if (!isTypedView(type))
+ return false;
+
+ checkArray(
+ ArrayMode(toArrayType(type)), node->codeOrigin, node->child1().node(),
+ 0, neverNeedsStorage);
+
+ node->setOp(GetTypedArrayByteOffset);
+ node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+ setUseKindAndUnboxIfProfitable<KnownCellUse>(node->child1());
+ return true;
+ }
BasicBlock* m_block;
unsigned m_indexInBlock;
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2013-08-19 23:16:01 UTC (rev 154305)
@@ -154,6 +154,7 @@
macro(GetByOffset, NodeResultJS) \
macro(PutByOffset, NodeMustGenerate) \
macro(GetArrayLength, NodeResultInt32) \
+ macro(GetTypedArrayByteOffset, NodeResultInt32) \
macro(GetScope, NodeResultJS) \
macro(GetMyScope, NodeResultJS) \
macro(SetMyScope, NodeMustGenerate) \
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2013-08-19 23:16:01 UTC (rev 154305)
@@ -466,6 +466,7 @@
case PutByValAlias:
case GetArrayLength:
+ case GetTypedArrayByteOffset:
case Int32ToDouble:
case DoubleAsInt32:
case GetLocalUnlinked:
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2013-08-19 23:16:01 UTC (rev 154305)
@@ -243,6 +243,9 @@
case StringCharCodeAt:
return node->arrayMode().alreadyChecked(graph, node, state.forNode(node->child1()));
+ case GetTypedArrayByteOffset:
+ return !(state.forNode(node->child1()).m_type & ~(SpecTypedArrayView));
+
case PutByVal:
case PutByValAlias:
return node->arrayMode().modeForPut().alreadyChecked(
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2013-08-19 23:16:01 UTC (rev 154305)
@@ -4032,6 +4032,37 @@
storageResult(storageReg, node);
}
+void SpeculativeJIT::compileGetTypedArrayByteOffset(Node* node)
+{
+ SpeculateCellOperand base(this, node->child1());
+ GPRTemporary vector(this);
+ GPRTemporary data(this);
+
+ GPRReg baseGPR = base.gpr();
+ GPRReg vectorGPR = vector.gpr();
+ GPRReg dataGPR = data.gpr();
+
+ JITCompiler::Jump emptyByteOffset = m_jit.branch32(
+ MacroAssembler::NotEqual,
+ MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfMode()),
+ TrustedImm32(WastefulTypedArray));
+
+ m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), dataGPR);
+ m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfVector()), vectorGPR);
+ m_jit.loadPtr(MacroAssembler::Address(dataGPR, Butterfly::offsetOfArrayBuffer()), dataGPR);
+ m_jit.loadPtr(MacroAssembler::Address(dataGPR, ArrayBuffer::offsetOfData()), dataGPR);
+ m_jit.subPtr(dataGPR, vectorGPR);
+
+ JITCompiler::Jump done = m_jit.jump();
+
+ emptyByteOffset.link(&m_jit);
+ m_jit.move(TrustedImmPtr(0), vectorGPR);
+
+ done.link(&m_jit);
+
+ integerResult(vectorGPR, node);
+}
+
void SpeculativeJIT::compileGetByValOnArguments(Node* node)
{
SpeculateCellOperand base(this, node->child1());
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2013-08-19 23:16:01 UTC (rev 154305)
@@ -1973,6 +1973,7 @@
void compileArithDiv(Node*);
void compileArithMod(Node*);
void compileGetIndexedPropertyStorage(Node*);
+ void compileGetTypedArrayByteOffset(Node*);
void compileGetByValOnIntTypedArray(Node*, TypedArrayType);
void compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
void compileGetByValOnFloatTypedArray(Node*, TypedArrayType);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2013-08-19 23:16:01 UTC (rev 154305)
@@ -4027,6 +4027,11 @@
break;
}
+ case GetTypedArrayByteOffset: {
+ compileGetTypedArrayByteOffset(node);
+ break;
+ }
+
case GetByOffset: {
StorageOperand storage(this, node->child1());
GPRTemporary resultTag(this, storage);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2013-08-19 23:16:01 UTC (rev 154305)
@@ -3945,6 +3945,11 @@
break;
}
+ case GetTypedArrayByteOffset: {
+ compileGetTypedArrayByteOffset(node);
+ break;
+ }
+
case GetByOffset: {
StorageOperand storage(this, node->child1());
GPRTemporary result(this, storage);
Modified: trunk/Source/_javascript_Core/dfg/DFGTypeCheckHoistingPhase.cpp (154304 => 154305)
--- trunk/Source/_javascript_Core/dfg/DFGTypeCheckHoistingPhase.cpp 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/dfg/DFGTypeCheckHoistingPhase.cpp 2013-08-19 23:16:01 UTC (rev 154305)
@@ -254,6 +254,7 @@
case GetArrayLength:
case CheckArray:
case GetIndexedPropertyStorage:
+ case GetTypedArrayByteOffset:
case Phantom:
// Don't count these uses.
break;
Modified: trunk/Source/_javascript_Core/runtime/ArrayBuffer.h (154304 => 154305)
--- trunk/Source/_javascript_Core/runtime/ArrayBuffer.h 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/runtime/ArrayBuffer.h 2013-08-19 23:16:01 UTC (rev 154305)
@@ -113,6 +113,8 @@
JS_EXPORT_PRIVATE bool transfer(ArrayBufferContents&);
bool isNeutered() { return !m_contents.m_data; }
+
+ static ptrdiff_t offsetOfData() { return OBJECT_OFFSETOF(ArrayBuffer, m_contents) + OBJECT_OFFSETOF(ArrayBufferContents, m_data); }
~ArrayBuffer() { }
Modified: trunk/Source/_javascript_Core/runtime/Butterfly.h (154304 => 154305)
--- trunk/Source/_javascript_Core/runtime/Butterfly.h 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/runtime/Butterfly.h 2013-08-19 23:16:01 UTC (rev 154305)
@@ -101,6 +101,7 @@
char* pointer() { return reinterpret_cast<char*>(this); }
static ptrdiff_t offsetOfIndexingHeader() { return IndexingHeader::offsetOfIndexingHeader(); }
+ static ptrdiff_t offsetOfArrayBuffer() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfArrayBuffer(); }
static ptrdiff_t offsetOfPublicLength() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfPublicLength(); }
static ptrdiff_t offsetOfVectorLength() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfVectorLength(); }
Modified: trunk/Source/_javascript_Core/runtime/IndexingHeader.h (154304 => 154305)
--- trunk/Source/_javascript_Core/runtime/IndexingHeader.h 2013-08-19 22:40:17 UTC (rev 154304)
+++ trunk/Source/_javascript_Core/runtime/IndexingHeader.h 2013-08-19 23:16:01 UTC (rev 154305)
@@ -45,6 +45,7 @@
static ptrdiff_t offsetOfIndexingHeader() { return -static_cast<ptrdiff_t>(sizeof(IndexingHeader)); }
+ static ptrdiff_t offsetOfArrayBuffer() { return OBJECT_OFFSETOF(IndexingHeader, u.typedArray.buffer); }
static ptrdiff_t offsetOfPublicLength() { return OBJECT_OFFSETOF(IndexingHeader, u.lengths.publicLength); }
static ptrdiff_t offsetOfVectorLength() { return OBJECT_OFFSETOF(IndexingHeader, u.lengths.vectorLength); }