Changeset 236496 in webkit
- Timestamp:
- Sep 25, 2018, 10:16:22 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 9 added
- 3 edited
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/stress/array-lastindexof-array-prototype-trap.js (added)
-
JSTests/stress/array-lastindexof-cached-length.js (added)
-
JSTests/stress/array-lastindexof-fast-path-effects.js (added)
-
JSTests/stress/array-lastindexof-have-a-bad-time-c-runtime.js (added)
-
JSTests/stress/array-lastindexof-hole-nan.js (added)
-
JSTests/stress/array-lastindexof-infinity.js (added)
-
JSTests/stress/array-lastindexof-negative-zero.js (added)
-
JSTests/stress/array-lastindexof-own-getter.js (added)
-
JSTests/stress/array-lastindexof-prototype-trap.js (added)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/runtime/ArrayPrototype.cpp (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r236495 r236496 1 2018-09-20 Yusuke Suzuki <yusukesuzuki@slowstart.org> 2 3 [JSC] Optimize Array#lastIndexOf 4 https://bugs.webkit.org/show_bug.cgi?id=189780 5 6 Reviewed by Saam Barati. 7 8 * stress/array-lastindexof-array-prototype-trap.js: Added. 9 (shouldBe): 10 (AncestorArray.prototype.get 2): 11 (AncestorArray): 12 * stress/array-lastindexof-have-a-bad-time-c-runtime.js: Added. 13 (shouldBe): 14 * stress/array-lastindexof-hole-nan.js: Added. 15 (shouldBe): 16 (throw.new.Error): 17 * stress/array-lastindexof-infinity.js: Added. 18 (shouldBe): 19 (throw.new.Error): 20 * stress/array-lastindexof-negative-zero.js: Added. 21 (shouldBe): 22 (throw.new.Error): 23 * stress/array-lastindexof-own-getter.js: Added. 24 (shouldBe): 25 (throw.new.Error.get array): 26 (get array): 27 * stress/array-lastindexof-prototype-trap.js: Added. 28 (shouldBe): 29 (DerivedArray.prototype.get 2): 30 (DerivedArray): 31 1 32 2018-09-25 Saam Barati <sbarati@apple.com> 2 33 -
trunk/Source/JavaScriptCore/ChangeLog
r236495 r236496 1 2018-09-20 Yusuke Suzuki <yusukesuzuki@slowstart.org> 2 3 [JSC] Optimize Array#lastIndexOf 4 https://bugs.webkit.org/show_bug.cgi?id=189780 5 6 Reviewed by Saam Barati. 7 8 Optimize Array#lastIndexOf as the same to Array#indexOf. We add a fast path 9 for JSArray with contiguous storage. 10 11 * runtime/ArrayPrototype.cpp: 12 (JSC::arrayProtoFuncLastIndexOf): 13 1 14 2018-09-25 Saam Barati <sbarati@apple.com> 2 15 -
trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
r236437 r236496 1151 1151 } 1152 1152 1153 enum class IndexOfDirection { Forward, Backward }; 1154 template<IndexOfDirection direction> 1155 ALWAYS_INLINE JSValue fastIndexOf(ExecState* exec, VM& vm, JSArray* array, unsigned length, JSValue searchElement, unsigned index) 1156 { 1157 auto scope = DECLARE_THROW_SCOPE(vm); 1158 1159 bool canDoFastPath = array->canDoFastIndexedAccess(vm) 1160 && array->getArrayLength() == length; // The effects in getting `index` could have changed the length of this array. 1161 if (!canDoFastPath) 1162 return JSValue(); 1163 1164 switch (array->indexingType()) { 1165 case ALL_INT32_INDEXING_TYPES: { 1166 if (!searchElement.isNumber()) 1167 return jsNumber(-1); 1168 JSValue searchInt32; 1169 if (searchElement.isInt32()) 1170 searchInt32 = searchElement; 1171 else { 1172 double searchNumber = searchElement.asNumber(); 1173 if (!canBeInt32(searchNumber)) 1174 return jsNumber(-1); 1175 searchInt32 = jsNumber(static_cast<int32_t>(searchNumber)); 1176 } 1177 auto& butterfly = *array->butterfly(); 1178 auto data = butterfly.contiguous().data(); 1179 if (direction == IndexOfDirection::Forward) { 1180 for (; index < length; ++index) { 1181 // Array#indexOf uses `===` semantics (not HashMap isEqual semantics). 1182 // And the hole never matches against Int32 value. 1183 if (searchInt32 == data[index].get()) 1184 return jsNumber(index); 1185 } 1186 } else { 1187 do { 1188 ASSERT(index < length); 1189 // Array#lastIndexOf uses `===` semantics (not HashMap isEqual semantics). 1190 // And the hole never matches against Int32 value. 1191 if (searchInt32 == data[index].get()) 1192 return jsNumber(index); 1193 } while (index--); 1194 } 1195 return jsNumber(-1); 1196 } 1197 case ALL_CONTIGUOUS_INDEXING_TYPES: { 1198 auto& butterfly = *array->butterfly(); 1199 auto data = butterfly.contiguous().data(); 1200 1201 if (direction == IndexOfDirection::Forward) { 1202 for (; index < length; ++index) { 1203 JSValue value = data[index].get(); 1204 if (!value) 1205 continue; 1206 bool isEqual = JSValue::strictEqual(exec, searchElement, value); 1207 RETURN_IF_EXCEPTION(scope, { }); 1208 if (isEqual) 1209 return jsNumber(index); 1210 } 1211 } else { 1212 do { 1213 ASSERT(index < length); 1214 JSValue value = data[index].get(); 1215 if (!value) 1216 continue; 1217 bool isEqual = JSValue::strictEqual(exec, searchElement, value); 1218 RETURN_IF_EXCEPTION(scope, { }); 1219 if (isEqual) 1220 return jsNumber(index); 1221 } while (index--); 1222 } 1223 return jsNumber(-1); 1224 } 1225 case ALL_DOUBLE_INDEXING_TYPES: { 1226 if (!searchElement.isNumber()) 1227 return jsNumber(-1); 1228 double searchNumber = searchElement.asNumber(); 1229 auto& butterfly = *array->butterfly(); 1230 auto data = butterfly.contiguousDouble().data(); 1231 if (direction == IndexOfDirection::Forward) { 1232 for (; index < length; ++index) { 1233 // Array#indexOf uses `===` semantics (not HashMap isEqual semantics). 1234 // And the hole never matches since it is NaN. 1235 if (data[index] == searchNumber) 1236 return jsNumber(index); 1237 } 1238 } else { 1239 do { 1240 ASSERT(index < length); 1241 // Array#lastIndexOf uses `===` semantics (not HashMap isEqual semantics). 1242 // And the hole never matches since it is NaN. 1243 if (data[index] == searchNumber) 1244 return jsNumber(index); 1245 } while (index--); 1246 } 1247 return jsNumber(-1); 1248 } 1249 default: 1250 return JSValue(); 1251 } 1252 } 1253 1153 1254 EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec) 1154 1255 { … … 1169 1270 1170 1271 if (isJSArray(thisObject)) { 1171 JSArray* array = asArray(thisObject); 1172 bool canDoFastPath = array->canDoFastIndexedAccess(vm) 1173 && array->getArrayLength() == length; // The effects in getting `index` could have changed the length of this array. 1174 if (canDoFastPath) { 1175 switch (array->indexingType()) { 1176 case ALL_INT32_INDEXING_TYPES: { 1177 if (!searchElement.isNumber()) 1178 return JSValue::encode(jsNumber(-1)); 1179 JSValue searchInt32; 1180 if (searchElement.isInt32()) 1181 searchInt32 = searchElement; 1182 else { 1183 double searchNumber = searchElement.asNumber(); 1184 if (!canBeInt32(searchNumber)) 1185 return JSValue::encode(jsNumber(-1)); 1186 searchInt32 = jsNumber(static_cast<int32_t>(searchNumber)); 1187 } 1188 auto& butterfly = *array->butterfly(); 1189 auto data = butterfly.contiguous().data(); 1190 for (; index < length; ++index) { 1191 // Array#indexOf uses `===` semantics (not HashMap isEqual semantics). 1192 // And the hole never matches against Int32 value. 1193 if (searchInt32 == data[index].get()) 1194 return JSValue::encode(jsNumber(index)); 1195 } 1196 return JSValue::encode(jsNumber(-1)); 1197 } 1198 case ALL_CONTIGUOUS_INDEXING_TYPES: { 1199 auto& butterfly = *array->butterfly(); 1200 auto data = butterfly.contiguous().data(); 1201 for (; index < length; ++index) { 1202 JSValue value = data[index].get(); 1203 if (!value) 1204 continue; 1205 bool isEqual = JSValue::strictEqual(exec, searchElement, value); 1206 RETURN_IF_EXCEPTION(scope, { }); 1207 if (isEqual) 1208 return JSValue::encode(jsNumber(index)); 1209 } 1210 return JSValue::encode(jsNumber(-1)); 1211 } 1212 case ALL_DOUBLE_INDEXING_TYPES: { 1213 if (!searchElement.isNumber()) 1214 return JSValue::encode(jsNumber(-1)); 1215 double searchNumber = searchElement.asNumber(); 1216 auto& butterfly = *array->butterfly(); 1217 auto data = butterfly.contiguousDouble().data(); 1218 for (; index < length; ++index) { 1219 // Array#indexOf uses `===` semantics (not HashMap isEqual semantics). 1220 // And the hole never matches since it is NaN. 1221 if (data[index] == searchNumber) 1222 return JSValue::encode(jsNumber(index)); 1223 } 1224 return JSValue::encode(jsNumber(-1)); 1225 } 1226 default: 1227 break; 1228 } 1229 } 1272 if (JSValue result = fastIndexOf<IndexOfDirection::Forward>(exec, vm, asArray(thisObject), length, searchElement, index)) 1273 return JSValue::encode(result); 1230 1274 } 1231 1275 … … 1250 1294 1251 1295 // 15.4.4.15 1252 JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);1253 EXCEPTION_ASSERT(!!scope.exception() == !thisObj );1254 if (UNLIKELY(!thisObj ))1255 return encodedJSValue();1256 unsigned length = toLength(exec, thisObj );1296 JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec); 1297 EXCEPTION_ASSERT(!!scope.exception() == !thisObject); 1298 if (UNLIKELY(!thisObject)) 1299 return { }; 1300 unsigned length = toLength(exec, thisObject); 1257 1301 if (UNLIKELY(scope.exception()) || !length) 1258 1302 return JSValue::encode(jsNumber(-1)); … … 1262 1306 JSValue fromValue = exec->uncheckedArgument(1); 1263 1307 double fromDouble = fromValue.toInteger(exec); 1264 RETURN_IF_EXCEPTION(scope, encodedJSValue());1308 RETURN_IF_EXCEPTION(scope, { }); 1265 1309 if (fromDouble < 0) { 1266 1310 fromDouble += length; … … 1273 1317 1274 1318 JSValue searchElement = exec->argument(0); 1319 1320 if (isJSArray(thisObject)) { 1321 if (JSValue result = fastIndexOf<IndexOfDirection::Backward>(exec, vm, asArray(thisObject), length, searchElement, index)) 1322 return JSValue::encode(result); 1323 } 1324 1275 1325 do { 1276 RELEASE_ASSERT(index < length);1277 JSValue e = getProperty(exec, thisObj , index);1278 RETURN_IF_EXCEPTION(scope, encodedJSValue());1326 ASSERT(index < length); 1327 JSValue e = getProperty(exec, thisObject, index); 1328 RETURN_IF_EXCEPTION(scope, { }); 1279 1329 if (!e) 1280 1330 continue; 1281 1331 bool isEqual = JSValue::strictEqual(exec, searchElement, e); 1282 RETURN_IF_EXCEPTION(scope, encodedJSValue());1332 RETURN_IF_EXCEPTION(scope, { }); 1283 1333 if (isEqual) 1284 1334 return JSValue::encode(jsNumber(index));
Note:
See TracChangeset
for help on using the changeset viewer.