Changeset 286251 in webkit
- Timestamp:
- Nov 29, 2021 12:04:08 PM (8 months ago)
- Location:
- trunk
- Files:
-
- 4 added
- 15 edited
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/microbenchmarks/class-fields-classic-constructor-assignments.js (added)
-
JSTests/microbenchmarks/class-fields-private-fields.js (added)
-
JSTests/microbenchmarks/class-fields-public-fields.js (added)
-
JSTests/stress/class-fields-getter-override.js (added)
-
JSTests/stress/custom-get-set-proto-chain-put.js (modified) (1 diff)
-
JSTests/stress/freeze-and-seal-should-prevent-extensions.js (modified) (2 diffs)
-
JSTests/stress/object-assign-fast-path.js (modified) (1 diff)
-
JSTests/stress/ordinary-set-exceptions.js (modified) (2 diffs)
-
JSTests/stress/put-non-reified-static-function-or-custom.js (modified) (1 diff)
-
JSTests/wasm/js-api/test_basic_api.js (modified) (1 diff)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/CommonSlowPaths.h (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/JSObject.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/JSObject.h (modified) (4 diffs)
-
Source/JavaScriptCore/runtime/JSObjectInlines.h (modified) (13 diffs)
-
Source/WTF/ChangeLog (modified) (1 diff)
-
Source/WTF/wtf/text/ASCIILiteral.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r286249 r286251 1 2021-11-29 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] Public Class Field initialization is slow 4 https://bugs.webkit.org/show_bug.cgi?id=232479 5 6 Reviewed by Alexey Shvayka. 7 8 * microbenchmarks/class-fields-classic-constructor-assignments.js: Added. 9 (Classic_Constructor_Assignments): 10 (bench): 11 * microbenchmarks/class-fields-private-fields.js: Added. 12 (ES2022_Private_Fields): 13 (bench): 14 * microbenchmarks/class-fields-public-fields.js: Added. 15 (ES2022_Public_Fields): 16 (bench): 17 * stress/class-fields-getter-override.js: Added. 18 (shouldThrow): 19 (defineCGetter.): 20 (B): 21 (define0Getter.): 22 (define0Getter): 23 (D): 24 * stress/custom-get-set-proto-chain-put.js: 25 (let.object.of.getObjects): 26 * stress/freeze-and-seal-should-prevent-extensions.js: 27 * stress/object-assign-fast-path.js: 28 * stress/ordinary-set-exceptions.js: 29 (shouldThrow): 30 * stress/put-non-reified-static-function-or-custom.js: 31 * wasm/js-api/test_basic_api.js: 32 (const.c.in.constructorProperties.switch): 33 1 34 2021-11-29 Yusuke Suzuki <ysuzuki@apple.com> 2 35 -
trunk/JSTests/stress/custom-get-set-proto-chain-put.js
r280256 r286251 122 122 Object.preventExtensions(object); 123 123 for (let i = 0; i < 100; ++i) { 124 shouldThrow(() => { object.customValueNoSetter = {}; }, "TypeError: Attempt ed to assign to readonly property.");124 shouldThrow(() => { object.customValueNoSetter = {}; }, "TypeError: Attempting to define property on object that is not extensible."); 125 125 assert(!Reflect.set(object, "customValueNoSetter", {})); 126 126 } -
trunk/JSTests/stress/freeze-and-seal-should-prevent-extensions.js
r192858 r286251 32 32 shouldBe(object.Matcha, 'Matcha'); 33 33 shouldBe(Reflect.isExtensible(object), false); 34 shouldThrow(() => object.Mocha = 'Mocha', `TypeError: Attempt ed to assign to readonly property.`);34 shouldThrow(() => object.Mocha = 'Mocha', `TypeError: Attempting to define property on object that is not extensible.`); 35 35 }()); 36 36 … … 48 48 shouldBe(object.Matcha, 'Matcha'); 49 49 shouldBe(Reflect.isExtensible(object), false); 50 shouldThrow(() => object.Mocha = 'Mocha', `TypeError: Attempt ed to assign to readonly property.`);50 shouldThrow(() => object.Mocha = 'Mocha', `TypeError: Attempting to define property on object that is not extensible.`); 51 51 }()); -
trunk/JSTests/stress/object-assign-fast-path.js
r280460 r286251 181 181 shouldThrow(() => { 182 182 Object.assign(object, { bar: 2 }); 183 }, `TypeError: Attempt ed to assign to readonly property.`);183 }, `TypeError: Attempting to define property on object that is not extensible.`); 184 184 shouldBe(object.bar, undefined); 185 185 } -
trunk/JSTests/stress/ordinary-set-exceptions.js
r198270 r286251 64 64 }), true); 65 65 receiver.cocoa = 'NG'; 66 }, `TypeError: Attempt ed to assign toreadonly property.`);66 }, `TypeError: Attempting to change value of a readonly property.`); 67 67 68 68 // 9.1.9.1 4-d-ii … … 86 86 }), true); 87 87 receiver.cocoa = 'NG'; 88 }, `TypeError: Attempt ed to assign toreadonly property.`);88 }, `TypeError: Attempting to change value of a readonly property.`); 89 89 90 90 // 9.1.9.1 7 -
trunk/JSTests/stress/put-non-reified-static-function-or-custom.js
r278589 r286251 126 126 Object.preventExtensions(heir); 127 127 128 shouldThrow(() => { heir[key] = testValue; }, "TypeError: Attempt ed to assign to readonly property.", key);128 shouldThrow(() => { heir[key] = testValue; }, "TypeError: Attempting to define property on object that is not extensible.", key); 129 129 assert(heir[key] !== testValue, key); 130 130 assert(object[key] !== testValue, key); -
trunk/JSTests/wasm/js-api/test_basic_api.js
r274609 r286251 87 87 assert.eq(Symbol.toStringTag in instance.exports, false); 88 88 assert.eq(Object.getOwnPropertySymbols(instance.exports).length, 0); 89 assert.throws(() => instance.exports[Symbol.toStringTag] = 42, TypeError, `Attempt ed to assign to readonly property.`);89 assert.throws(() => instance.exports[Symbol.toStringTag] = 42, TypeError, `Attempting to define property on object that is not extensible.`); 90 90 break; 91 91 case "Memory": -
trunk/Source/JavaScriptCore/ChangeLog
r286249 r286251 1 2021-11-29 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] Public Class Field initialization is slow 4 https://bugs.webkit.org/show_bug.cgi?id=232479 5 6 Reviewed by Alexey Shvayka. 7 8 Class public field implementation did not have optimization for initializing class fields: using 9 runtime call to initialize fields instead of IC. This patch leverages put_by_id / put_by_val with 10 direct flag so that we can enable IC. 11 12 Currently, we are not changing original putDirect semantics since it is out of this patch's scope. 13 We will look into it and probably changing it in a separate patch, but not in this patch. 14 15 ToT Patched 16 17 class-fields-classic-constructor-assignments 18 17.1491+-2.6327 15.0906+-0.6795 might be 1.1364x faster 19 class-fields-public-fields 409.4328+-8.3140 ^ 20.2752+-2.0835 ^ definitely 20.1938x faster 20 class-fields-private-fields 27.2621+-1.3858 25.1810+-3.9873 might be 1.0826x faster 21 22 * bytecompiler/NodesCodegen.cpp: 23 (JSC::DefineFieldNode::emitBytecode): 24 * runtime/CommonSlowPaths.h: 25 (JSC::CommonSlowPaths::putDirectWithReify): 26 * runtime/JSObject.cpp: 27 (JSC::JSObject::putDirectCustomAccessor): 28 (JSC::JSObject::putDirectNonIndexAccessor): 29 * runtime/JSObject.h: 30 (JSC::JSObject::putDirect): 31 (JSC::JSObject::putDirectRespectingExtensibility): 32 * runtime/JSObjectInlines.h: 33 (JSC::JSObject::putInlineFast): 34 (JSC::JSObject::putDirectInternal): 35 (JSC::JSObject::putOwnDataProperty): 36 (JSC::JSObject::putOwnDataPropertyMayBeIndex): 37 1 38 2021-11-29 Yusuke Suzuki <ysuzuki@apple.com> 2 39 -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r284435 r286251 5040 5040 switch (m_type) { 5041 5041 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()); 5046 5048 break; 5047 5049 } … … 5058 5060 } 5059 5061 case DefineFieldNode::Type::ComputedName: { 5060 // FIXME: Improve performance of public class fields5061 // https://bugs.webkit.org/show_bug.cgi?id=1983305062 5063 5062 // For ComputedNames, the expression has already been evaluated earlier during evaluation of a ClassExprNode. 5064 5063 // Here, `m_ident` refers to private symbol ID in a class lexical scope, containing the value already converted to an Expression. … … 5073 5072 generator.emitSetFunctionName(value.get(), privateName.get()); 5074 5073 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 } 5076 5078 break; 5077 5079 } -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h
r284700 r286251 36 36 #include "SlowPathFunction.h" 37 37 #include "StackAlignment.h" 38 #include "TypeError.h" 38 39 #include "VMInlines.h" 39 40 #include <wtf/StdLibExtras.h> … … 187 188 } 188 189 189 190 190 static ALWAYS_INLINE void putDirectWithReify(VM& vm, JSGlobalObject* globalObject, JSObject* baseObject, PropertyName propertyName, JSValue value, PutPropertySlot& slot, Structure** result = nullptr) 191 191 { 192 192 auto scope = DECLARE_THROW_SCOPE(vm); 193 if (baseObject->inherits<JSFunction>(vm)) { 193 bool isJSFunction = baseObject->inherits<JSFunction>(vm); 194 if (isJSFunction) { 194 195 jsCast<JSFunction*>(baseObject)->reifyLazyPropertyIfNeeded(vm, globalObject, propertyName); 195 196 RETURN_IF_EXCEPTION(scope, void()); … … 197 198 if (result) 198 199 *result = originalStructureBeforePut(vm, baseObject); 199 scope.release(); 200 baseObject->putDirect(vm, propertyName, value, slot); 200 201 Structure* structure = baseObject->structure(vm); 202 if (LIKELY(propertyName != vm.propertyNames->underscoreProto && !structure->hasReadOnlyOrGetterSetterPropertiesExcludingProto() && (isJSFunction || structure->classInfo()->methodTable.defineOwnProperty == &JSObject::defineOwnProperty))) { 203 auto error = baseObject->putDirectRespectingExtensibility(vm, propertyName, value, 0, slot); 204 if (!error.isNull()) 205 typeError(globalObject, scope, slot.isStrictMode(), error); 206 } else { 207 slot.disableCaching(); 208 scope.release(); 209 PropertyDescriptor descriptor(value, 0); 210 baseObject->methodTable(vm)->defineOwnProperty(baseObject, globalObject, propertyName, descriptor, slot.isStrictMode()); 211 } 201 212 } 202 213 -
trunk/Source/JavaScriptCore/runtime/JSObject.cpp
r285687 r286251 2007 2007 2008 2008 PutPropertySlot slot(this); 2009 bool result = putDirectInternal<PutModeDefineOwnProperty >(vm, propertyName, value, attributes, slot);2009 bool result = putDirectInternal<PutModeDefineOwnPropertyIgnoringExtensibility>(vm, propertyName, value, attributes, slot).isNull(); 2010 2010 2011 2011 ASSERT(slot.type() == PutPropertySlot::NewProperty); … … 2038 2038 ASSERT(attributes & PropertyAttribute::Accessor); 2039 2039 PutPropertySlot slot(this); 2040 bool result = putDirectInternal<PutModeDefineOwnProperty >(vm, propertyName, accessor, attributes, slot);2040 bool result = putDirectInternal<PutModeDefineOwnPropertyIgnoringExtensibility>(vm, propertyName, accessor, attributes, slot).isNull(); 2041 2041 2042 2042 Structure* structure = this->structure(vm); -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r285730 r286251 101 101 JS_EXPORT_PRIVATE friend bool setUpStaticFunctionSlot(VM&, const HashTableValue*, JSObject*, PropertyName, PropertySlot&); 102 102 103 enum PutMode {103 enum PutMode : uint8_t { 104 104 PutModePut, 105 105 PutModeDefineOwnProperty, 106 PutModeDefineOwnPropertyIgnoringExtensibility, 106 107 }; 107 108 … … 686 687 bool putDirect(VM&, PropertyName, JSValue, unsigned attributes, PutPropertySlot&); 687 688 bool putDirect(VM&, PropertyName, JSValue, PutPropertySlot&); 689 ASCIILiteral putDirectRespectingExtensibility(VM&, PropertyName, JSValue, unsigned attributes, PutPropertySlot&); 688 690 void putDirectWithoutTransition(VM&, PropertyName, JSValue, unsigned attributes = 0); 689 691 bool putDirectNonIndexAccessor(VM&, PropertyName, GetterSetter*, unsigned attributes); … … 1157 1159 1158 1160 template<PutMode> 1159 bool putDirectInternal(VM&, PropertyName, JSValue, unsigned attr, PutPropertySlot&);1161 ASCIILiteral putDirectInternal(VM&, PropertyName, JSValue, unsigned attr, PutPropertySlot&); 1160 1162 1161 1163 JS_EXPORT_PRIVATE NEVER_INLINE bool putInlineSlow(JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&); … … 1583 1585 ASSERT(!value.isCustomGetterSetter() && !(attributes & PropertyAttribute::CustomAccessorOrValue)); 1584 1586 PutPropertySlot slot(this); 1585 return putDirectInternal<PutModeDefineOwnProperty >(vm, propertyName, value, attributes, slot);1587 return putDirectInternal<PutModeDefineOwnPropertyIgnoringExtensibility>(vm, propertyName, value, attributes, slot).isNull(); 1586 1588 } 1587 1589 1588 1590 inline bool JSObject::putDirect(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot) 1591 { 1592 ASSERT(!value.isGetterSetter()); 1593 ASSERT(!value.isCustomGetterSetter()); 1594 return putDirectInternal<PutModeDefineOwnPropertyIgnoringExtensibility>(vm, propertyName, value, attributes, slot).isNull(); 1595 } 1596 1597 inline bool JSObject::putDirect(VM& vm, PropertyName propertyName, JSValue value, PutPropertySlot& slot) 1598 { 1599 ASSERT(!value.isGetterSetter()); 1600 ASSERT(!value.isCustomGetterSetter()); 1601 return putDirectInternal<PutModeDefineOwnPropertyIgnoringExtensibility>(vm, propertyName, value, 0, slot).isNull(); 1602 } 1603 1604 inline ASCIILiteral JSObject::putDirectRespectingExtensibility(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot) 1589 1605 { 1590 1606 ASSERT(!value.isGetterSetter()); 1591 1607 ASSERT(!value.isCustomGetterSetter()); 1592 1608 return putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot); 1593 }1594 1595 inline bool JSObject::putDirect(VM& vm, PropertyName propertyName, JSValue value, PutPropertySlot& slot)1596 {1597 ASSERT(!value.isGetterSetter());1598 ASSERT(!value.isCustomGetterSetter());1599 return putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, 0, slot);1600 1609 } 1601 1610 -
trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h
r284330 r286251 283 283 auto scope = DECLARE_THROW_SCOPE(vm); 284 284 285 // FIXME: For a failure due to non-extensible structure, the error message is misleading286 if (! putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot))287 return typeError(globalObject, scope, slot.isStrictMode(), ReadonlyPropertyWriteError);285 auto error = putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot); 286 if (!error.isNull()) 287 return typeError(globalObject, scope, slot.isStrictMode(), error); 288 288 return true; 289 289 } … … 320 320 321 321 template<JSObject::PutMode mode> 322 ALWAYS_INLINE bool JSObject::putDirectInternal(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot)322 ALWAYS_INLINE ASCIILiteral JSObject::putDirectInternal(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot) 323 323 { 324 324 ASSERT(value); … … 336 336 PropertyOffset offset = structure->get(vm, propertyName, currentAttributes); 337 337 if (offset != invalidOffset) { 338 if ((mode == PutModePut ) && currentAttributes & PropertyAttribute::ReadOnlyOrAccessorOrCustomAccessor)339 return false;338 if ((mode == PutModePut || mode == PutModeDefineOwnProperty) && currentAttributes & PropertyAttribute::ReadOnlyOrAccessorOrCustomAccessor) 339 return ReadonlyPropertyChangeError; 340 340 341 341 putDirect(vm, offset, value); … … 344 344 // FIXME: Check attributes against PropertyAttribute::CustomAccessorOrValue. Changing GetterSetter should work w/o transition. 345 345 // https://bugs.webkit.org/show_bug.cgi?id=214342 346 if ( mode == PutModeDefineOwnProperty&& (attributes != currentAttributes || (attributes & PropertyAttribute::AccessorOrCustomAccessorOrValue)))346 if ((mode == PutModeDefineOwnProperty || mode == PutModeDefineOwnPropertyIgnoringExtensibility) && (attributes != currentAttributes || (attributes & PropertyAttribute::AccessorOrCustomAccessorOrValue))) 347 347 setStructure(vm, Structure::attributeChangeTransition(vm, structure, propertyName, attributes)); 348 348 else { … … 351 351 } 352 352 353 return true;353 return ASCIILiteral::null(); 354 354 } 355 355 356 if ((mode == PutModePut ) && !isStructureExtensible(vm))357 return false;356 if ((mode == PutModePut || mode == PutModeDefineOwnProperty) && !isStructureExtensible(vm)) 357 return NonExtensibleObjectPropertyDefineError; 358 358 359 359 offset = prepareToPutDirectWithoutTransition(vm, propertyName, attributes, structureID, structure); … … 363 363 if (attributes & PropertyAttribute::ReadOnly) 364 364 this->structure(vm)->setContainsReadOnlyProperties(); 365 return true;365 return ASCIILiteral::null(); 366 366 } 367 367 … … 387 387 setStructure(vm, newStructure); 388 388 slot.setNewProperty(this, offset); 389 return true;389 return ASCIILiteral::null(); 390 390 } 391 391 … … 393 393 offset = structure->get(vm, propertyName, currentAttributes); 394 394 if (offset != invalidOffset) { 395 if ((mode == PutModePut ) && currentAttributes & PropertyAttribute::ReadOnlyOrAccessorOrCustomAccessor)396 return false;395 if ((mode == PutModePut || mode == PutModeDefineOwnProperty) && currentAttributes & PropertyAttribute::ReadOnlyOrAccessorOrCustomAccessor) 396 return ReadonlyPropertyChangeError; 397 397 398 398 structure->didReplaceProperty(offset); … … 401 401 // FIXME: Check attributes against PropertyAttribute::CustomAccessorOrValue. Changing GetterSetter should work w/o transition. 402 402 // https://bugs.webkit.org/show_bug.cgi?id=214342 403 if ( mode == PutModeDefineOwnProperty&& (attributes != currentAttributes || (attributes & PropertyAttribute::AccessorOrCustomAccessorOrValue))) {403 if ((mode == PutModeDefineOwnProperty || mode == PutModeDefineOwnPropertyIgnoringExtensibility) && (attributes != currentAttributes || (attributes & PropertyAttribute::AccessorOrCustomAccessorOrValue))) { 404 404 // We want the structure transition watchpoint to fire after this object has switched structure. 405 405 // This allows adaptive watchpoints to observe if the new structure is the one we want. … … 411 411 } 412 412 413 return true;414 } 415 416 if ((mode == PutModePut ) && !isStructureExtensible(vm))417 return false;413 return ASCIILiteral::null(); 414 } 415 416 if ((mode == PutModePut || mode == PutModeDefineOwnProperty) && !isStructureExtensible(vm)) 417 return NonExtensibleObjectPropertyDefineError; 418 418 419 419 // We want the structure transition watchpoint to fire after this object has switched structure. … … 440 440 if (attributes & PropertyAttribute::ReadOnly) 441 441 newStructure->setContainsReadOnlyProperties(); 442 return true;442 return ASCIILiteral::null(); 443 443 } 444 444 … … 574 574 { 575 575 validatePutOwnDataProperty(vm, propertyName, value); 576 return putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot) ;576 return putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot).isNull(); 577 577 } 578 578 … … 584 584 return putDirectIndex(globalObject, index.value(), value, 0, PutDirectIndexLikePutDirect); 585 585 586 return putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot) ;586 return putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot).isNull(); 587 587 } 588 588 -
trunk/Source/WTF/ChangeLog
r286248 r286251 1 2021-11-29 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] Public Class Field initialization is slow 4 https://bugs.webkit.org/show_bug.cgi?id=232479 5 6 Reviewed by Alexey Shvayka. 7 8 * wtf/text/ASCIILiteral.h: 9 1 10 2021-11-29 Yusuke Suzuki <ysuzuki@apple.com> 2 11 -
trunk/Source/WTF/wtf/text/ASCIILiteral.h
r285048 r286251 50 50 } 51 51 52 constexpr bool isNull() const { return !m_characters; } 53 52 54 constexpr const char* characters() const { return m_characters; } 53 55 const LChar* characters8() const { return bitwise_cast<const LChar*>(m_characters); }
Note: See TracChangeset
for help on using the changeset viewer.