Ignore:
Timestamp:
Nov 29, 2021, 12:04:08 PM (3 years ago)
Author:
[email protected]
Message:

[JSC] Public Class Field initialization is slow
https://bugs.webkit.org/show_bug.cgi?id=232479

Reviewed by Alexey Shvayka.

JSTests:

  • microbenchmarks/class-fields-classic-constructor-assignments.js: Added.

(Classic_Constructor_Assignments):
(bench):

  • microbenchmarks/class-fields-private-fields.js: Added.

(ES2022_Private_Fields):
(bench):

  • microbenchmarks/class-fields-public-fields.js: Added.

(ES2022_Public_Fields):
(bench):

  • stress/class-fields-getter-override.js: Added.

(shouldThrow):
(defineCGetter.):
(B):
(define0Getter.):
(define0Getter):
(D):

  • stress/custom-get-set-proto-chain-put.js:

(let.object.of.getObjects):

  • stress/freeze-and-seal-should-prevent-extensions.js:
  • stress/object-assign-fast-path.js:
  • stress/ordinary-set-exceptions.js:

(shouldThrow):

  • stress/put-non-reified-static-function-or-custom.js:
  • wasm/js-api/test_basic_api.js:

(const.c.in.constructorProperties.switch):

Source/JavaScriptCore:

Class public field implementation did not have optimization for initializing class fields: using
runtime call to initialize fields instead of IC. This patch leverages put_by_id / put_by_val with
direct flag so that we can enable IC.

Currently, we are not changing original putDirect semantics since it is out of this patch's scope.
We will look into it and probably changing it in a separate patch, but not in this patch.

ToT Patched

class-fields-classic-constructor-assignments

17.1491+-2.6327 15.0906+-0.6795 might be 1.1364x faster

class-fields-public-fields 409.4328+-8.3140 20.2752+-2.0835 definitely 20.1938x faster
class-fields-private-fields 27.2621+-1.3858 25.1810+-3.9873 might be 1.0826x faster

  • bytecompiler/NodesCodegen.cpp:

(JSC::DefineFieldNode::emitBytecode):

  • runtime/CommonSlowPaths.h:

(JSC::CommonSlowPaths::putDirectWithReify):

  • runtime/JSObject.cpp:

(JSC::JSObject::putDirectCustomAccessor):
(JSC::JSObject::putDirectNonIndexAccessor):

  • runtime/JSObject.h:

(JSC::JSObject::putDirect):
(JSC::JSObject::putDirectRespectingExtensibility):

  • runtime/JSObjectInlines.h:

(JSC::JSObject::putInlineFast):
(JSC::JSObject::putDirectInternal):
(JSC::JSObject::putOwnDataProperty):
(JSC::JSObject::putOwnDataPropertyMayBeIndex):

Source/WTF:

  • wtf/text/ASCIILiteral.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r284435 r286251  
    50405040    switch (m_type) {
    50415041    case DefineFieldNode::Type::Name: {
    5042         // FIXME: Improve performance of public class fields
    5043         // https://bugs.webkit.org/show_bug.cgi?id=198330
    5044         RefPtr<RegisterID> propertyName = generator.emitLoad(nullptr, *m_ident);
    5045         generator.emitCallDefineProperty(generator.thisRegister(), propertyName.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable | BytecodeGenerator::PropertyEnumerable, m_position);
     5042        StrictModeScope strictModeScope(generator);
     5043        if (auto index = parseIndex(*m_ident)) {
     5044            RefPtr<RegisterID> propertyName = generator.emitLoad(nullptr, jsNumber(index.value()));
     5045            generator.emitDirectPutByVal(generator.thisRegister(), propertyName.get(), value.get());
     5046        } else
     5047            generator.emitDirectPutById(generator.thisRegister(), *m_ident, value.get());
    50465048        break;
    50475049    }
     
    50585060    }
    50595061    case DefineFieldNode::Type::ComputedName: {
    5060         // FIXME: Improve performance of public class fields
    5061         // https://bugs.webkit.org/show_bug.cgi?id=198330
    5062 
    50635062        // For ComputedNames, the expression has already been evaluated earlier during evaluation of a ClassExprNode.
    50645063        // Here, `m_ident` refers to private symbol ID in a class lexical scope, containing the value already converted to an Expression.
     
    50735072            generator.emitSetFunctionName(value.get(), privateName.get());
    50745073        generator.emitProfileType(privateName.get(), var, m_position, m_position + m_ident->length());
    5075         generator.emitCallDefineProperty(generator.thisRegister(), privateName.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable | BytecodeGenerator::PropertyEnumerable, m_position);
     5074        {
     5075            StrictModeScope strictModeScope(generator);
     5076            generator.emitDirectPutByVal(generator.thisRegister(), privateName.get(), value.get());
     5077        }
    50765078        break;
    50775079    }
Note: See TracChangeset for help on using the changeset viewer.