Changeset 218084 in webkit
- Timestamp:
- Jun 11, 2017 8:58:23 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 15 added
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r218082 r218084 1 2017-06-09 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [DFG] Add ArrayIndexOf intrinsic 4 https://bugs.webkit.org/show_bug.cgi?id=172421 5 6 Reviewed by Saam Barati. 7 8 * stress/array-indexof-array-prototype-change.js: Added. 9 (shouldBe): 10 (indexOfInt32): 11 * stress/array-indexof-have-a-bad-time-getter.js: Added. 12 (shouldBe): 13 (indexOfInt32): 14 * stress/array-indexof-have-a-bad-time.js: Added. 15 (shouldBe): 16 (indexOfInt32): 17 * stress/array-indexof-hole-with-prototype.js: Added. 18 (shouldBe): 19 (indexOf): 20 * stress/array-indexof-hole.js: Added. 21 (shouldBe): 22 (indexOf): 23 * stress/array-indexof-index.js: Added. 24 (shouldBe): 25 (indexOfInt32): 26 (indexOfDouble): 27 (indexOfString): 28 (indexOfObject): 29 (indexOfValue): 30 * stress/array-indexof-negative-index.js: Added. 31 (shouldBe): 32 (indexOfInt32): 33 (indexOfDouble): 34 (indexOfString): 35 (indexOfObject): 36 (indexOfValue): 37 * stress/array-indexof-non-int32-start-index.js: Added. 38 (shouldBe): 39 (indexOf): 40 (object.valueOf): 41 * stress/array-indexof-object-prototype-change.js: Added. 42 (shouldBe): 43 (indexOfInt32): 44 * stress/array-indexof-object.js: Added. 45 (shouldBe): 46 (indexOf): 47 * stress/array-indexof-original-array.js: Added. 48 (shouldBe): 49 (indexOfInt32): 50 * stress/array-indexof-string.js: Added. 51 (shouldBe): 52 (indexOf): 53 * stress/array-indexof-structure-change-convert.js: Added. 54 (shouldBe): 55 (indexOf): 56 * stress/array-indexof-structure-change.js: Added. 57 (shouldBe): 58 (indexOf): 59 * stress/array-indexof.js: Added. 60 (shouldBe): 61 (indexOf): 62 1 63 2017-06-11 Keith Miller <keith_miller@apple.com> 2 64 -
trunk/Source/JavaScriptCore/ChangeLog
r218082 r218084 1 2017-06-09 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [DFG] Add ArrayIndexOf intrinsic 4 https://bugs.webkit.org/show_bug.cgi?id=172421 5 6 Reviewed by Saam Barati. 7 8 This patch introduces ArrayIndexOfInstrinsic for DFG and FTL optimizations. 9 We emit array check and go fast path if the array is Array::Int32, Array::Double 10 or Array::Continugous. In addition, for Array::Int32 and Array::Double case, 11 we have inlined fast paths. 12 13 With updated ARES-6 Babylon, 14 15 Before 16 firstIteration: 45.76 +- 3.87 ms 17 averageWorstCase: 24.41 +- 2.17 ms 18 steadyState: 8.01 +- 0.22 ms 19 After 20 firstIteration: 45.64 +- 4.23 ms 21 averageWorstCase: 23.03 +- 3.34 ms 22 steadyState: 7.33 +- 0.34 ms 23 24 In SixSpeed. 25 baseline patched 26 27 map-set-lookup.es5 734.4701+-10.4383 ^ 102.0968+-2.6357 ^ definitely 7.1939x faster 28 map-set.es5 41.1396+-1.0558 ^ 33.1916+-0.7986 ^ definitely 1.2395x faster 29 map-set-object.es5 62.8317+-1.2518 ^ 45.6944+-0.8369 ^ definitely 1.3750x faster 30 31 * dfg/DFGAbstractInterpreterInlines.h: 32 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 33 * dfg/DFGByteCodeParser.cpp: 34 (JSC::DFG::ByteCodeParser::handleIntrinsicCall): 35 * dfg/DFGClobberize.h: 36 (JSC::DFG::clobberize): 37 * dfg/DFGDoesGC.cpp: 38 (JSC::DFG::doesGC): 39 * dfg/DFGFixupPhase.cpp: 40 (JSC::DFG::FixupPhase::fixupNode): 41 * dfg/DFGNode.h: 42 (JSC::DFG::Node::hasArrayMode): 43 * dfg/DFGNodeType.h: 44 * dfg/DFGOperations.cpp: 45 * dfg/DFGOperations.h: 46 * dfg/DFGPredictionPropagationPhase.cpp: 47 * dfg/DFGSafeToExecute.h: 48 (JSC::DFG::safeToExecute): 49 * dfg/DFGSpeculativeJIT.cpp: 50 (JSC::DFG::SpeculativeJIT::compileArrayIndexOf): 51 (JSC::DFG::SpeculativeJIT::speculateObject): 52 * dfg/DFGSpeculativeJIT.h: 53 (JSC::DFG::SpeculativeJIT::callOperation): 54 * dfg/DFGSpeculativeJIT32_64.cpp: 55 (JSC::DFG::SpeculativeJIT::compile): 56 * dfg/DFGSpeculativeJIT64.cpp: 57 (JSC::DFG::SpeculativeJIT::compile): 58 (JSC::DFG::SpeculativeJIT::speculateInt32): 59 * ftl/FTLCapabilities.cpp: 60 (JSC::FTL::canCompile): 61 * ftl/FTLLowerDFGToB3.cpp: 62 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 63 (JSC::FTL::DFG::LowerDFGToB3::compileArrayIndexOf): 64 * jit/JITOperations.h: 65 * runtime/ArrayPrototype.cpp: 66 (JSC::ArrayPrototype::finishCreation): 67 * runtime/Intrinsic.cpp: 68 (JSC::intrinsicName): 69 * runtime/Intrinsic.h: 70 1 71 2017-06-11 Keith Miller <keith_miller@apple.com> 2 72 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r217523 r218084 1707 1707 1708 1708 forNode(node).set(m_graph, structureSet); 1709 break; 1710 } 1711 1712 case ArrayIndexOf: { 1713 forNode(node).setType(SpecInt32Only); 1709 1714 break; 1710 1715 } -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r217840 r218084 2324 2324 2325 2325 // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole. 2326 // https://bugs.webkit.org/show_bug.cgi?id=173171 2326 2327 if (globalObject->arraySpeciesWatchpoint().state() == IsWatched 2327 2328 && globalObject->havingABadTimeWatchpoint()->isStillValid() … … 2379 2380 RELEASE_ASSERT_NOT_REACHED(); 2380 2381 return false; 2382 } 2383 2384 case ArrayIndexOfIntrinsic: { 2385 if (argumentCountIncludingThis < 2) 2386 return false; 2387 2388 if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType) 2389 || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache) 2390 || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache) 2391 || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType)) 2392 return false; 2393 2394 ArrayMode arrayMode = getArrayMode(m_currentInstruction[OPCODE_LENGTH(op_call) - 2].u.arrayProfile); 2395 if (!arrayMode.isJSArray()) 2396 return false; 2397 2398 if (arrayMode.arrayClass() != Array::OriginalArray) 2399 return false; 2400 2401 // We do not want to convert arrays into one type just to perform indexOf. 2402 if (arrayMode.doesConversion()) 2403 return false; 2404 2405 switch (arrayMode.type()) { 2406 case Array::Double: 2407 case Array::Int32: 2408 case Array::Contiguous: { 2409 JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic); 2410 2411 InlineWatchpointSet& objectPrototypeTransition = globalObject->objectPrototype()->structure()->transitionWatchpointSet(); 2412 InlineWatchpointSet& arrayPrototypeTransition = globalObject->arrayPrototype()->structure()->transitionWatchpointSet(); 2413 2414 // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole. 2415 // https://bugs.webkit.org/show_bug.cgi?id=173171 2416 if (globalObject->havingABadTimeWatchpoint()->isStillValid() 2417 && arrayPrototypeTransition.isStillValid() 2418 && objectPrototypeTransition.isStillValid() 2419 && globalObject->arrayPrototypeChainIsSane()) { 2420 2421 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint()); 2422 m_graph.watchpoints().addLazily(arrayPrototypeTransition); 2423 m_graph.watchpoints().addLazily(objectPrototypeTransition); 2424 2425 insertChecks(); 2426 2427 Node* array = get(virtualRegisterForArgument(0, registerOffset)); 2428 addVarArgChild(array); 2429 addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Search element. 2430 if (argumentCountIncludingThis >= 3) 2431 addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // Start index. 2432 addVarArgChild(nullptr); 2433 2434 Node* node = addToGraph(Node::VarArg, ArrayIndexOf, OpInfo(arrayMode.asWord()), OpInfo()); 2435 set(VirtualRegister(resultOperand), node); 2436 return true; 2437 } 2438 2439 return false; 2440 } 2441 default: 2442 return false; 2443 } 2444 2445 RELEASE_ASSERT_NOT_REACHED(); 2446 return false; 2447 2381 2448 } 2382 2449 -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r217523 r218084 539 539 write(HeapObjectCount); 540 540 return; 541 542 case ArrayIndexOf: { 543 // FIXME: Should support a CSE rule. 544 // https://bugs.webkit.org/show_bug.cgi?id=173173 545 read(MiscFields); 546 read(JSCell_indexingType); 547 read(JSCell_structureID); 548 read(JSObject_butterfly); 549 read(Butterfly_publicLength); 550 switch (node->arrayMode().type()) { 551 case Array::Double: 552 read(IndexedDoubleProperties); 553 return; 554 case Array::Int32: 555 read(IndexedInt32Properties); 556 return; 557 case Array::Contiguous: 558 read(IndexedContiguousProperties); 559 return; 560 default: 561 RELEASE_ASSERT_NOT_REACHED(); 562 return; 563 } 564 return; 565 } 541 566 542 567 case GetById: -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r217202 r218084 321 321 case CallDOM: 322 322 case ArraySlice: 323 case ArrayIndexOf: 323 324 case ParseInt: // We might resolve a rope even though we don't clobber anything. 324 325 return true; -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r217523 r218084 1021 1021 if (node->numChildren() == 4) 1022 1022 fixEdge<Int32Use>(m_graph.varArgChild(node, 2)); 1023 break; 1024 } 1025 1026 case ArrayIndexOf: { 1027 Edge& array = m_graph.varArgChild(node, 0); 1028 Edge& storage = m_graph.varArgChild(node, node->numChildren() == 3 ? 2 : 3); 1029 blessArrayOperation(array, Edge(), storage); 1030 ASSERT_WITH_MESSAGE(storage.node(), "blessArrayOperation for ArrayIndexOf must set Butterfly for storage edge."); 1031 1032 fixEdge<KnownCellUse>(array); 1033 if (node->numChildren() == 4) 1034 fixEdge<Int32Use>(m_graph.varArgChild(node, 2)); 1035 1036 Edge& searchElement = m_graph.varArgChild(node, 1); 1037 // FIXME: We have a chance to constant-fold this node to -1 by 1038 // emitting non number edge filters. 1039 // https://bugs.webkit.org/show_bug.cgi?id=173176 1040 switch (node->arrayMode().type()) { 1041 case Array::Double: { 1042 if (searchElement->shouldSpeculateNumber()) 1043 fixEdge<DoubleRepUse>(searchElement); 1044 break; 1045 } 1046 case Array::Int32: { 1047 if (searchElement->shouldSpeculateInt32()) 1048 fixEdge<Int32Use>(searchElement); 1049 break; 1050 } 1051 case Array::Contiguous: { 1052 if (searchElement->shouldSpeculateString()) 1053 fixEdge<StringUse>(searchElement); 1054 else if (searchElement->shouldSpeculateObject()) 1055 fixEdge<ObjectUse>(searchElement); 1056 break; 1057 } 1058 default: 1059 RELEASE_ASSERT_NOT_REACHED(); 1060 break; 1061 } 1023 1062 break; 1024 1063 } -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r217523 r218084 1819 1819 case ArrayPush: 1820 1820 case ArrayPop: 1821 case ArrayIndexOf: 1821 1822 case HasIndexedProperty: 1822 1823 case AtomicsAdd: -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r217202 r218084 263 263 macro(ArrayPop, NodeResultJS | NodeMustGenerate) \ 264 264 macro(ArraySlice, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \ 265 macro(ArrayIndexOf, NodeResultInt32 | NodeHasVarArgs) \ 265 266 \ 266 267 /* Optimizations for regular expression matching. */\ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r217202 r218084 1906 1906 } 1907 1907 1908 int32_t JIT_OPERATION operationArrayIndexOfString(ExecState* exec, Butterfly* butterfly, JSString* searchElement, int32_t index) 1909 { 1910 VM& vm = exec->vm(); 1911 NativeCallFrameTracer tracer(&vm, exec); 1912 auto scope = DECLARE_THROW_SCOPE(vm); 1913 1914 int32_t length = butterfly->publicLength(); 1915 auto data = butterfly->contiguous().data(); 1916 for (; index < length; ++index) { 1917 JSValue value = data[index].get(); 1918 if (!value || !value.isString()) 1919 continue; 1920 auto* string = asString(value); 1921 if (string == searchElement) 1922 return index; 1923 if (string->equal(exec, searchElement)) 1924 return index; 1925 RETURN_IF_EXCEPTION(scope, { }); 1926 } 1927 return -1; 1928 } 1929 1930 int32_t JIT_OPERATION operationArrayIndexOfValueInt32OrContiguous(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index) 1931 { 1932 VM& vm = exec->vm(); 1933 NativeCallFrameTracer tracer(&vm, exec); 1934 auto scope = DECLARE_THROW_SCOPE(vm); 1935 1936 JSValue searchElement = JSValue::decode(encodedValue); 1937 1938 int32_t length = butterfly->publicLength(); 1939 auto data = butterfly->contiguous().data(); 1940 for (; index < length; ++index) { 1941 JSValue value = data[index].get(); 1942 if (!value) 1943 continue; 1944 if (JSValue::strictEqual(exec, searchElement, value)) 1945 return index; 1946 RETURN_IF_EXCEPTION(scope, { }); 1947 } 1948 return -1; 1949 } 1950 1951 int32_t JIT_OPERATION operationArrayIndexOfValueDouble(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index) 1952 { 1953 VM& vm = exec->vm(); 1954 NativeCallFrameTracer tracer(&vm, exec); 1955 1956 JSValue searchElement = JSValue::decode(encodedValue); 1957 1958 if (!searchElement.isNumber()) 1959 return -1; 1960 double number = searchElement.asNumber(); 1961 1962 int32_t length = butterfly->publicLength(); 1963 const double* data = butterfly->contiguousDouble().data(); 1964 for (; index < length; ++index) { 1965 // This comparison ignores NaN. 1966 if (data[index] == number) 1967 return index; 1968 } 1969 return -1; 1970 } 1971 1908 1972 void JIT_OPERATION operationLoadVarargs(ExecState* exec, int32_t firstElementDest, EncodedJSValue encodedArguments, int32_t offset, int32_t length, int32_t mandatoryMinimum) 1909 1973 { -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r217202 r218084 206 206 int32_t JIT_OPERATION operationHasOwnProperty(ExecState*, JSObject*, EncodedJSValue); 207 207 208 int32_t JIT_OPERATION operationArrayIndexOfString(ExecState*, Butterfly*, JSString*, int32_t); 209 int32_t JIT_OPERATION operationArrayIndexOfValue(ExecState*, Butterfly*, EncodedJSValue, int32_t); 210 int32_t JIT_OPERATION operationArrayIndexOfValueDouble(ExecState*, Butterfly*, EncodedJSValue, int32_t); 211 int32_t JIT_OPERATION operationArrayIndexOfValueInt32OrContiguous(ExecState*, Butterfly*, EncodedJSValue, int32_t); 212 208 213 JSCell* JIT_OPERATION operationSpreadFastArray(ExecState*, JSCell*); 209 214 JSCell* JIT_OPERATION operationSpreadGeneric(ExecState*, JSCell*); -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r217202 r218084 763 763 break; 764 764 765 case GetRestLength: { 765 case GetRestLength: 766 case ArrayIndexOf: { 766 767 setPrediction(SpecInt32Only); 767 768 break; -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r217202 r218084 393 393 return true; 394 394 395 case ArraySlice: { 395 case ArraySlice: 396 case ArrayIndexOf: { 396 397 // You could plausibly move this code around as long as you proved the 397 398 // incoming array base structure is an original array at the hoisted location. -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r217523 r218084 7443 7443 } 7444 7444 7445 void SpeculativeJIT::compileArrayIndexOf(Node* node) 7446 { 7447 ASSERT(node->op() == ArrayIndexOf); 7448 7449 StorageOperand storage(this, m_jit.graph().varArgChild(node, node->numChildren() == 3 ? 2 : 3)); 7450 GPRTemporary index(this); 7451 GPRTemporary tempLength(this); 7452 7453 GPRReg storageGPR = storage.gpr(); 7454 GPRReg indexGPR = index.gpr(); 7455 GPRReg lengthGPR = tempLength.gpr(); 7456 7457 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), lengthGPR); 7458 7459 if (node->numChildren() == 4) { 7460 SpeculateInt32Operand startIndex(this, m_jit.graph().varArgChild(node, 2)); 7461 GPRReg startIndexGPR = startIndex.gpr(); 7462 MacroAssembler::JumpList done; 7463 auto isPositive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, startIndexGPR, TrustedImm32(0)); 7464 m_jit.move(lengthGPR, indexGPR); 7465 done.append(m_jit.branchAdd32(MacroAssembler::PositiveOrZero, startIndexGPR, indexGPR)); 7466 m_jit.move(TrustedImm32(0), indexGPR); 7467 done.append(m_jit.jump()); 7468 7469 isPositive.link(&m_jit); 7470 m_jit.move(startIndexGPR, indexGPR); 7471 done.append(m_jit.branch32(MacroAssembler::BelowOrEqual, indexGPR, lengthGPR)); 7472 m_jit.move(lengthGPR, indexGPR); 7473 7474 done.link(&m_jit); 7475 } else 7476 m_jit.move(TrustedImm32(0), indexGPR); 7477 7478 Edge& searchElementEdge = m_jit.graph().varArgChild(node, 1); 7479 switch (searchElementEdge.useKind()) { 7480 case Int32Use: 7481 case ObjectUse: { 7482 auto emitLoop = [&] (auto emitCompare) { 7483 m_jit.zeroExtend32ToPtr(lengthGPR, lengthGPR); 7484 m_jit.zeroExtend32ToPtr(indexGPR, indexGPR); 7485 7486 auto loop = m_jit.label(); 7487 auto notFound = m_jit.branch32(CCallHelpers::Equal, indexGPR, lengthGPR); 7488 7489 auto found = emitCompare(); 7490 7491 m_jit.add32(TrustedImm32(1), indexGPR); 7492 m_jit.jump().linkTo(loop, &m_jit); 7493 7494 notFound.link(&m_jit); 7495 m_jit.move(TrustedImm32(-1), indexGPR); 7496 found.link(&m_jit); 7497 int32Result(indexGPR, node); 7498 }; 7499 7500 #if USE(JSVALUE32_64) 7501 GPRTemporary temp(this); 7502 GPRReg tempGPR = temp.gpr(); 7503 #endif 7504 7505 if (searchElementEdge.useKind() == Int32Use) { 7506 ASSERT(node->arrayMode().type() == Array::Int32); 7507 #if USE(JSVALUE64) 7508 JSValueOperand searchElement(this, searchElementEdge, ManualOperandSpeculation); 7509 JSValueRegs searchElementRegs = searchElement.jsValueRegs(); 7510 speculateInt32(searchElementEdge, searchElementRegs); 7511 GPRReg searchElementGPR = searchElementRegs.payloadGPR(); 7512 #else 7513 SpeculateInt32Operand searchElement(this, searchElementEdge); 7514 GPRReg searchElementGPR = searchElement.gpr(); 7515 #endif 7516 emitLoop([&] () { 7517 #if USE(JSVALUE64) 7518 auto found = m_jit.branch64(CCallHelpers::Equal, MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), searchElementGPR); 7519 #else 7520 auto skip = m_jit.branch32(CCallHelpers::NotEqual, MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, TagOffset), TrustedImm32(JSValue::Int32Tag)); 7521 m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, PayloadOffset), tempGPR); 7522 auto found = m_jit.branch32(CCallHelpers::Equal, tempGPR, searchElementGPR); 7523 skip.link(&m_jit); 7524 #endif 7525 return found; 7526 }); 7527 } else { 7528 ASSERT(node->arrayMode().type() == Array::Contiguous); 7529 SpeculateCellOperand searchElement(this, searchElementEdge); 7530 GPRReg searchElementGPR = searchElement.gpr(); 7531 speculateObject(searchElementEdge, searchElementGPR); 7532 7533 emitLoop([&] () { 7534 #if USE(JSVALUE64) 7535 auto found = m_jit.branch64(CCallHelpers::Equal, MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), searchElementGPR); 7536 #else 7537 auto skip = m_jit.branch32(CCallHelpers::NotEqual, MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, TagOffset), TrustedImm32(JSValue::CellTag)); 7538 m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, PayloadOffset), tempGPR); 7539 auto found = m_jit.branch32(CCallHelpers::Equal, tempGPR, searchElementGPR); 7540 skip.link(&m_jit); 7541 #endif 7542 return found; 7543 }); 7544 } 7545 break; 7546 } 7547 7548 case DoubleRepUse: { 7549 ASSERT(node->arrayMode().type() == Array::Double); 7550 SpeculateDoubleOperand searchElement(this, searchElementEdge); 7551 FPRTemporary tempDouble(this); 7552 7553 FPRReg searchElementFPR = searchElement.fpr(); 7554 FPRReg tempFPR = tempDouble.fpr(); 7555 7556 m_jit.zeroExtend32ToPtr(lengthGPR, lengthGPR); 7557 m_jit.zeroExtend32ToPtr(indexGPR, indexGPR); 7558 7559 auto loop = m_jit.label(); 7560 auto notFound = m_jit.branch32(CCallHelpers::Equal, indexGPR, lengthGPR); 7561 m_jit.loadDouble(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), tempFPR); 7562 auto found = m_jit.branchDouble(CCallHelpers::DoubleEqual, tempFPR, searchElementFPR); 7563 m_jit.add32(TrustedImm32(1), indexGPR); 7564 m_jit.jump().linkTo(loop, &m_jit); 7565 7566 notFound.link(&m_jit); 7567 m_jit.move(TrustedImm32(-1), indexGPR); 7568 found.link(&m_jit); 7569 int32Result(indexGPR, node); 7570 break; 7571 } 7572 7573 case StringUse: { 7574 ASSERT(node->arrayMode().type() == Array::Contiguous); 7575 SpeculateCellOperand searchElement(this, searchElementEdge); 7576 7577 GPRReg searchElementGPR = searchElement.gpr(); 7578 7579 speculateString(searchElementEdge, searchElementGPR); 7580 7581 flushRegisters(); 7582 7583 callOperation(operationArrayIndexOfString, lengthGPR, storageGPR, searchElementGPR, indexGPR); 7584 m_jit.exceptionCheck(); 7585 7586 int32Result(lengthGPR, node); 7587 break; 7588 } 7589 7590 case UntypedUse: { 7591 JSValueOperand searchElement(this, searchElementEdge); 7592 7593 JSValueRegs searchElementRegs = searchElement.jsValueRegs(); 7594 7595 flushRegisters(); 7596 switch (node->arrayMode().type()) { 7597 case Array::Double: 7598 callOperation(operationArrayIndexOfValueDouble, lengthGPR, storageGPR, searchElementRegs, indexGPR); 7599 break; 7600 case Array::Int32: 7601 case Array::Contiguous: 7602 callOperation(operationArrayIndexOfValueInt32OrContiguous, lengthGPR, storageGPR, searchElementRegs, indexGPR); 7603 break; 7604 default: 7605 RELEASE_ASSERT_NOT_REACHED(); 7606 break; 7607 } 7608 m_jit.exceptionCheck(); 7609 7610 int32Result(lengthGPR, node); 7611 break; 7612 } 7613 7614 default: 7615 RELEASE_ASSERT_NOT_REACHED(); 7616 break; 7617 } 7618 } 7619 7445 7620 void SpeculativeJIT::compileNotifyWrite(Node* node) 7446 7621 { … … 8429 8604 } 8430 8605 8606 void SpeculativeJIT::speculateObject(Edge edge, GPRReg cell) 8607 { 8608 DFG_TYPE_CHECK(JSValueSource::unboxedCell(cell), edge, SpecObject, m_jit.branchIfNotObject(cell)); 8609 } 8610 8431 8611 void SpeculativeJIT::speculateObject(Edge edge) 8432 8612 { … … 8435 8615 8436 8616 SpeculateCellOperand operand(this, edge); 8437 GPRReg gpr = operand.gpr(); 8438 DFG_TYPE_CHECK( 8439 JSValueSource::unboxedCell(gpr), edge, SpecObject, m_jit.branchIfNotObject(gpr)); 8617 speculateObject(edge, operand.gpr()); 8440 8618 } 8441 8619 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r217202 r218084 1007 1007 return appendCallSetResult(operation, result); 1008 1008 } 1009 JITCompiler::Call callOperation(Z_JITOperation_EBJssZ operation, GPRReg result, GPRReg butterfly, GPRReg string, GPRReg index) 1010 { 1011 m_jit.setupArgumentsWithExecState(butterfly, string, index); 1012 return appendCallSetResult(operation, result); 1013 } 1009 1014 JITCompiler::Call callOperation(P_JITOperation_ESt operation, GPRReg result, RegisteredStructure structure) 1010 1015 { … … 1886 1891 { 1887 1892 m_jit.setupArgumentsWithExecState(arg1, TrustedImm32(arg2)); 1893 return appendCallSetResult(operation, result); 1894 } 1895 JITCompiler::Call callOperation(Z_JITOperation_EBJZ operation, GPRReg result, GPRReg arg1, JSValueRegs arg2, GPRReg arg3) 1896 { 1897 m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg3); 1888 1898 return appendCallSetResult(operation, result); 1889 1899 } … … 2419 2429 { 2420 2430 m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), TrustedImm32(arg2)); 2431 return appendCallSetResult(operation, result); 2432 } 2433 JITCompiler::Call callOperation(Z_JITOperation_EBJZ operation, GPRReg result, GPRReg arg1, JSValueRegs arg2, GPRReg arg3) 2434 { 2435 m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR(), arg3); 2421 2436 return appendCallSetResult(operation, result); 2422 2437 } … … 2830 2845 void compileGetRestLength(Node*); 2831 2846 void compileArraySlice(Node*); 2847 void compileArrayIndexOf(Node*); 2832 2848 void compileNotifyWrite(Node*); 2833 2849 bool compileRegExpExec(Node*); … … 2950 2966 void convertAnyInt(Edge, GPRReg resultGPR); 2951 2967 void speculateAnyInt(Edge); 2968 void speculateInt32(Edge, JSValueRegs); 2952 2969 void speculateDoubleRepAnyInt(Edge); 2953 2970 #endif // USE(JSVALUE64) … … 2958 2975 void speculateCell(Edge); 2959 2976 void speculateCellOrOther(Edge); 2977 void speculateObject(Edge, GPRReg cell); 2960 2978 void speculateObject(Edge); 2961 2979 void speculateArray(Edge, GPRReg cell); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r217202 r218084 3584 3584 } 3585 3585 3586 case ArrayIndexOf: { 3587 compileArrayIndexOf(node); 3588 break; 3589 } 3590 3586 3591 case DFG::Jump: { 3587 3592 jump(node->targetBlock()); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r217896 r218084 3720 3720 case ArraySlice: { 3721 3721 compileArraySlice(node); 3722 break; 3723 } 3724 3725 case ArrayIndexOf: { 3726 compileArrayIndexOf(node); 3722 3727 break; 3723 3728 } … … 6169 6174 } 6170 6175 6176 void SpeculativeJIT::speculateInt32(Edge edge, JSValueRegs regs) 6177 { 6178 DFG_TYPE_CHECK(regs, edge, SpecInt32Only, m_jit.branchIfNotInt32(regs)); 6179 } 6180 6171 6181 void SpeculativeJIT::speculateDoubleRepAnyInt(Edge edge) 6172 6182 { -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r217202 r218084 283 283 case CallDOMGetter: 284 284 case ArraySlice: 285 case ArrayIndexOf: 285 286 case ParseInt: 286 287 case AtomicsAdd: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r217995 r218084 727 727 compileArraySlice(); 728 728 break; 729 case ArrayIndexOf: 730 compileArrayIndexOf(); 731 break; 729 732 case CreateActivation: 730 733 compileCreateActivation(); … … 4051 4054 setJSValue(arrayResult.array); 4052 4055 } 4056 4057 void compileArrayIndexOf() 4058 { 4059 LValue storage = lowStorage(m_node->numChildren() == 3 ? m_graph.varArgChild(m_node, 2) : m_graph.varArgChild(m_node, 3)); 4060 LValue length = m_out.load32(storage, m_heaps.Butterfly_publicLength); 4061 4062 LValue startIndex; 4063 if (m_node->numChildren() == 4) { 4064 startIndex = lowInt32(m_graph.varArgChild(m_node, 2)); 4065 startIndex = m_out.select(m_out.greaterThanOrEqual(startIndex, m_out.int32Zero), 4066 m_out.select(m_out.above(startIndex, length), length, startIndex), 4067 m_out.select(m_out.lessThan(m_out.add(length, startIndex), m_out.int32Zero), m_out.int32Zero, m_out.add(length, startIndex))); 4068 } else 4069 startIndex = m_out.int32Zero; 4070 4071 Edge& searchElementEdge = m_graph.varArgChild(m_node, 1); 4072 switch (searchElementEdge.useKind()) { 4073 case Int32Use: 4074 case ObjectUse: 4075 case DoubleRepUse: { 4076 LBasicBlock loopHeader = m_out.newBlock(); 4077 LBasicBlock loopBody = m_out.newBlock(); 4078 LBasicBlock loopNext = m_out.newBlock(); 4079 LBasicBlock notFound = m_out.newBlock(); 4080 LBasicBlock continuation = m_out.newBlock(); 4081 4082 LValue searchElement; 4083 if (searchElementEdge.useKind() == Int32Use) { 4084 ASSERT(m_node->arrayMode().type() == Array::Int32); 4085 speculate(searchElementEdge); 4086 searchElement = lowJSValue(searchElementEdge, ManualOperandSpeculation); 4087 } else if (searchElementEdge.useKind() == ObjectUse) { 4088 ASSERT(m_node->arrayMode().type() == Array::Contiguous); 4089 searchElement = lowObject(searchElementEdge); 4090 } else { 4091 ASSERT(m_node->arrayMode().type() == Array::Double); 4092 searchElement = lowDouble(searchElementEdge); 4093 } 4094 4095 startIndex = m_out.zeroExtPtr(startIndex); 4096 length = m_out.zeroExtPtr(length); 4097 4098 ValueFromBlock initialStartIndex = m_out.anchor(startIndex); 4099 m_out.jump(loopHeader); 4100 4101 LBasicBlock lastNext = m_out.appendTo(loopHeader, loopBody); 4102 LValue index = m_out.phi(pointerType(), initialStartIndex); 4103 m_out.branch(m_out.notEqual(index, length), unsure(loopBody), unsure(notFound)); 4104 4105 m_out.appendTo(loopBody, loopNext); 4106 ValueFromBlock foundResult = m_out.anchor(index); 4107 if (searchElementEdge.useKind() == Int32Use) { 4108 // Empty value is ignored because of TagTypeNumber. 4109 LValue value = m_out.load64(m_out.baseIndex(m_heaps.indexedInt32Properties, storage, index)); 4110 m_out.branch(m_out.equal(value, searchElement), unsure(continuation), unsure(loopNext)); 4111 } else if (searchElementEdge.useKind() == ObjectUse) { 4112 // Empty value never matches against object pointers. 4113 LValue value = m_out.load64(m_out.baseIndex(m_heaps.indexedContiguousProperties, storage, index)); 4114 m_out.branch(m_out.equal(value, searchElement), unsure(continuation), unsure(loopNext)); 4115 } else { 4116 // Empty value is ignored because of NaN. 4117 LValue value = m_out.loadDouble(m_out.baseIndex(m_heaps.indexedDoubleProperties, storage, index)); 4118 m_out.branch(m_out.doubleEqual(value, searchElement), unsure(continuation), unsure(loopNext)); 4119 } 4120 4121 m_out.appendTo(loopNext, notFound); 4122 LValue nextIndex = m_out.add(index, m_out.intPtrOne); 4123 m_out.addIncomingToPhi(index, m_out.anchor(nextIndex)); 4124 m_out.jump(loopHeader); 4125 4126 m_out.appendTo(notFound, continuation); 4127 ValueFromBlock notFoundResult = m_out.anchor(m_out.constIntPtr(-1)); 4128 m_out.jump(continuation); 4129 4130 m_out.appendTo(continuation, lastNext); 4131 setInt32(m_out.castToInt32(m_out.phi(pointerType(), notFoundResult, foundResult))); 4132 break; 4133 } 4134 4135 case StringUse: 4136 ASSERT(m_node->arrayMode().type() == Array::Contiguous); 4137 setInt32(vmCall(Int32, m_out.operation(operationArrayIndexOfString), m_callFrame, storage, lowString(searchElementEdge), startIndex)); 4138 break; 4139 4140 case UntypedUse: 4141 switch (m_node->arrayMode().type()) { 4142 case Array::Double: 4143 setInt32(vmCall(Int32, m_out.operation(operationArrayIndexOfValueDouble), m_callFrame, storage, lowJSValue(searchElementEdge), startIndex)); 4144 break; 4145 case Array::Int32: 4146 case Array::Contiguous: 4147 setInt32(vmCall(Int32, m_out.operation(operationArrayIndexOfValueInt32OrContiguous), m_callFrame, storage, lowJSValue(searchElementEdge), startIndex)); 4148 break; 4149 default: 4150 RELEASE_ASSERT_NOT_REACHED(); 4151 break; 4152 } 4153 break; 4154 4155 default: 4156 RELEASE_ASSERT_NOT_REACHED(); 4157 break; 4158 } 4159 } 4160 4053 4161 4054 4162 void compileArrayPop() -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r217202 r218084 234 234 typedef int32_t (JIT_OPERATION *Z_JITOperation_EOI)(ExecState*, JSObject*, UniquedStringImpl*); 235 235 typedef int32_t (JIT_OPERATION *Z_JITOperation_EOJ)(ExecState*, JSObject*, EncodedJSValue); 236 typedef int32_t (JIT_OPERATION *Z_JITOperation_EBJssZ)(ExecState*, Butterfly*, JSString*, int32_t); 237 typedef int32_t (JIT_OPERATION *Z_JITOperation_EBJZ)(ExecState*, Butterfly*, EncodedJSValue, int32_t); 236 238 typedef size_t (JIT_OPERATION *S_JITOperation_EO)(ExecState*, JSObject*); 237 239 typedef size_t (JIT_OPERATION *S_JITOperation_ECC)(ExecState*, JSCell*, JSCell*); -
trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
r217149 r218084 106 106 JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("forEach", arrayPrototypeForEachCodeGenerator, DontEnum); 107 107 JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("some", arrayPrototypeSomeCodeGenerator, DontEnum); 108 JSC_NATIVE_ FUNCTION_WITHOUT_TRANSITION("indexOf", arrayProtoFuncIndexOf, DontEnum, 1);108 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION("indexOf", arrayProtoFuncIndexOf, DontEnum, 1, ArrayIndexOfIntrinsic); 109 109 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("lastIndexOf", arrayProtoFuncLastIndexOf, DontEnum, 1); 110 110 JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("filter", arrayPrototypeFilterCodeGenerator, DontEnum); -
trunk/Source/JavaScriptCore/runtime/Intrinsic.cpp
r217050 r218084 72 72 case TanhIntrinsic: 73 73 return "TanhIntrinsic"; 74 case ArrayIndexOfIntrinsic: 75 return "ArrayIndexOfIntrinsic"; 74 76 case ArrayPushIntrinsic: 75 77 return "ArrayPushIntrinsic"; -
trunk/Source/JavaScriptCore/runtime/Intrinsic.h
r217050 r218084 52 52 ArrayPopIntrinsic, 53 53 ArraySliceIntrinsic, 54 ArrayIndexOfIntrinsic, 54 55 CharCodeAtIntrinsic, 55 56 CharAtIntrinsic,
Note: See TracChangeset
for help on using the changeset viewer.