Changeset 234058 in webkit
- Timestamp:
- Jul 20, 2018 11:28:28 AM (6 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r234025 r234058 1 2018-07-20 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] A bit performance improvement for Object.assign by cleaning up code 4 https://bugs.webkit.org/show_bug.cgi?id=187852 5 6 Reviewed by Saam Barati. 7 8 We clean up Object.assign code a bit. 9 10 1. Vector and MarkedArgumentBuffer are extracted out from the loop since repeatedly creating MarkedArgumentBuffer is costly. 11 2. canDoFastPath is not necessary. Restructuring the code to clean up things. 12 13 It improves the performance a bit. 14 15 baseline patched 16 17 object-assign.es6 237.7719+-5.5175 231.2856+-4.6907 might be 1.0280x faster 18 19 * runtime/ObjectConstructor.cpp: 20 (JSC::objectConstructorAssign): 21 1 22 2018-07-19 Carlos Garcia Campos <cgarcia@igalia.com> 2 23 -
trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
r234022 r234058 305 305 bool targetCanPerformFastPut = jsDynamicCast<JSFinalObject*>(vm, target) && target->canPerformFastPutInlineExcludingProto(vm); 306 306 307 Vector<RefPtr<UniquedStringImpl>, 8> properties; 308 MarkedArgumentBuffer values; 307 309 unsigned argsCount = exec->argumentCount(); 308 310 for (unsigned i = 1; i < argsCount; ++i) { … … 319 321 } 320 322 321 bool canDoFastPath; 322 Vector<RefPtr<UniquedStringImpl>, 8> properties; 323 MarkedArgumentBuffer values; 324 { 325 auto canPerformFastPropertyEnumerationForObjectAssign = [] (Structure* structure) { 326 if (structure->typeInfo().overridesGetOwnPropertySlot()) 327 return false; 328 if (structure->typeInfo().overridesGetPropertyNames()) 329 return false; 330 // FIXME: Indexed properties can be handled. 331 // https://bugs.webkit.org/show_bug.cgi?id=185358 332 if (hasIndexedProperties(structure->indexingType())) 333 return false; 334 if (structure->hasGetterSetterProperties()) 335 return false; 336 if (structure->isUncacheableDictionary()) 337 return false; 338 // Cannot perform fast [[Put]] to |target| if the property names of the |source| contain "__proto__". 339 if (structure->hasUnderscoreProtoPropertyExcludingOriginalProto()) 340 return false; 323 auto canPerformFastPropertyEnumerationForObjectAssign = [] (Structure* structure) { 324 if (structure->typeInfo().overridesGetOwnPropertySlot()) 325 return false; 326 if (structure->typeInfo().overridesGetPropertyNames()) 327 return false; 328 // FIXME: Indexed properties can be handled. 329 // https://bugs.webkit.org/show_bug.cgi?id=185358 330 if (hasIndexedProperties(structure->indexingType())) 331 return false; 332 if (structure->hasGetterSetterProperties()) 333 return false; 334 if (structure->isUncacheableDictionary()) 335 return false; 336 // Cannot perform fast [[Put]] to |target| if the property names of the |source| contain "__proto__". 337 if (structure->hasUnderscoreProtoPropertyExcludingOriginalProto()) 338 return false; 339 return true; 340 }; 341 342 if (canPerformFastPropertyEnumerationForObjectAssign(source->structure(vm))) { 343 // |source| Structure does not have any getters. And target can perform fast put. 344 // So enumerating properties and putting properties are non observable. 345 346 // FIXME: It doesn't seem like we should have to do this in two phases, but 347 // we're running into crashes where it appears that source is transitioning 348 // under us, and even ends up in a state where it has a null butterfly. My 349 // leading hypothesis here is that we fire some value replacement watchpoint 350 // that ends up transitioning the structure underneath us. 351 // https://bugs.webkit.org/show_bug.cgi?id=187837 352 353 // Do not clear since Vector::clear shrinks the backing store. 354 properties.resize(0); 355 values.clear(); 356 source->structure(vm)->forEachProperty(vm, [&] (const PropertyMapEntry& entry) -> bool { 357 if (entry.attributes & PropertyAttribute::DontEnum) 358 return true; 359 360 PropertyName propertyName(entry.key); 361 if (propertyName.isPrivateName()) 362 return true; 363 364 properties.append(entry.key); 365 values.appendWithCrashOnOverflow(source->getDirect(entry.offset)); 366 341 367 return true; 342 }; 343 344 Structure* structure = source->structure(vm); 345 canDoFastPath = canPerformFastPropertyEnumerationForObjectAssign(structure); 346 if (canDoFastPath) { 347 // |source| Structure does not have any getters. And target can perform fast put. 348 // So enumerating properties and putting properties are non observable. 349 350 // FIXME: It doesn't seem like we should have to do this in two phases, but 351 // we're running into crashes where it appears that source is transitioning 352 // under us, and even ends up in a state where it has a null butterfly. My 353 // leading hypothesis here is that we fire some value replacement watchpoint 354 // that ends up transitioning the structure underneath us. 355 // https://bugs.webkit.org/show_bug.cgi?id=187837 356 357 structure->forEachProperty(vm, [&] (const PropertyMapEntry& entry) -> bool { 358 if (entry.attributes & PropertyAttribute::DontEnum) 359 return true; 360 361 PropertyName propertyName(entry.key); 362 if (propertyName.isPrivateName()) 363 return true; 364 365 properties.append(entry.key); 366 values.appendWithCrashOnOverflow(source->getDirect(entry.offset)); 367 368 return true; 369 }); 370 } 371 } 372 373 if (canDoFastPath) { 368 }); 369 374 370 for (size_t i = 0; i < properties.size(); ++i) { 375 371 // FIXME: We could put properties in a batching manner to accelerate Object.assign more. … … 378 374 target->putOwnDataProperty(vm, properties[i].get(), values.at(i), putPropertySlot); 379 375 } 380 381 376 continue; 382 377 }
Note: See TracChangeset
for help on using the changeset viewer.