DFG should inline typedArray.byteOffset
https://bugs.webkit.org/show_bug.cgi?id=119962
Source/JavaScriptCore:
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):
LayoutTests:
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):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@154305 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 2b36e00..3c3c738 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,61 @@
+2013-08-17 Filip Pizlo <fpizlo@apple.com>
+
+ 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 <fpizlo@apple.com>
<https://webkit.org/b/119994> DFG new Array() inlining could get confused about global objects
diff --git a/Source/JavaScriptCore/bytecode/SpeculatedType.h b/Source/JavaScriptCore/bytecode/SpeculatedType.h
index bf31c5d..803e7a8 100644
--- a/Source/JavaScriptCore/bytecode/SpeculatedType.h
+++ b/Source/JavaScriptCore/bytecode/SpeculatedType.h
@@ -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.
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractHeap.h b/Source/JavaScriptCore/dfg/DFGAbstractHeap.h
index c9bbc56..6914fdf 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractHeap.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractHeap.h
@@ -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) \
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
index 1bb2afa..4a5d46d 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
@@ -1376,6 +1376,12 @@
forNode(node).clear();
break;
}
+
+ case GetTypedArrayByteOffset: {
+ forNode(node).setType(SpecInt32);
+ break;
+ }
+
case GetByOffset: {
forNode(node).makeTop();
break;
diff --git a/Source/JavaScriptCore/dfg/DFGArrayMode.h b/Source/JavaScriptCore/dfg/DFGArrayMode.h
index 02a69a5..1689189 100644
--- a/Source/JavaScriptCore/dfg/DFGArrayMode.h
+++ b/Source/JavaScriptCore/dfg/DFGArrayMode.h
@@ -445,6 +445,11 @@
return arrayMode.lengthNeedsStorage();
}
+static inline bool neverNeedsStorage(const ArrayMode&)
+{
+ return false;
+}
+
} } // namespace JSC::DFG
namespace WTF {
diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
index 0dda196..629b565 100644
--- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
@@ -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)
diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h
index 6ed4a4a..5efd6ca 100644
--- a/Source/JavaScriptCore/dfg/DFGClobberize.h
+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h
@@ -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,7 +429,14 @@
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:
@@ -456,7 +467,7 @@
return;
default:
- read(TypedArrayLength);
+ read(JSArrayBufferView_length);
return;
}
}
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index cab0c23..99d15bb 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -729,12 +729,17 @@
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());
@@ -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;
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index d30e4fc..9e3616b 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -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) \
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index a038bf4..cacdd7c 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -466,6 +466,7 @@
case PutByValAlias:
case GetArrayLength:
+ case GetTypedArrayByteOffset:
case Int32ToDouble:
case DoubleAsInt32:
case GetLocalUnlinked:
diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
index d89c833..39e55ab 100644
--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
@@ -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(
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index dc09322..d615a4e 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -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());
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index 6262686..d87efe0 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -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);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index c3a2475e..b45c618 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -4027,6 +4027,11 @@
break;
}
+ case GetTypedArrayByteOffset: {
+ compileGetTypedArrayByteOffset(node);
+ break;
+ }
+
case GetByOffset: {
StorageOperand storage(this, node->child1());
GPRTemporary resultTag(this, storage);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 500babf..3364f09 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -3945,6 +3945,11 @@
break;
}
+ case GetTypedArrayByteOffset: {
+ compileGetTypedArrayByteOffset(node);
+ break;
+ }
+
case GetByOffset: {
StorageOperand storage(this, node->child1());
GPRTemporary result(this, storage);
diff --git a/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp b/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp
index 2254bf9..c2230e3 100644
--- a/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp
@@ -254,6 +254,7 @@
case GetArrayLength:
case CheckArray:
case GetIndexedPropertyStorage:
+ case GetTypedArrayByteOffset:
case Phantom:
// Don't count these uses.
break;
diff --git a/Source/JavaScriptCore/runtime/ArrayBuffer.h b/Source/JavaScriptCore/runtime/ArrayBuffer.h
index 8977573..204df41 100644
--- a/Source/JavaScriptCore/runtime/ArrayBuffer.h
+++ b/Source/JavaScriptCore/runtime/ArrayBuffer.h
@@ -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() { }
diff --git a/Source/JavaScriptCore/runtime/Butterfly.h b/Source/JavaScriptCore/runtime/Butterfly.h
index 3fc0077..ded85fc 100644
--- a/Source/JavaScriptCore/runtime/Butterfly.h
+++ b/Source/JavaScriptCore/runtime/Butterfly.h
@@ -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(); }
diff --git a/Source/JavaScriptCore/runtime/IndexingHeader.h b/Source/JavaScriptCore/runtime/IndexingHeader.h
index fefaaf6..2788129 100644
--- a/Source/JavaScriptCore/runtime/IndexingHeader.h
+++ b/Source/JavaScriptCore/runtime/IndexingHeader.h
@@ -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); }