WebKit Bugzilla
Attachment 347465 Details for
Bug 188573
: Inline DataView accesses into DFG/FTL
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP
c-backup.diff (text/plain), 72.44 KB, created by
Saam Barati
on 2018-08-19 14:03:23 PDT
(
hide
)
Description:
WIP
Filename:
MIME Type:
Creator:
Saam Barati
Created:
2018-08-19 14:03:23 PDT
Size:
72.44 KB
patch
obsolete
>Index: JSTests/stress/dataview-jit.js >=================================================================== >--- JSTests/stress/dataview-jit.js (nonexistent) >+++ JSTests/stress/dataview-jit.js (working copy) >@@ -0,0 +1,183 @@ >+function assert(b) { >+ if (!b) >+ throw new Error("Bad!"); >+} >+ >+// OOPS: add unsigned tests! >+ >+function test1() { >+ function bigEndian(o, i) { >+ return o.getInt32(i, false); >+ } >+ noInline(bigEndian); >+ function littleEndian(o, i) { >+ return o.getInt32(i, true); >+ } >+ noInline(littleEndian); >+ function biEndian(o, i, b) { >+ return o.getInt32(i, b); >+ } >+ noInline(biEndian); >+ >+ let ab = new ArrayBuffer(4); >+ let ta = new Int32Array(ab); >+ ta[0] = 0x01020304; >+ let dv = new DataView(ab); >+ >+ for (let i = 0; i < 10000; ++i) { >+ assert(bigEndian(dv, 0) === 0x04030201); >+ assert(littleEndian(dv, 0) === 0x01020304); >+ if (i % 2) >+ assert(biEndian(dv, 0, true) === 0x01020304); >+ else >+ assert(biEndian(dv, 0, false) === 0x04030201); >+ } >+ >+ for (let i = 0; i < 10000; ++i) { >+ assert(bigEndian(dv, 0) === 0x04030201); >+ assert(littleEndian(dv, 0) === 0x01020304); >+ if (i % 2) >+ assert(biEndian(dv, 0, true) === 0x01020304); >+ else >+ assert(biEndian(dv, 0, false) === 0x04030201); >+ } >+ >+ // Make sure we get the right sign. >+ ta[0] = -32361386; // 0xfe123456 >+ for (let i = 0; i < 10000; ++i) { >+ assert(bigEndian(dv, 0) === 0x563412fe); >+ assert(littleEndian(dv, 0) === -32361386); >+ if (i % 2) >+ assert(biEndian(dv, 0, true) === -32361386); >+ else >+ assert(biEndian(dv, 0, false) === 0x563412fe); >+ } >+ >+ // -2146290602 == (int)0x80123456 >+ ta[0] = 0x56341280; >+ for (let i = 0; i < 10000; ++i) { >+ assert(bigEndian(dv, 0) === -2146290602); >+ assert(littleEndian(dv, 0) === 0x56341280); >+ if (i % 2) >+ assert(biEndian(dv, 0, true) === 0x56341280); >+ else >+ assert(biEndian(dv, 0, false) === -2146290602); >+ } >+} >+//test1(); >+ >+function test2() { >+ function bigEndian(o, i) { >+ return o.getInt16(i, false); >+ } >+ noInline(bigEndian); >+ function littleEndian(o, i) { >+ return o.getInt16(i, true); >+ } >+ noInline(littleEndian); >+ function biEndian(o, i, b) { >+ return o.getInt16(i, b); >+ } >+ noInline(biEndian); >+ >+ let ab = new ArrayBuffer(2); >+ let ta = new Int16Array(ab); >+ ta[0] = 0x0102; >+ let dv = new DataView(ab); >+ >+ for (let i = 0; i < 10000; ++i) { >+ assert(bigEndian(dv, 0) === 0x0201); >+ assert(littleEndian(dv, 0) === 0x0102); >+ if (i % 2) >+ assert(biEndian(dv, 0, true) === 0x0102); >+ else >+ assert(biEndian(dv, 0, false) === 0x0201); >+ } >+ >+ // Check sign. >+ ta[0] = -512; // 0xfe00 >+ for (let i = 0; i < 10000; ++i) { >+ assert(bigEndian(dv, 0) === 0x00fe); >+ assert(littleEndian(dv, 0) === -512); >+ if (i % 2) >+ assert(biEndian(dv, 0, true) === -512); >+ else >+ assert(biEndian(dv, 0, false) === 0x00fe); >+ } >+ >+ // Check sign extension. >+ ta[0] = 0x00fe; >+ for (let i = 0; i < 10000; ++i) { >+ assert(bigEndian(dv, 0) === -512); >+ assert(littleEndian(dv, 0) === 0x00fe); >+ if (i % 2) >+ assert(biEndian(dv, 0, true) === 0x00fe); >+ else >+ assert(biEndian(dv, 0, false) === -512); >+ } >+} >+//test2(); >+ >+function test3() { >+ function bigEndian(o, i) { >+ return o.getFloat32(i, false); >+ } >+ noInline(bigEndian); >+ function littleEndian(o, i) { >+ return o.getFloat32(i, true); >+ } >+ noInline(littleEndian); >+ function biEndian(o, i, b) { >+ return o.getFloat32(i, b); >+ } >+ noInline(biEndian); >+ >+ let ab = new ArrayBuffer(4); >+ let ta = new Float32Array(ab); >+ const normal = 12912.403; // 0x4649c19d >+ const normalAsDouble = 12912.403320312500; >+ //9dc14946 >+ const flipped = -5.1162437589918884e-21; >+ ta[0] = normal; >+ >+ let dv = new DataView(ab); >+ for (let i = 0; i < 10000; ++i) { >+ assert(bigEndian(dv, 0) === flipped); >+ assert(littleEndian(dv, 0) === 12912.403320312500); >+ if (i % 2) >+ assert(biEndian(dv, 0, true) === normalAsDouble); >+ else >+ assert(biEndian(dv, 0, false) === flipped); >+ } >+} >+//test3(); >+ >+function test4() { >+ function bigEndian(o, i) { >+ return o.getUint32(i, false); >+ } >+ noInline(bigEndian); >+ function littleEndian(o, i) { >+ return o.getUint32(i, true); >+ } >+ noInline(littleEndian); >+ function biEndian(o, i, b) { >+ return o.getUint32(i, b); >+ } >+ noInline(biEndian); >+ >+ let ab = new ArrayBuffer(4); >+ let ta = new Uint32Array(ab); >+ ta[0] = 0xa0b0d0f0; >+ >+ let dv = new DataView(ab); >+ for (let i = 0; i < 10000; ++i) { >+ assert(bigEndian(dv, 0) === 0xf0d0b0a0); >+ assert(littleEndian(dv, 0) === 0xa0b0d0f0); >+ if (i % 2) >+ assert(biEndian(dv, 0, true) === 0xa0b0d0f0); >+ else >+ assert(biEndian(dv, 0, false) === 0xf0d0b0a0); >+ } >+} >+test4(); >Index: Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h >=================================================================== >--- Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (revision 234873) >+++ Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (working copy) >@@ -408,6 +408,23 @@ public: > m_assembler.popcnt_rr(src, dst); > } > >+ void byteSwap32(RegisterID dst) >+ { >+ m_assembler.bswapl_r(dst); >+ } >+ >+ void byteSwap16(RegisterID dst) >+ { >+ m_assembler.rolw_i8r(8, dst); >+ } >+ >+#if CPU(X86_64) >+ void byteSwap64(RegisterID dst) >+ { >+ m_assembler.bswapq_r(dst); >+ } >+#endif >+ > // Only used for testing purposes. > void illegalInstruction() > { >Index: Source/JavaScriptCore/assembler/X86Assembler.h >=================================================================== >--- Source/JavaScriptCore/assembler/X86Assembler.h (revision 234873) >+++ Source/JavaScriptCore/assembler/X86Assembler.h (working copy) >@@ -337,6 +337,7 @@ private: > OP2_XADDb = 0xC0, > OP2_XADD = 0xC1, > OP2_PEXTRW_GdUdIb = 0xC5, >+ OP2_BSWAP = 0xC8, > OP2_PSLLQ_UdqIb = 0x73, > OP2_PSRLQ_UdqIb = 0x73, > OP2_POR_VdqWdq = 0XEB, >@@ -1638,6 +1639,18 @@ public: > } > #endif > >+ void bswapl_r(RegisterID dst) >+ { >+ m_formatter.twoByteOp(OP2_BSWAP, dst); >+ } >+ >+#if CPU(X86_64) >+ void bswapq_r(RegisterID dst) >+ { >+ m_formatter.twoByteOp64(OP2_BSWAP, dst); >+ } >+#endif >+ > void tzcnt_rr(RegisterID src, RegisterID dst) > { > m_formatter.prefix(PRE_SSE_F3); >@@ -1701,6 +1714,18 @@ private: > m_formatter.immediate8(imm); > } > } >+ >+ template<GroupOpcodeID op> >+ void shiftInstruction16(int imm, RegisterID dst) >+ { >+ m_formatter.prefix(PRE_OPERAND_SIZE); >+ if (imm == 1) >+ m_formatter.oneByteOp(OP_GROUP2_Ev1, op, dst); >+ else { >+ m_formatter.oneByteOp(OP_GROUP2_EvIb, op, dst); >+ m_formatter.immediate8(imm); >+ } >+ } > public: > > void sarl_i8r(int imm, RegisterID dst) >@@ -1753,6 +1778,11 @@ public: > m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_ROL, dst); > } > >+ void rolw_i8r(int imm, RegisterID dst) >+ { >+ shiftInstruction16<GROUP2_OP_ROL>(imm, dst); >+ } >+ > #if CPU(X86_64) > private: > template<GroupOpcodeID op> >@@ -4333,6 +4363,14 @@ private: > writer.putByteUnchecked(opcode); > } > >+ void twoByteOp(TwoByteOpcodeID opcode, int reg) >+ { >+ SingleInstructionBufferWriter writer(m_buffer); >+ writer.emitRexIfNeeded(0, 0, reg); >+ writer.putByteUnchecked(OP_2BYTE_ESCAPE); >+ writer.putByteUnchecked(opcode + (reg & 7)); >+ } >+ > void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID rm) > { > SingleInstructionBufferWriter writer(m_buffer); >@@ -4506,6 +4544,14 @@ private: > writer.memoryModRMAddr(reg, address); > } > >+ void twoByteOp64(TwoByteOpcodeID opcode, int reg) >+ { >+ SingleInstructionBufferWriter writer(m_buffer); >+ writer.emitRexW(0, 0, reg); >+ writer.putByteUnchecked(OP_2BYTE_ESCAPE); >+ writer.putByteUnchecked(opcode + (reg & 7)); >+ } >+ > void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID rm) > { > SingleInstructionBufferWriter writer(m_buffer); >Index: Source/JavaScriptCore/bytecode/DataFormat.h >=================================================================== >--- Source/JavaScriptCore/bytecode/DataFormat.h (revision 234873) >+++ Source/JavaScriptCore/bytecode/DataFormat.h (working copy) >@@ -38,7 +38,7 @@ namespace JSC { > enum DataFormat { > DataFormatNone = 0, > DataFormatInt32 = 1, >- DataFormatInt52 = 2, // Int52's are left-shifted by 16 by default. >+ DataFormatInt52 = 2, // Int52's are left-shifted by 12 by default. > DataFormatStrictInt52 = 3, // "Strict" Int52 means it's not shifted. > DataFormatDouble = 4, > DataFormatBoolean = 5, >Index: Source/JavaScriptCore/bytecode/SpeculatedType.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/SpeculatedType.cpp (revision 234873) >+++ Source/JavaScriptCore/bytecode/SpeculatedType.cpp (working copy) >@@ -203,6 +203,11 @@ void dumpSpeculation(PrintStream& outStr > strOut.print("DerivedArray"); > else > isTop = false; >+ >+ if (value & SpecDataViewObject) >+ strOut.print("DataView"); >+ else >+ isTop = false; > } > > if ((value & SpecString) == SpecString) >@@ -432,6 +437,9 @@ SpeculatedType speculationFromClassInfo( > > if (classInfo == ProxyObject::info()) > return SpecProxyObject; >+ >+ if (classInfo == JSDataView::info()) >+ return SpecDataViewObject; > > if (classInfo->isSubClassOf(JSFunction::info())) { > if (classInfo == JSBoundFunction::info()) >@@ -559,6 +567,8 @@ SpeculatedType speculationFromJSType(JST > return SpecWeakMapObject; > case JSWeakSetType: > return SpecWeakSetObject; >+ case DataViewType: >+ return SpecDataViewObject; > default: > ASSERT_NOT_REACHED(); > } >@@ -750,6 +760,8 @@ SpeculatedType speculationFromString(con > return SpecProxyObject; > if (!strncmp(speculation, "SpecDerivedArray", strlen("SpecDerivedArray"))) > return SpecDerivedArray; >+ if (!strncmp(speculation, "SpecDataViewObject", strlen("SpecDataViewObject"))) >+ return SpecDataViewObject; > if (!strncmp(speculation, "SpecObjectOther", strlen("SpecObjectOther"))) > return SpecObjectOther; > if (!strncmp(speculation, "SpecObject", strlen("SpecObject"))) >Index: Source/JavaScriptCore/bytecode/SpeculatedType.h >=================================================================== >--- Source/JavaScriptCore/bytecode/SpeculatedType.h (revision 234873) >+++ Source/JavaScriptCore/bytecode/SpeculatedType.h (working copy) >@@ -65,7 +65,6 @@ static const SpeculatedType SpecWeakSetO > static const SpeculatedType SpecProxyObject = 1ull << 21; // It's definitely a Proxy object or one of its subclasses. > static const SpeculatedType SpecDerivedArray = 1ull << 22; // It's definitely a DerivedArray object. > static const SpeculatedType SpecObjectOther = 1ull << 23; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction. >-static const SpeculatedType SpecObject = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecWeakMapObject | SpecWeakSetObject | SpecProxyObject | SpecDerivedArray | SpecObjectOther; // Bitmask used for testing for any kind of object prediction. > static const SpeculatedType SpecStringIdent = 1ull << 24; // It's definitely a JSString, and it's an identifier. > static const SpeculatedType SpecStringVar = 1ull << 25; // It's definitely a JSString, and it's not an identifier. > static const SpeculatedType SpecString = SpecStringIdent | SpecStringVar; // It's definitely a JSString. >@@ -93,7 +92,9 @@ static const SpeculatedType SpecOther > static const SpeculatedType SpecMisc = SpecBoolean | SpecOther; // It's definitely either a boolean, Null, or Undefined. > static const SpeculatedType SpecEmpty = 1ull << 37; // It's definitely an empty value marker. > static const SpeculatedType SpecBigInt = 1ull << 38; // It's definitely a BigInt. >+static const SpeculatedType SpecDataViewObject = 1ull << 39; // It's definitely a JSDataView. > static const SpeculatedType SpecPrimitive = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc | SpecBigInt; // It's any non-Object JSValue. >+static const SpeculatedType SpecObject = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecWeakMapObject | SpecWeakSetObject | SpecProxyObject | SpecDerivedArray | SpecObjectOther | SpecDataViewObject; // Bitmask used for testing for any kind of object prediction. > static const SpeculatedType SpecCell = SpecObject | SpecString | SpecSymbol | SpecCellOther | SpecBigInt; // It's definitely a JSCell. > static const SpeculatedType SpecHeapTop = SpecCell | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN. > static const SpeculatedType SpecBytecodeTop = SpecHeapTop | SpecEmpty; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN. Corresponds to what could be found in a bytecode local. >Index: Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (working copy) >@@ -3770,9 +3770,29 @@ bool AbstractInterpreter<AbstractStateTy > filter(node->child1(), SpecCell); > break; > } >- >+ >+ case DataViewGetInt: { >+ DataViewData data = node->dataViewData(); >+ if (data.byteSize < 4) >+ setNonCellTypeForNode(node, SpecInt32Only); >+ else { >+ if (!(node->prediction() & ~SpecInt32Only)) >+ setNonCellTypeForNode(node, SpecInt32Only); >+ else >+ setNonCellTypeForNode(node, SpecBytecodeDouble); // OOPS: do int52 here. >+ } >+ break; >+ } >+ >+ case DataViewGetFloat: { >+ setNonCellTypeForNode(node, SpecFullDouble); > break; >+ } > >+ case DataViewSet: { >+ break; >+ } >+ > case Unreachable: > // It may be that during a previous run of AI we proved that something was unreachable, but > // during this run of AI we forget that it's unreachable. AI's proofs don't have to get >Index: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (working copy) >@@ -3079,6 +3079,176 @@ bool ByteCodeParser::handleIntrinsicCall > return true; > } > >+ case DataViewGetInt8: >+ case DataViewGetUint8: >+ case DataViewGetInt16: >+ case DataViewGetUint16: >+ case DataViewGetInt32: >+ case DataViewGetUint32: >+ case DataViewGetFloat32: >+ case DataViewGetFloat64: { >+#if CPU(BIG_ENDIAN) >+ return false; >+#endif >+ >+ if (argumentCountIncludingThis < 2) >+ return false; >+ if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType)) >+ return false; >+ >+ insertChecks(); >+ >+ uint8_t byteSize; >+ NodeType op = DataViewGetInt; >+ bool isSigned = false; >+ switch (intrinsic) { >+ case DataViewGetInt8: >+ isSigned = true; >+ FALLTHROUGH; >+ case DataViewGetUint8: >+ byteSize = 1; >+ break; >+ >+ case DataViewGetInt16: >+ isSigned = true; >+ FALLTHROUGH; >+ case DataViewGetUint16: >+ byteSize = 2; >+ break; >+ >+ case DataViewGetInt32: >+ isSigned = true; >+ FALLTHROUGH; >+ case DataViewGetUint32: >+ byteSize = 4; >+ break; >+ >+ case DataViewGetFloat32: >+ byteSize = 4; >+ op = DataViewGetFloat; >+ break; >+ case DataViewGetFloat64: >+ byteSize = 8; >+ op = DataViewGetFloat; >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ >+ TriState isLittleEndian = MixedTriState; >+ Node* littleEndianChild = nullptr; >+ if (byteSize > 1) { >+ if (argumentCountIncludingThis < 3) >+ isLittleEndian = FalseTriState; >+ else { >+ littleEndianChild = get(virtualRegisterForArgument(2, registerOffset)); >+ if (littleEndianChild->hasConstant()) { >+ JSValue constant = littleEndianChild->constant()->value(); >+ isLittleEndian = constant.pureToBoolean(); >+ if (isLittleEndian != MixedTriState) >+ littleEndianChild = nullptr; >+ } else >+ isLittleEndian = MixedTriState; >+ } >+ } >+ >+ DataViewData data { }; >+ data.isLittleEndian = isLittleEndian; >+ data.isSigned = isSigned; >+ data.byteSize = byteSize; >+ >+ set(VirtualRegister(resultOperand), >+ addToGraph(op, OpInfo(data.asQuadWord), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), littleEndianChild)); >+ return true; >+ } >+ >+ case DataViewSetInt8: >+ case DataViewSetUint8: >+ case DataViewSetInt16: >+ case DataViewSetUint16: >+ case DataViewSetInt32: >+ case DataViewSetUint32: >+ case DataViewSetFloat32: >+ case DataViewSetFloat64: { >+#if CPU(BIG_ENDIAN) >+ return false; >+#endif >+ if (argumentCountIncludingThis < 3) >+ return false; >+ if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType)) >+ return false; >+ >+ insertChecks(); >+ >+ uint8_t byteSize; >+ bool isFloatingPoint = false; >+ bool isSigned = false; >+ switch (intrinsic) { >+ case DataViewSetInt8: >+ isSigned = true; >+ FALLTHROUGH; >+ case DataViewSetUint8: >+ byteSize = 1; >+ break; >+ >+ case DataViewSetInt16: >+ isSigned = true; >+ FALLTHROUGH; >+ case DataViewSetUint16: >+ byteSize = 2; >+ break; >+ >+ case DataViewSetInt32: >+ isSigned = true; >+ FALLTHROUGH; >+ case DataViewSetUint32: >+ byteSize = 4; >+ break; >+ >+ case DataViewSetFloat32: >+ isFloatingPoint = true; >+ byteSize = 4; >+ break; >+ case DataViewSetFloat64: >+ isFloatingPoint = true; >+ byteSize = 8; >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ >+ TriState isLittleEndian = MixedTriState; >+ Node* littleEndianChild = nullptr; >+ if (byteSize > 1) { >+ if (argumentCountIncludingThis < 4) >+ isLittleEndian = FalseTriState; >+ else { >+ littleEndianChild = get(virtualRegisterForArgument(3, registerOffset)); >+ if (littleEndianChild->hasConstant()) { >+ JSValue constant = littleEndianChild->constant()->value(); >+ isLittleEndian = constant.pureToBoolean(); >+ if (isLittleEndian != MixedTriState) >+ littleEndianChild = nullptr; >+ } else >+ isLittleEndian = MixedTriState; >+ } >+ } >+ >+ DataViewData data { }; >+ data.isLittleEndian = isLittleEndian; >+ data.isSigned = isSigned; >+ data.byteSize = byteSize; >+ data.isFloatingPoint = isFloatingPoint; >+ >+ addVarArgChild(get(virtualRegisterForArgument(0, registerOffset))); >+ addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); >+ addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); >+ addVarArgChild(littleEndianChild); >+ >+ addToGraph(Node::VarArg, DataViewSet, OpInfo(data.asQuadWord), OpInfo()); >+ return true; >+ } >+ > case HasOwnPropertyIntrinsic: { > if (argumentCountIncludingThis != 2) > return false; >Index: Source/JavaScriptCore/dfg/DFGClobberize.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGClobberize.h (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGClobberize.h (working copy) >@@ -1758,7 +1758,21 @@ void clobberize(Graph& graph, Node* node > case NumberToStringWithValidRadixConstant: > def(PureValue(node, node->validRadixConstant())); > return; >- >+ >+ case DataViewGetFloat: >+ case DataViewGetInt: { >+ read(MiscFields); >+ read(TypedArrayProperties); >+ return; >+ } >+ >+ case DataViewSet: { >+ read(MiscFields); >+ read(TypedArrayProperties); >+ write(TypedArrayProperties); >+ return; >+ } >+ > case LastNodeType: > RELEASE_ASSERT_NOT_REACHED(); > return; >Index: Source/JavaScriptCore/dfg/DFGDoesGC.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGDoesGC.cpp (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGDoesGC.cpp (working copy) >@@ -318,6 +318,9 @@ bool doesGC(Graph& graph, Node* node) > case FilterGetByIdStatus: > case FilterPutByIdStatus: > case FilterInByIdStatus: >+ case DataViewGetInt: >+ case DataViewGetFloat: >+ case DataViewSet: > return false; > > case PushWithScope: >Index: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (working copy) >@@ -2104,6 +2104,42 @@ private: > fixEdge<CellUse>(node->child1()); > break; > >+ case DataViewGetInt: >+ case DataViewGetFloat: { >+ fixEdge<DataViewObjectUse>(node->child1()); >+ fixEdge<Int32Use>(node->child2()); >+ if (node->child3()) >+ fixEdge<BooleanUse>(node->child3()); >+ break; >+ } >+ >+ case DataViewSet: { >+ DataViewData data = node->dataViewData(); >+ fixEdge<DataViewObjectUse>(m_graph.varArgChild(node, 0)); >+ fixEdge<Int32Use>(m_graph.varArgChild(node, 1)); >+ if (m_graph.varArgChild(node, 3)) >+ fixEdge<BooleanUse>(m_graph.varArgChild(node, 3)); >+ >+ Edge& valueToStore = m_graph.varArgChild(node, 2); >+ if (data.isFloatingPoint) >+ fixEdge<DoubleRepUse>(valueToStore); >+ else { >+ switch (data.byteSize) { >+ case 1: >+ case 2: >+ fixEdge<Int32Use>(valueToStore); >+ break; >+ case 4: >+ if (data.isSigned) >+ fixEdge<Int32Use>(valueToStore); >+ else >+ fixEdge<Int52RepUse>(valueToStore); >+ break; >+ } >+ } >+ break; >+ } >+ > #if !ASSERT_DISABLED > // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes. > case SetArgument: >Index: Source/JavaScriptCore/dfg/DFGNode.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNode.h (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGNode.h (working copy) >@@ -117,6 +117,19 @@ struct NewArrayBufferData { > static_assert(sizeof(IndexingType) <= sizeof(unsigned), ""); > static_assert(sizeof(NewArrayBufferData) == sizeof(uint64_t), ""); > >+struct DataViewData { >+ union { >+ struct { >+ uint8_t byteSize; >+ bool isSigned; >+ bool isFloatingPoint; // Used for the DataViewSet node. >+ TriState isLittleEndian; >+ }; >+ uint64_t asQuadWord; >+ }; >+}; >+static_assert(sizeof(DataViewData) == sizeof(uint64_t), ""); >+ > struct BranchTarget { > BranchTarget() > : block(0) >@@ -1659,6 +1672,8 @@ public: > case GetDynamicVar: > case ExtractValueFromWeakMapGet: > case ToThis: >+ case DataViewGetInt: >+ case DataViewGetFloat: > return true; > default: > return false; >@@ -2143,6 +2158,12 @@ public: > return m_opInfo.as<unsigned>(); > } > >+ DataViewData dataViewData() >+ { >+ ASSERT(op() == DataViewGetInt || op() == DataViewGetFloat || op() == DataViewSet); >+ return bitwise_cast<DataViewData>(m_opInfo.as<uint64_t>()); >+ } >+ > bool shouldGenerate() > { > return m_refCount; >Index: Source/JavaScriptCore/dfg/DFGNodeType.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNodeType.h (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGNodeType.h (working copy) >@@ -483,6 +483,10 @@ namespace JSC { namespace DFG { > macro(FilterGetByIdStatus, NodeMustGenerate) \ > macro(FilterInByIdStatus, NodeMustGenerate) \ > macro(FilterPutByIdStatus, NodeMustGenerate) \ >+ /* Data view access */ \ >+ macro(DataViewGetInt, NodeMustGenerate | NodeResultJS) /* The gets are must generate for now because they do bounds checks */ \ >+ macro(DataViewGetFloat, NodeMustGenerate | NodeResultDouble) \ >+ macro(DataViewSet, NodeMustGenerate | NodeMustGenerate | NodeHasVarArgs) \ > > > // This enum generates a monotonically increasing id for all Node types, >Index: Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (working copy) >@@ -621,7 +621,14 @@ private: > } > break; > } >- >+ >+ case DataViewSet: { >+ DataViewData data = node->dataViewData(); >+ if (data.isFloatingPoint) >+ m_graph.voteNode(m_graph.varArgChild(node, 2), VoteValue, weight); >+ break; >+ } >+ > case MovHint: > // Ignore these since they have no effect on in-DFG execution. > break; >@@ -750,7 +757,9 @@ private: > case CallDOMGetter: > case GetDynamicVar: > case GetPrototypeOf: >- case ExtractValueFromWeakMapGet: { >+ case ExtractValueFromWeakMapGet: >+ case DataViewGetInt: >+ case DataViewGetFloat: { > setPrediction(m_currentNode->getHeapPrediction()); > break; > } >@@ -1220,6 +1229,7 @@ private: > case FilterPutByIdStatus: > case FilterInByIdStatus: > case ClearCatchLocals: >+ case DataViewSet: > break; > > // This gets ignored because it only pretends to produce a value. >Index: Source/JavaScriptCore/dfg/DFGSafeToExecute.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSafeToExecute.h (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGSafeToExecute.h (working copy) >@@ -65,6 +65,7 @@ public: > case SetObjectUse: > case WeakMapObjectUse: > case WeakSetObjectUse: >+ case DataViewObjectUse: > case ObjectOrOtherUse: > case StringIdentUse: > case StringUse: >@@ -602,6 +603,13 @@ bool safeToExecute(AbstractStateType& st > return true; > } > >+ case DataViewGetInt: >+ case DataViewGetFloat: >+ return false; // OOPS: can we always do this or just sometimes? >+ >+ case DataViewSet: >+ return false; >+ > case SetAdd: > case MapSet: > return false; >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (working copy) >@@ -4553,6 +4553,386 @@ void SpeculativeJIT::compile(Node* node) > compileClearCatchLocals(node); > break; > >+ case DataViewGetFloat: >+ case DataViewGetInt: { >+ SpeculateCellOperand dataView(this, node->child1()); >+ GPRReg dataViewGPR = dataView.gpr(); >+ speculateDataViewObject(node->child1(), dataViewGPR); >+ >+ SpeculateInt32Operand index(this, node->child2()); >+ GPRReg indexGPR = index.gpr(); >+ >+ GPRTemporary temp1(this); >+ GPRReg t1 = temp1.gpr(); >+ GPRTemporary temp2(this); >+ GPRReg t2 = temp2.gpr(); >+ >+ std::optional<SpeculateBooleanOperand> isLittleEndianOperand; >+ if (node->child3()) >+ isLittleEndianOperand.emplace(this, node->child3()); >+ GPRReg isLittleEndianGPR = isLittleEndianOperand ? isLittleEndianOperand->gpr() : InvalidGPRReg; >+ >+ DataViewData data = node->dataViewData(); >+ >+ m_jit.zeroExtend32ToPtr(indexGPR, t2); >+ if (data.byteSize > 1) >+ m_jit.add64(TrustedImm32(data.byteSize - 1), t2); >+ m_jit.load32(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1); >+ // OOPS: does load32 already zero extend? >+ m_jit.zeroExtend32ToPtr(t1, t1); >+ // OOPS: Comment on why this works for negatives, etc. >+ speculationCheck(OutOfBounds, JSValueRegs(), node, >+ m_jit.branch32(MacroAssembler::AboveOrEqual, t2, t1)); >+ >+ m_jit.loadPtr(JITCompiler::Address(dataViewGPR, JSArrayBufferView::offsetOfVector()), t2); >+ speculationCheck(Uncountable, JSValueSource(), node, m_jit.branchTestPtr(MacroAssembler::Zero, t2)); // OOPS: add test. Can we neuter a JSDataView? >+ >+ m_jit.zeroExtend32ToPtr(indexGPR, t1); >+ auto baseIndex = JITCompiler::BaseIndex(t2, t1, MacroAssembler::TimesOne); >+ >+ // OOPS: do pointer caging >+ if (node->op() == DataViewGetInt) { >+ switch (data.byteSize) { >+ case 1: >+ if (data.isSigned) >+ m_jit.load8SignedExtendTo32(baseIndex, t2); >+ else >+ m_jit.load8(baseIndex, t2); >+ int32Result(t2, node); >+ break; >+ case 2: { >+ auto emitLittleEndianLoad = [&] { >+ if (data.isSigned) >+ m_jit.load16SignedExtendTo32(baseIndex, t2); >+ else >+ m_jit.load16(baseIndex, t2); >+ }; >+ auto emitBigEndianLoad = [&] { >+ m_jit.load16(baseIndex, t2); >+ m_jit.byteSwap16(t2); >+ if (data.isSigned) >+ m_jit.signExtend16To32(t2, t2); >+ }; >+ >+ if (data.isLittleEndian == FalseTriState) >+ emitBigEndianLoad(); >+ else if (data.isLittleEndian == TrueTriState) >+ emitLittleEndianLoad(); >+ else { >+ RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg); >+ auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1)); >+ emitLittleEndianLoad(); >+ auto done = m_jit.jump(); >+ isBigEndian.link(&m_jit); >+ emitBigEndianLoad(); >+ done.link(&m_jit); >+ } >+ int32Result(t2, node); >+ break; >+ } >+ case 4: { >+ m_jit.load32(baseIndex, t2); >+ >+ if (data.isLittleEndian == FalseTriState) >+ m_jit.byteSwap32(t2); >+ else if (data.isLittleEndian == MixedTriState) { >+ RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg); >+ auto isLittleEndian = m_jit.branchTest32(MacroAssembler::NonZero, isLittleEndianGPR, TrustedImm32(1)); >+ m_jit.byteSwap32(t2); >+ isLittleEndian.link(&m_jit); >+ } >+ >+ if (data.isSigned) >+ int32Result(t2, node); >+ else { >+ bool resultIsInt32 = !(node->prediction() & ~SpecInt32Only); >+ if (resultIsInt32) { >+ speculationCheck(Uncountable, JSValueSource(), node, m_jit.branch32(MacroAssembler::LessThan, t2, TrustedImm32(0))); >+ int32Result(t2, node); >+ } else { >+ // OOPS: Do I need this given above? >+ m_jit.zeroExtend32ToPtr(t2, t2); >+ >+ FPRTemporary fpTemp(this); >+ m_jit.convertInt64ToDouble(t2, fpTemp.fpr()); >+ m_jit.boxDouble(fpTemp.fpr(), t2); >+ jsValueResult(t2, node); >+ } >+ } >+ >+ break; >+ } >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ } else { >+ FPRTemporary result(this); >+ FPRReg resultFPR = result.fpr(); >+ >+ switch (data.byteSize) { >+ case 4: { >+ auto emitLittleEndianCode = [&] { >+ m_jit.loadFloat(baseIndex, resultFPR); >+ m_jit.convertFloatToDouble(resultFPR, resultFPR); >+ }; >+ >+ auto emitBigEndianCode = [&] { >+ m_jit.load32(baseIndex, t2); >+ m_jit.byteSwap32(t2); >+ m_jit.move32ToFloat(t2, resultFPR); >+ m_jit.convertFloatToDouble(resultFPR, resultFPR); >+ }; >+ >+ if (data.isLittleEndian == TrueTriState) >+ emitLittleEndianCode(); >+ else if (data.isLittleEndian == FalseTriState) >+ emitBigEndianCode(); >+ else { >+ RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg); >+ auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1)); >+ emitLittleEndianCode(); >+ auto done = m_jit.jump(); >+ isBigEndian.link(&m_jit); >+ emitBigEndianCode(); >+ done.link(&m_jit); >+ } >+ >+ break; >+ } >+ case 8: { >+ auto emitLittleEndianCode = [&] { >+ m_jit.loadDouble(baseIndex, resultFPR); >+ }; >+ >+ auto emitBigEndianCode = [&] { >+ m_jit.load64(baseIndex, t2); >+ m_jit.byteSwap64(t2); >+ m_jit.move64ToDouble(t2, resultFPR); >+ }; >+ >+ if (data.isLittleEndian == TrueTriState) >+ emitLittleEndianCode(); >+ else if (data.isLittleEndian == FalseTriState) >+ emitBigEndianCode(); >+ else { >+ RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg); >+ auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1)); >+ emitLittleEndianCode(); >+ auto done = m_jit.jump(); >+ isBigEndian.link(&m_jit); >+ emitBigEndianCode(); >+ done.link(&m_jit); >+ } >+ >+ break; >+ } >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ >+ doubleResult(resultFPR, node); >+ } >+ >+ break; >+ } >+ >+ case DataViewSet: { >+ SpeculateCellOperand dataView(this, m_graph.varArgChild(node, 0)); >+ GPRReg dataViewGPR = dataView.gpr(); >+ speculateDataViewObject(m_graph.varArgChild(node, 0), dataViewGPR); >+ >+ SpeculateInt32Operand index(this, m_graph.varArgChild(node, 1)); >+ GPRReg indexGPR = index.gpr(); >+ >+ std::optional<SpeculateStrictInt52Operand> int52Value; >+ std::optional<SpeculateDoubleOperand> doubleValue; >+ std::optional<SpeculateInt32Operand> int32Value; >+ std::optional<FPRTemporary> fprTemporary; >+ GPRReg valueGPR = InvalidGPRReg; >+ FPRReg valueFPR = InvalidFPRReg; >+ FPRReg tempFPR = InvalidFPRReg; >+ >+ DataViewData data = node->dataViewData(); >+ >+ Edge& valueEdge = m_graph.varArgChild(node, 2); >+ switch (valueEdge.useKind()) { >+ case Int32Use: >+ int32Value.emplace(this, valueEdge); >+ valueGPR = int32Value->gpr(); >+ break; >+ case DoubleRepUse: >+ doubleValue.emplace(this, valueEdge); >+ valueFPR = doubleValue->fpr(); >+ if (data.byteSize == 4) { >+ fprTemporary.emplace(this); >+ tempFPR = fprTemporary->fpr(); >+ } >+ break; >+ case Int52RepUse: >+ int52Value.emplace(this, valueEdge); >+ valueGPR = int52Value->gpr(); >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ >+ GPRTemporary temp1(this); >+ GPRReg t1 = temp1.gpr(); >+ GPRTemporary temp2(this); >+ GPRReg t2 = temp2.gpr(); >+ GPRTemporary temp3(this); >+ GPRReg t3 = temp3.gpr(); >+ >+ std::optional<SpeculateBooleanOperand> isLittleEndianOperand; >+ if (node->child3()) >+ isLittleEndianOperand.emplace(this, node->child3()); >+ GPRReg isLittleEndianGPR = isLittleEndianOperand ? isLittleEndianOperand->gpr() : InvalidGPRReg; >+ >+ m_jit.zeroExtend32ToPtr(indexGPR, t2); >+ if (data.byteSize > 1) >+ m_jit.add64(TrustedImm32(data.byteSize - 1), t2); >+ m_jit.load32(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1); >+ // OOPS: does load32 already zero extend? >+ m_jit.zeroExtend32ToPtr(t1, t1); >+ // OOPS: Comment on why this works for negatives, etc. >+ speculationCheck(OutOfBounds, JSValueRegs(), node, >+ m_jit.branch32(MacroAssembler::AboveOrEqual, t2, t1)); >+ >+ m_jit.loadPtr(JITCompiler::Address(dataViewGPR, JSArrayBufferView::offsetOfVector()), t2); >+ speculationCheck(Uncountable, JSValueSource(), node, m_jit.branchTestPtr(MacroAssembler::Zero, t2)); // OOPS: add test. Can we neuter a JSDataView? >+ >+ m_jit.zeroExtend32ToPtr(indexGPR, t1); >+ auto baseIndex = JITCompiler::BaseIndex(t2, t1, MacroAssembler::TimesOne); >+ >+ // OOPS: do pointer caging >+ if (data.isFloatingPoint) { >+ RELEASE_ASSERT(valueFPR != InvalidFPRReg); >+ RELEASE_ASSERT(tempFPR != InvalidFPRReg); >+ if (data.byteSize == 4) { >+ m_jit.convertDoubleToFloat(valueFPR, tempFPR); >+ >+ auto emitLittleEndianCode = [&] { >+ m_jit.storeFloat(tempFPR, baseIndex); >+ }; >+ >+ auto emitBigEndianCode = [&] { >+ m_jit.moveFloatTo32(tempFPR, t3); >+ m_jit.byteSwap32(t3); >+ m_jit.store32(t3, baseIndex); >+ }; >+ >+ if (data.isLittleEndian == FalseTriState) >+ emitBigEndianCode(); >+ else if (data.isLittleEndian == TrueTriState) >+ emitLittleEndianCode(); >+ else { >+ RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg); >+ auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1)); >+ emitLittleEndianCode(); >+ auto done = m_jit.jump(); >+ isBigEndian.link(&m_jit); >+ emitBigEndianCode(); >+ done.link(&m_jit); >+ } >+ } else { >+ RELEASE_ASSERT(data.byteSize == 8); >+ RELEASE_ASSERT(valueFPR != InvalidFPRReg); >+ >+ auto emitLittleEndianCode = [&] { >+ m_jit.storeDouble(valueFPR, baseIndex); >+ }; >+ auto emitBigEndianCode = [&] { >+ m_jit.moveDoubleTo64(valueFPR, t3); >+ m_jit.byteSwap32(t3); >+ m_jit.store64(t3, baseIndex); >+ }; >+ >+ if (data.isLittleEndian == FalseTriState) >+ emitBigEndianCode(); >+ else if (data.isLittleEndian == TrueTriState) >+ emitLittleEndianCode(); >+ else { >+ RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg); >+ auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1)); >+ emitLittleEndianCode(); >+ auto done = m_jit.jump(); >+ isBigEndian.link(&m_jit); >+ emitBigEndianCode(); >+ done.link(&m_jit); >+ } >+ } >+ } else { >+ switch (data.byteSize) { >+ case 1: >+ RELEASE_ASSERT(valueEdge.useKind() == Int32Use); >+ RELEASE_ASSERT(valueGPR != InvalidGPRReg); >+ m_jit.store8(valueGPR, baseIndex); >+ break; >+ case 2: { >+ RELEASE_ASSERT(valueEdge.useKind() == Int32Use); >+ RELEASE_ASSERT(valueGPR != InvalidGPRReg); >+ >+ auto emitLittleEndianCode = [&] { >+ m_jit.store16(valueGPR, baseIndex); >+ }; >+ auto emitBigEndianCode = [&] { >+ m_jit.move(valueGPR, t3); >+ m_jit.byteSwap16(t3); >+ m_jit.store16(t3, baseIndex); >+ }; >+ >+ if (data.isLittleEndian == FalseTriState) >+ emitBigEndianCode(); >+ else if (data.isLittleEndian == TrueTriState) >+ emitLittleEndianCode(); >+ else { >+ RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg); >+ auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1)); >+ emitLittleEndianCode(); >+ auto done = m_jit.jump(); >+ isBigEndian.link(&m_jit); >+ emitBigEndianCode(); >+ done.link(&m_jit); >+ } >+ break; >+ } >+ case 4: { >+ RELEASE_ASSERT(valueEdge.useKind() == Int32Use || valueEdge.useKind() == Int52RepUse); >+ >+ auto emitLittleEndianCode = [&] { >+ m_jit.store32(valueGPR, baseIndex); >+ }; >+ auto emitBigEndianCode = [&] { >+ m_jit.zeroExtend32ToPtr(valueGPR, t3); >+ m_jit.byteSwap32(t3); >+ m_jit.store32(valueGPR, baseIndex); >+ >+ }; >+ >+ if (data.isLittleEndian == FalseTriState) >+ emitBigEndianCode(); >+ else if (data.isLittleEndian == TrueTriState) >+ emitLittleEndianCode(); >+ else { >+ RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg); >+ auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1)); >+ emitLittleEndianCode(); >+ auto done = m_jit.jump(); >+ isBigEndian.link(&m_jit); >+ emitBigEndianCode(); >+ done.link(&m_jit); >+ } >+ >+ break; >+ } >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ } >+ >+ break; >+ } >+ > #if ENABLE(FTL_JIT) > case CheckTierUpInLoop: { > MacroAssembler::Jump callTierUp = m_jit.branchAdd32( >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (working copy) >@@ -9903,6 +9903,20 @@ void SpeculativeJIT::speculateWeakSetObj > speculateWeakSetObject(edge, operand.gpr()); > } > >+void SpeculativeJIT::speculateDataViewObject(Edge edge, GPRReg cell) >+{ >+ speculateCellType(edge, cell, SpecDataViewObject, DataViewType); >+} >+ >+void SpeculativeJIT::speculateDataViewObject(Edge edge) >+{ >+ if (!needsTypeCheck(edge, SpecDataViewObject)) >+ return; >+ >+ SpeculateCellOperand operand(this, edge); >+ speculateDataViewObject(edge, operand.gpr()); >+} >+ > void SpeculativeJIT::speculateObjectOrOther(Edge edge) > { > if (!needsTypeCheck(edge, SpecObject | SpecOther)) >@@ -10271,6 +10285,9 @@ void SpeculativeJIT::speculate(Node*, Ed > case WeakSetObjectUse: > speculateWeakSetObject(edge); > break; >+ case DataViewObjectUse: >+ speculateDataViewObject(edge); >+ break; > case ObjectOrOtherUse: > speculateObjectOrOther(edge); > break; >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (working copy) >@@ -1610,6 +1610,8 @@ public: > void speculateWeakMapObject(Edge, GPRReg cell); > void speculateWeakSetObject(Edge); > void speculateWeakSetObject(Edge, GPRReg cell); >+ void speculateDataViewObject(Edge); >+ void speculateDataViewObject(Edge, GPRReg cell); > void speculateObjectOrOther(Edge); > void speculateString(Edge edge, GPRReg cell); > void speculateStringIdentAndLoadStorage(Edge edge, GPRReg string, GPRReg storage); >Index: Source/JavaScriptCore/dfg/DFGUseKind.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGUseKind.cpp (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGUseKind.cpp (working copy) >@@ -104,16 +104,19 @@ void printInternal(PrintStream& out, Use > out.print("DerivedArray"); > return; > case MapObjectUse: >- out.print("MapObjectUse"); >+ out.print("MapObject"); > return; > case SetObjectUse: >- out.print("SetObjectUse"); >+ out.print("SetObject"); > return; > case WeakMapObjectUse: >- out.print("WeakMapObjectUse"); >+ out.print("WeakMapObject"); > return; > case WeakSetObjectUse: >- out.print("WeakSetObjectUse"); >+ out.print("WeakSetObject"); >+ return; >+ case DataViewObjectUse: >+ out.print("DataViewObject"); > return; > case ObjectOrOtherUse: > out.print("ObjectOrOther"); >Index: Source/JavaScriptCore/dfg/DFGUseKind.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGUseKind.h (revision 234873) >+++ Source/JavaScriptCore/dfg/DFGUseKind.h (working copy) >@@ -70,6 +70,7 @@ enum UseKind { > SetObjectUse, > WeakMapObjectUse, > WeakSetObjectUse, >+ DataViewObjectUse, > StringObjectUse, > StringOrStringObjectUse, > NotStringVarUse, >@@ -160,6 +161,8 @@ inline SpeculatedType typeFilterFor(UseK > return SpecWeakMapObject; > case WeakSetObjectUse: > return SpecWeakSetObject; >+ case DataViewObjectUse: >+ return SpecDataViewObject; > case StringObjectUse: > return SpecStringObject; > case StringOrStringObjectUse: >@@ -259,6 +262,7 @@ inline bool isCell(UseKind kind) > case SetObjectUse: > case WeakMapObjectUse: > case WeakSetObjectUse: >+ case DataViewObjectUse: > return true; > default: > return false; >Index: Source/JavaScriptCore/ftl/FTLCapabilities.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLCapabilities.cpp (revision 234873) >+++ Source/JavaScriptCore/ftl/FTLCapabilities.cpp (working copy) >@@ -359,6 +359,9 @@ inline CapabilityLevel canCompile(Node* > case FilterPutByIdStatus: > case FilterInByIdStatus: > case CreateThis: >+ case DataViewGetInt: >+ case DataViewGetFloat: >+ case DataViewSet: > // These are OK. > break; > >@@ -445,6 +448,7 @@ CapabilityLevel canCompile(Graph& graph) > case SetObjectUse: > case WeakMapObjectUse: > case WeakSetObjectUse: >+ case DataViewObjectUse: > case FinalObjectUse: > case RegExpObjectUse: > case ProxyObjectUse: >Index: Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (revision 234873) >+++ Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (working copy) >@@ -1307,6 +1307,13 @@ private: > case FilterInByIdStatus: > compileFilterICStatus(); > break; >+ case DataViewGetInt: >+ case DataViewGetFloat: >+ compileDataViewGet(); >+ break; >+ case DataViewSet: >+ compileDataViewSet(); >+ break; > > case PhantomLocal: > case LoopHint: >@@ -12238,6 +12245,364 @@ private: > { > m_interpreter.filterICStatus(m_node); > } >+ >+ LValue byteSwap32(LValue value) >+ { >+ RELEASE_ASSERT(value->type() == Int32); >+ PatchpointValue* patchpoint = m_out.patchpoint(Int32); >+ patchpoint->appendSomeRegister(value); >+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { >+ jit.move(params[1].gpr(), params[0].gpr()); >+ jit.byteSwap32(params[0].gpr()); >+ }); >+ patchpoint->effects = Effects::none(); >+ return patchpoint; >+ } >+ >+ LValue byteSwap64(LValue value) >+ { >+ RELEASE_ASSERT(value->type() == Int64); >+ PatchpointValue* patchpoint = m_out.patchpoint(Int64); >+ patchpoint->appendSomeRegister(value); >+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { >+ jit.move(params[1].gpr(), params[0].gpr()); >+ jit.byteSwap64(params[0].gpr()); >+ }); >+ patchpoint->effects = Effects::none(); >+ return patchpoint; >+ } >+ >+ template <typename F1, typename F2> >+ LValue emitBranchOnEndiannessCode(LValue isLittleEndian, const F1& emitLittleEndianCode, const F2& emitBigEndianCode) >+ { >+ LType type; >+ >+ LBasicBlock bigEndianCase = m_out.newBlock(); >+ LBasicBlock littleEndianCase = m_out.newBlock(); >+ LBasicBlock continuation = m_out.newBlock(); >+ >+ m_out.branch(m_out.testIsZero32(isLittleEndian, m_out.constInt32(1)), >+ unsure(bigEndianCase), unsure(littleEndianCase)); >+ >+ LBasicBlock lastNext = m_out.appendTo(bigEndianCase, littleEndianCase); >+ LValue bigEndianValue = emitBigEndianCode(); >+ type = bigEndianValue ? bigEndianValue->type() : Void; >+ ValueFromBlock bigEndianResult = bigEndianValue ? m_out.anchor(bigEndianValue) : ValueFromBlock(); >+ m_out.jump(continuation); >+ >+ m_out.appendTo(littleEndianCase, continuation); >+ LValue littleEndianValue = emitLittleEndianCode(); >+ ValueFromBlock littleEndianResult = littleEndianValue ? m_out.anchor(littleEndianValue) : ValueFromBlock(); >+ RELEASE_ASSERT((!littleEndianValue && !bigEndianValue) || type == littleEndianValue->type()); >+ m_out.jump(continuation); >+ >+ m_out.appendTo(continuation, lastNext); >+ RELEASE_ASSERT(!!bigEndianResult == !!littleEndianResult); >+ if (bigEndianResult) >+ return m_out.phi(type, bigEndianResult, littleEndianResult); >+ return nullptr; >+ } >+ >+ void compileDataViewGet() >+ { >+ LValue dataView = lowDataViewObject(m_node->child1()); >+ LValue index = lowInt32(m_node->child2()); >+ LValue isLittleEndian = nullptr; >+ if (m_node->child3()) >+ isLittleEndian = lowBoolean(m_node->child3()); >+ >+ DataViewData data = m_node->dataViewData(); >+ >+ LValue length = m_out.zeroExtPtr(m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length)); >+ LValue indexToCheck = m_out.zeroExtPtr(index); >+ if (data.byteSize > 1) >+ indexToCheck = m_out.add(indexToCheck, m_out.constInt64(data.byteSize - 1)); >+ speculate(OutOfBounds, noValue(), nullptr, m_out.aboveOrEqual(indexToCheck, length)); >+ >+ LValue vector = m_out.loadPtr(dataView, m_heaps.JSArrayBufferView_vector); >+ >+ // OOPS: add neutering tests for JSDataView. We don't explicitly need to check for nullptr since our bounds check will fail. >+ >+ TypedPointer pointer(m_heaps.typedArrayProperties, m_out.add(vector, m_out.zeroExtPtr(index))); >+ >+ if (m_node->op() == DataViewGetInt) { >+ switch (data.byteSize) { >+ case 1: >+ if (data.isSigned) >+ setInt32(m_out.load8SignExt32(pointer)); >+ else >+ setInt32(m_out.load8ZeroExt32(pointer)); >+ break; >+ case 2: { >+ auto emitLittleEndianLoad = [&] { >+ if (data.isSigned) >+ return m_out.load16SignExt32(pointer); >+ return m_out.load16ZeroExt32(pointer); >+ }; >+ >+ auto emitBigEndianLoad = [&] { >+ LValue val = m_out.load16ZeroExt32(pointer); >+ >+ // OOPS: teach b3 byte swap! >+ PatchpointValue* patchpoint = m_out.patchpoint(Int32); >+ patchpoint->appendSomeRegister(val); >+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { >+ jit.move(params[1].gpr(), params[0].gpr()); >+ jit.byteSwap16(params[0].gpr()); >+ if (data.isSigned) >+ jit.signExtend16To32(params[0].gpr(), params[0].gpr()); >+ }); >+ patchpoint->effects = Effects::none(); >+ >+ return patchpoint; >+ }; >+ >+ if (data.isLittleEndian == FalseTriState) >+ setInt32(emitBigEndianLoad()); >+ else if (data.isLittleEndian == TrueTriState) >+ setInt32(emitLittleEndianLoad()); >+ else >+ setInt32(emitBranchOnEndiannessCode(isLittleEndian, emitLittleEndianLoad, emitBigEndianLoad)); >+ >+ break; >+ } >+ case 4: { >+ LValue loadedValue = m_out.load32(pointer); >+ >+ if (data.isLittleEndian == FalseTriState) >+ loadedValue = byteSwap32(loadedValue); >+ else if (data.isLittleEndian == MixedTriState) { >+ auto emitLittleEndianCode = [&] { >+ return loadedValue; >+ }; >+ auto emitBigEndianCode = [&] { >+ return byteSwap32(loadedValue); >+ }; >+ >+ loadedValue = emitBranchOnEndiannessCode(isLittleEndian, emitLittleEndianCode, emitBigEndianCode); >+ } >+ >+ if (data.isSigned) >+ setInt32(loadedValue); >+ else { >+ bool resultIsInt32 = !(m_node->prediction() & ~SpecInt32Only); >+ if (resultIsInt32) { >+ speculate(Uncountable, noValue(), nullptr, m_out.lessThan(loadedValue, m_out.int32Zero)); >+ setInt32(loadedValue); >+ } else { >+ LValue doubleVal = m_out.intToDouble(m_out.zeroExt(loadedValue, Int64)); >+ doubleVal = boxDouble(doubleVal); >+ setJSValue(doubleVal); >+ } >+ } >+ >+ break; >+ } >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ } else { >+ switch (data.byteSize) { >+ case 4: { >+ auto emitLittleEndianCode = [&] { >+ return m_out.floatToDouble(m_out.loadFloat(pointer)); >+ }; >+ >+ auto emitBigEndianCode = [&] { >+ LValue loadedValue = m_out.load32(pointer); >+ PatchpointValue* patchpoint = m_out.patchpoint(Double); >+ patchpoint->appendSomeRegister(loadedValue); >+ patchpoint->numGPScratchRegisters = 1; >+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { >+ jit.move(params[1].gpr(), params.gpScratch(0)); >+ jit.byteSwap32(params.gpScratch(0)); >+ jit.move32ToFloat(params.gpScratch(0), params[0].fpr()); >+ jit.convertFloatToDouble(params[0].fpr(), params[0].fpr()); >+ }); >+ patchpoint->effects = Effects::none(); >+ return patchpoint; >+ }; >+ >+ if (data.isLittleEndian == TrueTriState) >+ setDouble(emitLittleEndianCode()); >+ else if (data.isLittleEndian == FalseTriState) >+ setDouble(emitBigEndianCode()); >+ else >+ setDouble(emitBranchOnEndiannessCode(isLittleEndian, emitLittleEndianCode, emitBigEndianCode)); >+ >+ break; >+ } >+ case 8: { >+ auto emitLittleEndianCode = [&] { >+ return m_out.loadDouble(pointer); >+ }; >+ >+ auto emitBigEndianCode = [&] { >+ LValue loadedValue = m_out.load64(pointer); >+ loadedValue = byteSwap64(loadedValue); >+ return m_out.bitCast(loadedValue, Double); >+ }; >+ >+ if (data.isLittleEndian == TrueTriState) >+ setDouble(emitLittleEndianCode()); >+ else if (data.isLittleEndian == FalseTriState) >+ setDouble(emitBigEndianCode()); >+ else >+ setDouble(emitBranchOnEndiannessCode(isLittleEndian, emitLittleEndianCode, emitBigEndianCode)); >+ >+ break; >+ } >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ } >+ } >+ >+ void compileDataViewSet() >+ { >+ LValue dataView = lowDataViewObject(m_graph.varArgChild(m_node, 0)); >+ LValue index = lowInt32(m_graph.varArgChild(m_node, 1)); >+ LValue isLittleEndian = nullptr; >+ if (m_graph.varArgChild(m_node, 3)) >+ isLittleEndian = lowBoolean(m_graph.varArgChild(m_node, 3)); >+ >+ DataViewData data = m_node->dataViewData(); >+ >+ LValue length = m_out.zeroExtPtr(m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length)); >+ LValue indexToCheck = m_out.zeroExtPtr(index); >+ if (data.byteSize > 1) >+ indexToCheck = m_out.add(indexToCheck, m_out.constInt64(data.byteSize - 1)); >+ // OOPS: add neutering tests for JSDataView. We don't explicitly need to check for nullptr since our bounds check will fail. >+ speculate(OutOfBounds, noValue(), nullptr, m_out.aboveOrEqual(indexToCheck, length)); >+ >+ Edge& valueEdge = m_graph.varArgChild(m_node, 2); >+ LValue valueToStore; >+ switch (valueEdge.useKind()) { >+ case Int32Use: >+ valueToStore = lowInt32(valueEdge); >+ break; >+ case DoubleRepUse: >+ valueToStore = lowDouble(valueEdge); >+ break; >+ case Int52RepUse: >+ valueToStore = lowStrictInt52(valueEdge); >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ >+ LValue vector = m_out.loadPtr(dataView, m_heaps.JSArrayBufferView_vector); >+ TypedPointer pointer(m_heaps.typedArrayProperties, m_out.add(vector, m_out.zeroExtPtr(index))); >+ >+ if (data.isFloatingPoint) { >+ if (data.byteSize == 4) { >+ valueToStore = m_out.doubleToFloat(valueToStore); >+ >+ auto emitLittleEndianCode = [&] () -> LValue { >+ m_out.storeFloat(valueToStore, pointer); >+ return nullptr; >+ }; >+ >+ auto emitBigEndianCode = [&] () -> LValue { >+ PatchpointValue* patchpoint = m_out.patchpoint(Int32); >+ patchpoint->appendSomeRegister(valueToStore); >+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { >+ jit.moveFloatTo32(params[1].fpr(), params[0].gpr()); >+ jit.byteSwap32(params[0].gpr()); >+ }); >+ patchpoint->effects = Effects::none(); >+ m_out.store32(patchpoint, pointer); >+ return nullptr; >+ }; >+ >+ if (data.isLittleEndian == FalseTriState) >+ emitBigEndianCode(); >+ else if (data.isLittleEndian == TrueTriState) >+ emitLittleEndianCode(); >+ else >+ emitBranchOnEndiannessCode(isLittleEndian, emitLittleEndianCode, emitBigEndianCode); >+ >+ } else { >+ RELEASE_ASSERT(data.byteSize == 8); >+ auto emitLittleEndianCode = [&] () -> LValue { >+ m_out.storeDouble(valueToStore, pointer); >+ return nullptr; >+ }; >+ auto emitBigEndianCode = [&] () -> LValue { >+ m_out.store64(byteSwap64(m_out.bitCast(valueToStore, Int64)), pointer); >+ return nullptr; >+ }; >+ >+ if (data.isLittleEndian == FalseTriState) >+ emitBigEndianCode(); >+ else if (data.isLittleEndian == TrueTriState) >+ emitLittleEndianCode(); >+ else >+ emitBranchOnEndiannessCode(isLittleEndian, emitLittleEndianCode, emitBigEndianCode); >+ } >+ } else { >+ switch (data.byteSize) { >+ case 1: >+ RELEASE_ASSERT(valueEdge.useKind() == Int32Use); >+ m_out.store32As8(valueToStore, pointer); >+ break; >+ case 2: { >+ RELEASE_ASSERT(valueEdge.useKind() == Int32Use); >+ >+ auto emitLittleEndianCode = [&] () -> LValue { >+ m_out.store32As16(valueToStore, pointer); >+ return nullptr; >+ }; >+ auto emitBigEndianCode = [&] () -> LValue { >+ PatchpointValue* patchpoint = m_out.patchpoint(Int32); >+ patchpoint->appendSomeRegister(valueToStore); >+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { >+ jit.move(params[1].gpr(), params[0].gpr()); >+ jit.byteSwap16(params[0].gpr()); >+ }); >+ patchpoint->effects = Effects::none(); >+ >+ m_out.store32As16(patchpoint, pointer); >+ return nullptr; >+ }; >+ >+ if (data.isLittleEndian == FalseTriState) >+ emitBigEndianCode(); >+ else if (data.isLittleEndian == TrueTriState) >+ emitLittleEndianCode(); >+ else >+ emitBranchOnEndiannessCode(isLittleEndian, emitLittleEndianCode, emitBigEndianCode); >+ break; >+ } >+ case 4: { >+ RELEASE_ASSERT(valueEdge.useKind() == Int32Use || valueEdge.useKind() == Int52RepUse); >+ >+ if (valueEdge.useKind() == Int52RepUse) >+ valueToStore = m_out.castToInt32(valueToStore); >+ >+ auto emitLittleEndianCode = [&] () -> LValue { >+ m_out.store32(valueToStore, pointer); >+ return nullptr; >+ }; >+ auto emitBigEndianCode = [&] () -> LValue { >+ m_out.store32(byteSwap32(valueToStore), pointer); >+ return nullptr; >+ }; >+ >+ if (data.isLittleEndian == FalseTriState) >+ emitBigEndianCode(); >+ else if (data.isLittleEndian == TrueTriState) >+ emitLittleEndianCode(); >+ else >+ emitBranchOnEndiannessCode(isLittleEndian, emitLittleEndianCode, emitBigEndianCode); >+ >+ break; >+ } >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ } >+ } >+ } > > void emitSwitchForMultiByOffset(LValue base, bool structuresChecked, Vector<SwitchCase, 2>& cases, LBasicBlock exit) > { >@@ -14468,6 +14833,13 @@ private: > speculateWeakSetObject(edge, result); > return result; > } >+ >+ LValue lowDataViewObject(Edge edge) >+ { >+ LValue result = lowCell(edge); >+ speculateDataViewObject(edge, result); >+ return result; >+ } > > LValue lowString(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) > { >@@ -14943,6 +15315,9 @@ private: > case WeakSetObjectUse: > speculateWeakSetObject(edge); > break; >+ case DataViewObjectUse: >+ speculateDataViewObject(edge); >+ break; > case StringUse: > speculateString(edge); > break; >@@ -15437,6 +15812,17 @@ private: > { > speculateWeakSetObject(edge, lowCell(edge)); > } >+ >+ void speculateDataViewObject(Edge edge, LValue cell) >+ { >+ FTL_TYPE_CHECK( >+ jsValueValue(cell), edge, SpecDataViewObject, isNotType(cell, DataViewType)); >+ } >+ >+ void speculateDataViewObject(Edge edge) >+ { >+ speculateDataViewObject(edge, lowCell(edge)); >+ } > > void speculateString(Edge edge, LValue cell) > { >Index: Source/JavaScriptCore/runtime/Intrinsic.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/Intrinsic.cpp (revision 234873) >+++ Source/JavaScriptCore/runtime/Intrinsic.cpp (working copy) >@@ -239,6 +239,38 @@ const char* intrinsicName(Intrinsic intr > return "CPUCpuidIntrinsic"; > case CPUPauseIntrinsic: > return "CPUPauseIntrinsic"; >+ case DataViewGetInt8: >+ return "DataViewGetInt8"; >+ case DataViewGetUint8: >+ return "DataViewGetUint8"; >+ case DataViewGetInt16: >+ return "DataViewGetInt16"; >+ case DataViewGetUint16: >+ return "DataViewGetUint16"; >+ case DataViewGetInt32: >+ return "DataViewGetInt32"; >+ case DataViewGetUint32: >+ return "DataViewGetUint32"; >+ case DataViewGetFloat32: >+ return "DataViewGetFloat32"; >+ case DataViewGetFloat64: >+ return "DataViewGetFloat64"; >+ case DataViewSetInt8: >+ return "DataViewSetInt8"; >+ case DataViewSetUint8: >+ return "DataViewSetUint8"; >+ case DataViewSetInt16: >+ return "DataViewSetInt16"; >+ case DataViewSetUint16: >+ return "DataViewSetUint16"; >+ case DataViewSetInt32: >+ return "DataViewSetInt32"; >+ case DataViewSetUint32: >+ return "DataViewSetUint32"; >+ case DataViewSetFloat32: >+ return "DataViewSetFloat32"; >+ case DataViewSetFloat64: >+ return "DataViewSetFloat64"; > } > RELEASE_ASSERT_NOT_REACHED(); > return nullptr; >Index: Source/JavaScriptCore/runtime/Intrinsic.h >=================================================================== >--- Source/JavaScriptCore/runtime/Intrinsic.h (revision 234873) >+++ Source/JavaScriptCore/runtime/Intrinsic.h (working copy) >@@ -139,6 +139,23 @@ enum Intrinsic { > CPURdtscIntrinsic, > CPUCpuidIntrinsic, > CPUPauseIntrinsic, >+ >+ DataViewGetInt8, >+ DataViewGetUint8, >+ DataViewGetInt16, >+ DataViewGetUint16, >+ DataViewGetInt32, >+ DataViewGetUint32, >+ DataViewGetFloat32, >+ DataViewGetFloat64, >+ DataViewSetInt8, >+ DataViewSetUint8, >+ DataViewSetInt16, >+ DataViewSetUint16, >+ DataViewSetInt32, >+ DataViewSetUint32, >+ DataViewSetFloat32, >+ DataViewSetFloat64, > }; > > const char* intrinsicName(Intrinsic); >Index: Source/JavaScriptCore/runtime/JSDataViewPrototype.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSDataViewPrototype.cpp (revision 234873) >+++ Source/JavaScriptCore/runtime/JSDataViewPrototype.cpp (working copy) >@@ -39,22 +39,22 @@ namespace JSC { > > /* Source for JSDataViewPrototype.lut.h > @begin dataViewTable >- getInt8 dataViewProtoFuncGetInt8 DontEnum|Function 1 >- getUint8 dataViewProtoFuncGetUint8 DontEnum|Function 1 >- getInt16 dataViewProtoFuncGetInt16 DontEnum|Function 1 >- getUint16 dataViewProtoFuncGetUint16 DontEnum|Function 1 >- getInt32 dataViewProtoFuncGetInt32 DontEnum|Function 1 >- getUint32 dataViewProtoFuncGetUint32 DontEnum|Function 1 >- getFloat32 dataViewProtoFuncGetFloat32 DontEnum|Function 1 >- getFloat64 dataViewProtoFuncGetFloat64 DontEnum|Function 1 >- setInt8 dataViewProtoFuncSetInt8 DontEnum|Function 2 >- setUint8 dataViewProtoFuncSetUint8 DontEnum|Function 2 >- setInt16 dataViewProtoFuncSetInt16 DontEnum|Function 2 >- setUint16 dataViewProtoFuncSetUint16 DontEnum|Function 2 >- setInt32 dataViewProtoFuncSetInt32 DontEnum|Function 2 >- setUint32 dataViewProtoFuncSetUint32 DontEnum|Function 2 >- setFloat32 dataViewProtoFuncSetFloat32 DontEnum|Function 2 >- setFloat64 dataViewProtoFuncSetFloat64 DontEnum|Function 2 >+ getInt8 dataViewProtoFuncGetInt8 DontEnum|Function 1 DataViewGetInt8 >+ getUint8 dataViewProtoFuncGetUint8 DontEnum|Function 1 DataViewGetUint8 >+ getInt16 dataViewProtoFuncGetInt16 DontEnum|Function 1 DataViewGetInt16 >+ getUint16 dataViewProtoFuncGetUint16 DontEnum|Function 1 DataViewGetUint16 >+ getInt32 dataViewProtoFuncGetInt32 DontEnum|Function 1 DataViewGetInt32 >+ getUint32 dataViewProtoFuncGetUint32 DontEnum|Function 1 DataViewGetUint32 >+ getFloat32 dataViewProtoFuncGetFloat32 DontEnum|Function 1 DataViewGetFloat32 >+ getFloat64 dataViewProtoFuncGetFloat64 DontEnum|Function 1 DataViewGetFloat64 >+ setInt8 dataViewProtoFuncSetInt8 DontEnum|Function 2 DataViewSetInt8 >+ setUint8 dataViewProtoFuncSetUint8 DontEnum|Function 2 DataViewSetUint8 >+ setInt16 dataViewProtoFuncSetInt16 DontEnum|Function 2 DataViewSetInt16 >+ setUint16 dataViewProtoFuncSetUint16 DontEnum|Function 2 DataViewSetUint16 >+ setInt32 dataViewProtoFuncSetInt32 DontEnum|Function 2 DataViewSetInt32 >+ setUint32 dataViewProtoFuncSetUint32 DontEnum|Function 2 DataViewSetUint32 >+ setFloat32 dataViewProtoFuncSetFloat32 DontEnum|Function 2 DataViewSetFloat32 >+ setFloat64 dataViewProtoFuncSetFloat64 DontEnum|Function 2 DataViewSetFloat64 > buffer dataViewProtoGetterBuffer DontEnum|Accessor 0 > byteLength dataViewProtoGetterByteLength DontEnum|Accessor 0 > byteOffset dataViewProtoGetterByteOffset DontEnum|Accessor 0 >Index: Source/WTF/wtf/TriState.h >=================================================================== >--- Source/WTF/wtf/TriState.h (revision 234873) >+++ Source/WTF/wtf/TriState.h (working copy) >@@ -28,7 +28,7 @@ > > namespace WTF { > >-enum TriState { >+enum TriState : int8_t { > FalseTriState, > TrueTriState, > MixedTriState
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188573
:
347152
|
347278
|
347290
|
347309
|
347334
|
347342
|
347354
|
347415
|
347465
|
347476
|
347484
|
347579