Changeset 157267 in webkit
- Timestamp:
- Oct 10, 2013 4:16:04 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r157265 r157267 1 2013-10-09 Oliver Hunt <oliver@apple.com> 2 3 Further improve ArrayIterator performance 4 https://bugs.webkit.org/show_bug.cgi?id=122575 5 6 Reviewed by Mark Hahnenberg. 7 8 Add a few new tests to make sure the new asm thunk correctly 9 handles non-arrays. 10 11 * js/array-iterators-expected.txt: 12 * js/script-tests/array-iterators.js: 13 1 14 2013-10-10 Andy Estes <aestes@apple.com> 2 15 -
trunk/LayoutTests/js/array-iterators-expected.txt
r157150 r157267 56 56 PASS key is i 57 57 PASS testArray.length is 9 58 PASS i is 0 59 PASS value is o[key] 60 PASS key is 0 61 PASS value is 1 62 PASS value is o[key] 63 PASS key is 1 64 PASS value is 2 65 PASS value is o[key] 66 PASS key is 2 67 PASS value is 3 68 PASS value is o[key] 69 PASS key is 3 70 PASS value is 4 71 PASS value is o[key] 72 PASS key is 4 73 PASS value is 5 74 PASS value is o[key] 75 PASS key is 5 76 PASS value is 6 77 PASS o.length is 6 78 PASS value is 1.5 79 PASS value is 2.5 80 PASS value is 3.5 81 PASS value is 4.5 82 PASS value is 5.5 83 PASS value is 6.5 84 PASS testArray.length is 6 85 PASS value is true 86 PASS value is true 87 PASS value is true 88 PASS value is true 89 PASS value is true 90 PASS value is true 91 PASS testArray.length is 6 92 PASS isNaN(value) is true 93 PASS isNaN(value) is true 94 PASS isNaN(value) is true 95 PASS isNaN(value) is true 96 PASS isNaN(value) is true 97 PASS isNaN(value) is true 98 PASS testArray.length is 6 99 PASS value is undefined. 100 PASS value is undefined. 101 PASS value is undefined. 102 PASS value is undefined. 103 PASS value is undefined. 104 PASS value is undefined. 105 PASS value is undefined. 106 PASS value is undefined. 107 PASS testArray.length is 8 108 PASS key is 0 109 PASS key is 1 110 PASS key is 2 111 PASS key is 3 112 PASS key is 4 113 PASS key is 5 114 PASS key is 6 115 PASS key is 7 116 PASS testArray.length is 8 58 117 PASS successfullyParsed is true 59 118 -
trunk/LayoutTests/js/script-tests/array-iterators.js
r157150 r157267 51 51 shouldBe("testArray.length", String(i)) 52 52 53 var o = {}; 54 for (var i =0; i < 6; i++) 55 o[i]=i+1 56 57 58 var entries = Array.prototype.entries.call(o); 59 var i = 0; 60 for (var [key, value] of entries) { 61 fail(); 62 } 63 shouldBe("i", "0") 64 65 o.length=6; 66 67 var entries = Array.prototype.entries.call(o); 68 var i = 0; 69 for (var [key, value] of entries) { 70 shouldBe("value", "o[key]") 71 shouldBe("key", String(i)) 72 i++ 73 shouldBe("value", String(i)) 74 } 75 shouldBe("o.length", String(i)) 76 77 78 var testArray = [1.5,2.5,3.5,4.5,5.5,6.5] 79 var i = 0; 80 for (var value of testArray) { 81 shouldBe("value", String(i + 1.5)) 82 i++; 83 } 84 85 shouldBe("testArray.length", String(i)) 86 87 88 var testArray = [true,true,true,true,true,true] 89 var i = 0; 90 for (var value of testArray) { 91 shouldBe("value", "true") 92 i++; 93 } 94 95 shouldBe("testArray.length", String(i)) 96 97 98 var testArray = [NaN,NaN,NaN,NaN,NaN,NaN] 99 var i = 0; 100 for (var value of testArray) { 101 shouldBeTrue("isNaN(value)") 102 i++; 103 } 104 105 shouldBe("testArray.length", String(i)) 106 107 108 109 var testArray = [undefined,,undefined,,undefined,undefined] 110 testArray.length = 8; 111 var i = 0; 112 for (var value of testArray) { 113 shouldBeUndefined("value") 114 i++; 115 } 116 117 shouldBe("testArray.length", String(i)) 118 var i = 0; 119 for (var key of testArray.keys()) { 120 shouldBe("key", String(i)) 121 i++; 122 } 123 124 shouldBe("testArray.length", String(i)) -
trunk/Source/JavaScriptCore/ChangeLog
r157266 r157267 1 2013-10-09 Oliver Hunt <oliver@apple.com> 2 3 Further improve ArrayIterator performance 4 https://bugs.webkit.org/show_bug.cgi?id=122575 5 6 Reviewed by Mark Hahnenberg. 7 8 Add an assembly thunk for ArrayIterator.@@next so that we 9 can avoid marshalling costs when iterating arrays. 10 11 * jit/SpecializedThunkJIT.h: 12 (JSC::SpecializedThunkJIT::SpecializedThunkJIT): 13 (JSC::SpecializedThunkJIT::loadSpecificClassArgument): 14 * jit/ThunkGenerators.cpp: 15 (JSC::arrayIteratorNextThunkGenerator): 16 * jit/ThunkGenerators.h: 17 * runtime/ArrayIteratorPrototype.cpp: 18 (JSC::ArrayIteratorPrototype::finishCreation): 19 * runtime/Intrinsic.h: 20 * runtime/JSArrayIterator.h: 21 (JSC::JSArrayIterator::offsetOfIterationKind): 22 (JSC::JSArrayIterator::offsetOfIteratedObject): 23 (JSC::JSArrayIterator::offsetOfNextIndex): 24 * runtime/JSCJSValue.h: 25 (JSC::JSValue::offsetOfPayload): 26 * runtime/JSGlobalObject.cpp: 27 (JSC::JSGlobalObject::reset): 28 * runtime/JSGlobalObject.h: 29 (JSC::JSGlobalObject::iteratorResultStructureOffset): 30 * runtime/VM.cpp: 31 (JSC::thunkGeneratorForIntrinsic): 32 1 33 2013-10-10 Michael Saboff <msaboff@apple.com> 2 34 -
trunk/Source/JavaScriptCore/jit/SpecializedThunkJIT.h
r156184 r157267 31 31 #include "Executable.h" 32 32 #include "JSInterfaceJIT.h" 33 #include "JSStack.h" 33 34 #include "LinkBuffer.h" 34 35 … … 45 46 } 46 47 48 explicit SpecializedThunkJIT(VM* vm) 49 : JSInterfaceJIT(vm) 50 { 51 } 52 47 53 void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch) 48 54 { … … 61 67 loadCellArgument(argument, dst); 62 68 m_failures.append(branchPtr(NotEqual, Address(dst, JSCell::structureOffset()), TrustedImmPtr(vm.stringStructure.get()))); 69 } 70 71 void loadArgumentWithSpecificClass(const ClassInfo* classInfo, int argument, RegisterID dst, RegisterID scratch) 72 { 73 loadCellArgument(argument, dst); 74 loadPtr(Address(dst, JSCell::structureOffset()), scratch); 75 appendFailure(branchPtr(NotEqual, Address(scratch, Structure::classInfoOffset()), TrustedImmPtr(classInfo))); 63 76 } 64 77 … … 80 93 m_failures.append(failure); 81 94 } 82 95 #if USE(JSVALUE64) 83 96 void returnJSValue(RegisterID src) 84 97 { … … 88 101 ret(); 89 102 } 103 #else 104 void returnJSValue(RegisterID payload, RegisterID tag) 105 { 106 ASSERT_UNUSED(payload, payload == regT0); 107 ASSERT_UNUSED(tag, tag == regT1); 108 loadPtr(payloadFor(JSStack::CallerFrame, callFrameRegister), callFrameRegister); 109 ret(); 110 } 111 #endif 90 112 91 113 void returnDouble(FPRegisterID src) -
trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp
r157164 r157267 29 29 #include "CodeBlock.h" 30 30 #include "JITOperations.h" 31 #include "JSArray.h" 32 #include "JSArrayIterator.h" 31 33 #include "JSStack.h" 32 34 #include "Operations.h" … … 987 989 } 988 990 991 MacroAssemblerCodeRef arrayIteratorNextThunkGenerator(VM* vm) 992 { 993 typedef SpecializedThunkJIT::TrustedImm32 TrustedImm32; 994 typedef SpecializedThunkJIT::TrustedImmPtr TrustedImmPtr; 995 typedef SpecializedThunkJIT::Address Address; 996 typedef SpecializedThunkJIT::BaseIndex BaseIndex; 997 typedef SpecializedThunkJIT::Jump Jump; 998 999 SpecializedThunkJIT jit(vm); 1000 // Make sure we're being called on an array iterator, and load m_iteratedObject, and m_nextIndex into regT0 and regT1 respectively 1001 jit.loadArgumentWithSpecificClass(JSArrayIterator::info(), SpecializedThunkJIT::ThisArgument, SpecializedThunkJIT::regT4, SpecializedThunkJIT::regT1); 1002 1003 // Early exit if we don't have a thunk for this form of iteration 1004 jit.appendFailure(jit.branch32(SpecializedThunkJIT::AboveOrEqual, Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfIterationKind()), TrustedImm32(ArrayIterateKeyValue))); 1005 1006 jit.loadPtr(Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfIteratedObject()), SpecializedThunkJIT::regT0); 1007 1008 jit.load32(Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex()), SpecializedThunkJIT::regT1); 1009 1010 // Pull out the butterfly from iteratedObject 1011 jit.loadPtr(Address(SpecializedThunkJIT::regT0, JSCell::structureOffset()), SpecializedThunkJIT::regT2); 1012 1013 jit.load8(Address(SpecializedThunkJIT::regT2, Structure::indexingTypeOffset()), SpecializedThunkJIT::regT3); 1014 jit.loadPtr(Address(SpecializedThunkJIT::regT0, JSObject::butterflyOffset()), SpecializedThunkJIT::regT2); 1015 1016 jit.and32(TrustedImm32(IndexingShapeMask), SpecializedThunkJIT::regT3); 1017 1018 Jump notDone = jit.branch32(SpecializedThunkJIT::Below, SpecializedThunkJIT::regT1, Address(SpecializedThunkJIT::regT2, Butterfly::offsetOfPublicLength())); 1019 // Return the termination signal to indicate that we've finished 1020 jit.move(TrustedImmPtr(vm->iterationTerminator.get()), SpecializedThunkJIT::regT0); 1021 jit.returnJSCell(SpecializedThunkJIT::regT0); 1022 1023 notDone.link(&jit); 1024 1025 1026 Jump notKey = jit.branch32(SpecializedThunkJIT::NotEqual, Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfIterationKind()), TrustedImm32(ArrayIterateKey)); 1027 // If we're doing key iteration we just need to increment m_nextIndex and return the current value 1028 jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex())); 1029 jit.returnInt32(SpecializedThunkJIT::regT1); 1030 1031 notKey.link(&jit); 1032 1033 1034 // Okay, now we're returning a value so make sure we're inside the vector size 1035 jit.appendFailure(jit.branch32(SpecializedThunkJIT::AboveOrEqual, SpecializedThunkJIT::regT1, Address(SpecializedThunkJIT::regT2, Butterfly::offsetOfVectorLength()))); 1036 1037 // So now we perform inline loads for int32, value/undecided, and double storage 1038 Jump undecidedStorage = jit.branch32(SpecializedThunkJIT::Equal, SpecializedThunkJIT::regT3, TrustedImm32(UndecidedShape)); 1039 Jump notContiguousStorage = jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(ContiguousShape)); 1040 1041 undecidedStorage.link(&jit); 1042 1043 jit.loadPtr(Address(SpecializedThunkJIT::regT0, JSObject::butterflyOffset()), SpecializedThunkJIT::regT2); 1044 1045 #if USE(JSVALUE64) 1046 jit.load64(BaseIndex(SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT1, SpecializedThunkJIT::TimesEight), SpecializedThunkJIT::regT0); 1047 Jump notHole = jit.branchTest64(SpecializedThunkJIT::NonZero, SpecializedThunkJIT::regT0); 1048 jit.move(JSInterfaceJIT::TrustedImm64(ValueUndefined), JSInterfaceJIT::regT0); 1049 notHole.link(&jit); 1050 jit.addPtr(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex())); 1051 jit.returnJSValue(SpecializedThunkJIT::regT0); 1052 #else 1053 jit.load32(BaseIndex(SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT1, SpecializedThunkJIT::TimesEight, JSValue::offsetOfTag()), SpecializedThunkJIT::regT3); 1054 Jump notHole = jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(JSValue::EmptyValueTag)); 1055 jit.move(JSInterfaceJIT::TrustedImm32(JSValue::UndefinedTag), JSInterfaceJIT::regT1); 1056 jit.move(JSInterfaceJIT::TrustedImm32(0), JSInterfaceJIT::regT0); 1057 jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex())); 1058 jit.returnJSValue(SpecializedThunkJIT::regT0, JSInterfaceJIT::regT1); 1059 notHole.link(&jit); 1060 jit.load32(BaseIndex(SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT1, SpecializedThunkJIT::TimesEight, JSValue::offsetOfPayload()), SpecializedThunkJIT::regT0); 1061 jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex())); 1062 jit.move(SpecializedThunkJIT::regT3, SpecializedThunkJIT::regT1); 1063 jit.returnJSValue(SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1); 1064 #endif 1065 notContiguousStorage.link(&jit); 1066 1067 Jump notInt32Storage = jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(Int32Shape)); 1068 jit.loadPtr(Address(SpecializedThunkJIT::regT0, JSObject::butterflyOffset()), SpecializedThunkJIT::regT2); 1069 jit.load32(BaseIndex(SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT1, SpecializedThunkJIT::TimesEight, JSValue::offsetOfPayload()), SpecializedThunkJIT::regT0); 1070 jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex())); 1071 jit.returnInt32(SpecializedThunkJIT::regT0); 1072 notInt32Storage.link(&jit); 1073 1074 jit.appendFailure(jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(DoubleShape))); 1075 jit.loadPtr(Address(SpecializedThunkJIT::regT0, JSObject::butterflyOffset()), SpecializedThunkJIT::regT2); 1076 jit.loadDouble(BaseIndex(SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT1, SpecializedThunkJIT::TimesEight), SpecializedThunkJIT::fpRegT0); 1077 jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex())); 1078 jit.returnDouble(SpecializedThunkJIT::fpRegT0); 1079 1080 return jit.finalize(vm->jitStubs->ctiNativeCall(vm), "array-iterator-next"); 1081 } 1082 989 1083 } 990 1084 -
trunk/Source/JavaScriptCore/jit/ThunkGenerators.h
r157164 r157267 59 59 MacroAssemblerCodeRef powThunkGenerator(VM*); 60 60 MacroAssemblerCodeRef imulThunkGenerator(VM*); 61 MacroAssemblerCodeRef arrayIteratorNextThunkGenerator(VM*); 61 62 62 63 } -
trunk/Source/JavaScriptCore/runtime/ArrayIteratorPrototype.cpp
r157150 r157267 46 46 vm.prototypeMap.addPrototype(this); 47 47 48 JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorPrototypeNext, DontEnum, 0); 48 JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorPrototypeNext, DontEnum, 0, ArrayIteratorNextIntrinsic); 49 49 50 JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorPrivateName, arrayIteratorPrototypeIterate, DontEnum, 0); 50 51 } -
trunk/Source/JavaScriptCore/runtime/Intrinsic.h
r149159 r157267 49 49 RegExpTestIntrinsic, 50 50 StringPrototypeValueOfIntrinsic, 51 IMulIntrinsic 51 IMulIntrinsic, 52 ArrayIteratorNextIntrinsic 52 53 }; 53 54 -
trunk/Source/JavaScriptCore/runtime/JSArrayIterator.h
r156910 r157267 31 31 namespace JSC { 32 32 33 enum ArrayIterationKind {33 enum ArrayIterationKind : uint32_t { 34 34 ArrayIterateKey, 35 35 ArrayIterateValue, … … 64 64 size_t nextIndex() const { return m_nextIndex; } 65 65 void setNextIndex(size_t nextIndex) { m_nextIndex = nextIndex; } 66 void finish() { m_nextIndex = std::numeric_limits< size_t>::max(); }66 void finish() { m_nextIndex = std::numeric_limits<uint32_t>::max(); } 67 67 68 68 using JSNonFinalObject::arrayStorageOrNull; 69 static ptrdiff_t offsetOfIterationKind() { return OBJECT_OFFSETOF(JSArrayIterator, m_iterationKind); } 70 static ptrdiff_t offsetOfIteratedObject() { return OBJECT_OFFSETOF(JSArrayIterator, m_iteratedObject); } 71 static ptrdiff_t offsetOfNextIndex() { return OBJECT_OFFSETOF(JSArrayIterator, m_nextIndex); } 69 72 70 73 private: … … 83 86 ArrayIterationKind m_iterationKind; 84 87 WriteBarrier<JSObject> m_iteratedObject; 85 size_t m_nextIndex;88 uint32_t m_nextIndex; 86 89 }; 87 90 -
trunk/Source/JavaScriptCore/runtime/JSCJSValue.h
r156184 r157267 279 279 static const unsigned numberOfInt52Bits = 52; 280 280 static const unsigned int52ShiftAmount = 12; 281 282 static ptrdiff_t offsetOfPayload() { return OBJECT_OFFSETOF(JSValue, u.asBits.payload); } 283 static ptrdiff_t offsetOfTag() { return OBJECT_OFFSETOF(JSValue, u.asBits.tag); } 281 284 282 285 private: -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h
r156791 r157267 407 407 Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); } 408 408 Structure* iteratorResultStructure() const { return m_iteratorResultStructure.get(); } 409 static ptrdiff_t iteratorResultStructureOffset() { return OBJECT_OFFSETOF(JSGlobalObject, m_iteratorResultStructure); } 409 410 410 411 #if ENABLE(PROMISES) -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r157264 r157267 426 426 case IMulIntrinsic: 427 427 return imulThunkGenerator; 428 case ArrayIteratorNextIntrinsic: 429 return arrayIteratorNextThunkGenerator; 428 430 default: 429 431 return 0;
Note: See TracChangeset
for help on using the changeset viewer.