Changeset 185920 in webkit
- Timestamp:
- Jun 24, 2015 12:13:54 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r185918 r185920 1 2015-06-24 Keith Miller <keith_miller@apple.com> 2 3 Strict Equality on objects should only check that one of the two sides is an object. 4 https://bugs.webkit.org/show_bug.cgi?id=145992 5 6 Reviewed by Mark Lam. 7 8 Adds a test that checks if strict equality checks with objects properly exit out of DFG code when 9 dealing with document.all, which is an object that masquerades as undefined. 10 11 * js/dom/document-all-strict-eq-expected.txt: Added. 12 * js/dom/document-all-strict-eq.html: Added. 13 * js/dom/script-tests/document-all-strict-eq.js: Added. 14 (f): 15 1 16 2015-06-24 Myles C. Maxfield <mmaxfield@apple.com> 2 17 -
trunk/Source/JavaScriptCore/ChangeLog
r185909 r185920 1 2015-06-24 Keith Miller <keith_miller@apple.com> 2 3 Strict Equality on objects should only check that one of the two sides is an object. 4 https://bugs.webkit.org/show_bug.cgi?id=145992 5 6 This patch adds a new optimization for checking strict equality on objects. 7 If we speculate that a strict equality comparison has an object on one side 8 we only need to type check that side. Equality is then determined by a pointer 9 comparison between the two values (although in the 32-bit case we must also check 10 that the other side is a cell). Once LICM hoists type checks out of a loop we 11 can be cleverer about how we choose the operand we type check if both are 12 speculated to be objects. 13 14 For testing I added the addressOf function, which returns the address 15 of a Cell to the runtime. 16 17 Reviewed by Mark Lam. 18 19 * dfg/DFGFixupPhase.cpp: 20 (JSC::DFG::FixupPhase::fixupNode): 21 * dfg/DFGSpeculativeJIT.cpp: 22 (JSC::DFG::SpeculativeJIT::compileStrictEq): 23 * dfg/DFGSpeculativeJIT.h: 24 * dfg/DFGSpeculativeJIT32_64.cpp: 25 (JSC::DFG::SpeculativeJIT::compileObjectStrictEquality): 26 (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectStrictEquality): 27 * dfg/DFGSpeculativeJIT64.cpp: 28 (JSC::DFG::SpeculativeJIT::compileObjectStrictEquality): 29 (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectStrictEquality): 30 * ftl/FTLCapabilities.cpp: 31 (JSC::FTL::canCompile): 32 * ftl/FTLLowerDFGToLLVM.cpp: 33 (JSC::FTL::DFG::LowerDFGToLLVM::compileCompareStrictEq): 34 * jsc.cpp: 35 (GlobalObject::finishCreation): 36 (functionAddressOf): 37 * tests/stress/equality-type-checking.js: Added. 38 (Foo): 39 (checkStrictEq): 40 (checkStrictEqOther): 41 1 42 2015-06-24 Mark Lam <mark.lam@apple.com> 2 43 -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r185728 r185920 472 472 break; 473 473 } 474 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) { 474 WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint(); 475 if (masqueradesAsUndefinedWatchpoint->isStillValid()) { 476 477 if (node->child1()->shouldSpeculateObject()) { 478 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint); 479 fixEdge<ObjectUse>(node->child1()); 480 break; 481 } 482 if (node->child2()->shouldSpeculateObject()) { 483 m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint); 484 fixEdge<ObjectUse>(node->child2()); 485 break; 486 } 487 488 } else if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) { 475 489 fixEdge<ObjectUse>(node->child1()); 476 490 fixEdge<ObjectUse>(node->child2()); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r185267 r185920 3916 3916 } 3917 3917 3918 if (node->isBinaryUseKind(ObjectUse, UntypedUse)) { 3919 unsigned branchIndexInBlock = detectPeepHoleBranch(); 3920 if (branchIndexInBlock != UINT_MAX) { 3921 Node* branchNode = m_block->at(branchIndexInBlock); 3922 compilePeepHoleObjectStrictEquality(node->child1(), node->child2(), branchNode); 3923 use(node->child1()); 3924 use(node->child2()); 3925 m_indexInBlock = branchIndexInBlock; 3926 m_currentNode = branchNode; 3927 return true; 3928 } 3929 compileObjectStrictEquality(node->child1(), node->child2()); 3930 return false; 3931 } 3932 3933 if (node->isBinaryUseKind(UntypedUse, ObjectUse)) { 3934 unsigned branchIndexInBlock = detectPeepHoleBranch(); 3935 if (branchIndexInBlock != UINT_MAX) { 3936 Node* branchNode = m_block->at(branchIndexInBlock); 3937 compilePeepHoleObjectStrictEquality(node->child2(), node->child1(), branchNode); 3938 use(node->child1()); 3939 use(node->child2()); 3940 m_indexInBlock = branchIndexInBlock; 3941 m_currentNode = branchNode; 3942 return true; 3943 } 3944 compileObjectStrictEquality(node->child2(), node->child1()); 3945 return false; 3946 } 3947 3918 3948 if (node->isBinaryUseKind(ObjectUse)) { 3919 3949 unsigned branchIndexInBlock = detectPeepHoleBranch(); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r185239 r185920 2089 2089 void compilePeepHoleDoubleBranch(Node*, Node* branchNode, JITCompiler::DoubleCondition); 2090 2090 void compilePeepHoleObjectEquality(Node*, Node* branchNode); 2091 void compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode); 2091 2092 void compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode); 2092 2093 void compileObjectEquality(Node*); 2094 void compileObjectStrictEquality(Edge objectChild, Edge otherChild); 2093 2095 void compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild); 2094 2096 void compileObjectOrOtherLogicalNot(Edge value); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r184542 r185920 1183 1183 1184 1184 booleanResult(resultPayloadGPR, node); 1185 } 1186 1187 void SpeculativeJIT::compileObjectStrictEquality(Edge objectChild, Edge otherChild) 1188 { 1189 SpeculateCellOperand op1(this, objectChild); 1190 JSValueOperand op2(this, otherChild); 1191 1192 GPRReg op1GPR = op1.gpr(); 1193 GPRReg op2GPR = op2.payloadGPR(); 1194 1195 DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR)); 1196 1197 GPRTemporary resultPayload(this, Reuse, op1); 1198 GPRReg resultPayloadGPR = resultPayload.gpr(); 1199 1200 MacroAssembler::Jump op2CellJump = m_jit.branchIfCell(op2.jsValueRegs()); 1201 1202 m_jit.move(TrustedImm32(0), resultPayloadGPR); 1203 MacroAssembler::Jump op2NotCellJump = m_jit.jump(); 1204 1205 // At this point we know that we can perform a straight-forward equality comparison on pointer 1206 // values because we are doing strict equality. 1207 op2CellJump.link(&m_jit); 1208 m_jit.compare32(MacroAssembler::Equal, op1GPR, op2GPR, resultPayloadGPR); 1209 1210 op2NotCellJump.link(&m_jit); 1211 booleanResult(resultPayloadGPR, m_currentNode); 1212 } 1213 1214 void SpeculativeJIT::compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode) 1215 { 1216 BasicBlock* taken = branchNode->branchData()->taken.block; 1217 BasicBlock* notTaken = branchNode->branchData()->notTaken.block; 1218 1219 SpeculateCellOperand op1(this, objectChild); 1220 JSValueOperand op2(this, otherChild); 1221 1222 GPRReg op1GPR = op1.gpr(); 1223 GPRReg op2GPR = op2.payloadGPR(); 1224 1225 DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR)); 1226 1227 branch32(MacroAssembler::NotEqual, op2.tagGPR(), TrustedImm32(JSValue::CellTag), notTaken); 1228 1229 if (taken == nextBlock()) { 1230 branch32(MacroAssembler::NotEqual, op1GPR, op2GPR, notTaken); 1231 jump(taken); 1232 } else { 1233 branch32(MacroAssembler::Equal, op1GPR, op2GPR, taken); 1234 jump(notTaken); 1235 } 1185 1236 } 1186 1237 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r184542 r185920 1295 1295 1296 1296 jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean); 1297 } 1298 1299 void SpeculativeJIT::compileObjectStrictEquality(Edge objectChild, Edge otherChild) 1300 { 1301 SpeculateCellOperand op1(this, objectChild); 1302 JSValueOperand op2(this, otherChild); 1303 GPRTemporary result(this); 1304 1305 GPRReg op1GPR = op1.gpr(); 1306 GPRReg op2GPR = op2.gpr(); 1307 GPRReg resultGPR = result.gpr(); 1308 1309 DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR)); 1310 1311 // At this point we know that we can perform a straight-forward equality comparison on pointer 1312 // values because we are doing strict equality. 1313 m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR); 1314 m_jit.or32(TrustedImm32(ValueFalse), resultGPR); 1315 jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean); 1316 } 1317 1318 void SpeculativeJIT::compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode) 1319 { 1320 BasicBlock* taken = branchNode->branchData()->taken.block; 1321 BasicBlock* notTaken = branchNode->branchData()->notTaken.block; 1322 1323 SpeculateCellOperand op1(this, objectChild); 1324 JSValueOperand op2(this, otherChild); 1325 1326 GPRReg op1GPR = op1.gpr(); 1327 GPRReg op2GPR = op2.gpr(); 1328 1329 DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR)); 1330 1331 if (taken == nextBlock()) { 1332 branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR, notTaken); 1333 jump(taken); 1334 } else { 1335 branchPtr(MacroAssembler::Equal, op1GPR, op2GPR, taken); 1336 jump(notTaken); 1337 } 1297 1338 } 1298 1339 -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r185239 r185920 330 330 if (node->isBinaryUseKind(StringIdentUse)) 331 331 break; 332 if (node->isBinaryUseKind(ObjectUse, UntypedUse)) 333 break; 334 if (node->isBinaryUseKind(UntypedUse, ObjectUse)) 335 break; 332 336 if (node->isBinaryUseKind(ObjectUse)) 333 337 break; -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r185600 r185920 4158 4158 return; 4159 4159 } 4160 4160 4161 if (m_node->isBinaryUseKind(ObjectUse, UntypedUse)) { 4162 setBoolean( 4163 m_out.equal( 4164 lowNonNullObject(m_node->child1()), 4165 lowJSValue(m_node->child2()))); 4166 return; 4167 } 4168 4169 if (m_node->isBinaryUseKind(UntypedUse, ObjectUse)) { 4170 setBoolean( 4171 m_out.equal( 4172 lowNonNullObject(m_node->child2()), 4173 lowJSValue(m_node->child1()))); 4174 return; 4175 } 4176 4161 4177 if (m_node->isBinaryUseKind(ObjectUse)) { 4162 4178 setBoolean( -
trunk/Source/JavaScriptCore/jsc.cpp
r185608 r185920 459 459 static EncodedJSValue JSC_HOST_CALL functionHeapSize(ExecState*); 460 460 static EncodedJSValue JSC_HOST_CALL functionDeleteAllCompiledCode(ExecState*); 461 static EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState*); 461 462 #ifndef NDEBUG 462 463 static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*); … … 600 601 addFunction(vm, "gcHeapSize", functionHeapSize, 0); 601 602 addFunction(vm, "deleteAllCompiledCode", functionDeleteAllCompiledCode, 0); 603 addFunction(vm, "addressOf", functionAddressOf, 1); 602 604 #ifndef NDEBUG 603 605 addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0); … … 877 879 return JSValue::encode(jsUndefined()); 878 880 } 881 882 // This function is not generally very helpful in 64-bit code as the tag and payload 883 // share a register. But in 32-bit JITed code the tag may not be checked if an 884 // optimization removes type checking requirements, such as in ===. 885 EncodedJSValue JSC_HOST_CALL functionAddressOf(ExecState* exec) 886 { 887 JSValue value = exec->argument(0); 888 if (!value.isCell()) 889 return JSValue::encode(jsUndefined()); 890 // Need to cast to uint64_t so bitwise_cast will play along. 891 uint64_t asNumber = reinterpret_cast<uint64_t>(value.asCell()); 892 EncodedJSValue returnValue = JSValue::encode(jsNumber(bitwise_cast<double>(asNumber))); 893 return returnValue; 894 } 895 879 896 880 897 #ifndef NDEBUG
Note: See TracChangeset
for help on using the changeset viewer.