Changeset 234058 in webkit


Ignore:
Timestamp:
Jul 20, 2018 11:28:28 AM (6 years ago)
Author:
Yusuke Suzuki
Message:

[JSC] A bit performance improvement for Object.assign by cleaning up code
https://bugs.webkit.org/show_bug.cgi?id=187852

Reviewed by Saam Barati.

We clean up Object.assign code a bit.

  1. Vector and MarkedArgumentBuffer are extracted out from the loop since repeatedly creating MarkedArgumentBuffer is costly.
  2. canDoFastPath is not necessary. Restructuring the code to clean up things.

It improves the performance a bit.

baseline patched

object-assign.es6 237.7719+-5.5175 231.2856+-4.6907 might be 1.0280x faster

  • runtime/ObjectConstructor.cpp:

(JSC::objectConstructorAssign):

Location:
trunk/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r234025 r234058  
     12018-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
    1222018-07-19  Carlos Garcia Campos  <cgarcia@igalia.com>
    223
  • trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp

    r234022 r234058  
    305305    bool targetCanPerformFastPut = jsDynamicCast<JSFinalObject*>(vm, target) && target->canPerformFastPutInlineExcludingProto(vm);
    306306
     307    Vector<RefPtr<UniquedStringImpl>, 8> properties;
     308    MarkedArgumentBuffer values;
    307309    unsigned argsCount = exec->argumentCount();
    308310    for (unsigned i = 1; i < argsCount; ++i) {
     
    319321            }
    320322
    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
    341367                    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
    374370                for (size_t i = 0; i < properties.size(); ++i) {
    375371                    // FIXME: We could put properties in a batching manner to accelerate Object.assign more.
     
    378374                    target->putOwnDataProperty(vm, properties[i].get(), values.at(i), putPropertySlot);
    379375                }
    380 
    381376                continue;
    382377            }
Note: See TracChangeset for help on using the changeset viewer.