[Webkit-unassigned] [Bug 248754] New: Improve Object.defineProperties & Object.defineProperty perf via fast iteration in ToPropertyDescriptor
bugzilla-daemon at webkit.org
bugzilla-daemon at webkit.org
Mon Dec 5 01:21:19 PST 2022
https://bugs.webkit.org/show_bug.cgi?id=248754
Bug ID: 248754
Summary: Improve Object.defineProperties &
Object.defineProperty perf via fast iteration in
ToPropertyDescriptor
Product: WebKit
Version: WebKit Nightly Build
Hardware: Unspecified
OS: Unspecified
Status: NEW
Severity: Normal
Priority: P2
Component: JavaScriptCore
Assignee: webkit-unassigned at lists.webkit.org
Reporter: jarred at jarredsumner.com
A diff like this in ObjectConstructor::toPropertyDescriptor improves Object.defineProperties perf 15% - 70%
```
if (canPerformFastPropertyEnumerationForObjectAssign(description->structure())) {
description->structure()->forEachProperty(vm, [&] (const PropertyTableEntry& entry) -> bool {
if (entry.attributes() & PropertyAttribute::DontEnum)
return true;
PropertyName propertyName(entry.key());
if (propertyName == propertyNames->enumerable) {
desc.setEnumerable(description->getDirect(entry.offset()).toBoolean(globalObject));
RETURN_IF_EXCEPTION(scope, false);
} else if (propertyName == propertyNames->configurable) {
desc.setConfigurable(description->getDirect(entry.offset()).toBoolean(globalObject));
RETURN_IF_EXCEPTION(scope, false);
} else if (propertyName == propertyNames->value) {
desc.setValue(description->getDirect(entry.offset()));
RETURN_IF_EXCEPTION(scope, false);
} else if (propertyName == propertyNames->writable) {
desc.setWritable(description->getDirect(entry.offset()).toBoolean(globalObject));
RETURN_IF_EXCEPTION(scope, false);
} else if (propertyName == propertyNames->get) {
JSValue getter = description->getDirect(entry.offset());
RETURN_IF_EXCEPTION(scope, false);
if (!getter.isUndefinedOrNull() && !getter.isCallable()) {
throwTypeError(globalObject, scope, "Getter must be a function."_s);
return false;
}
desc.setGetter(getter);
} else if (propertyName == propertyNames->set) {
JSValue setter = description->getDirect(entry.offset());
RETURN_IF_EXCEPTION(scope, false);
if (!setter.isUndefinedOrNull() && !setter.isCallable()) {
throwTypeError(globalObject, scope, "Setter must be a function."_s);
return false;
}
desc.setSetter(setter);
}
return true;
});
RETURN_IF_EXCEPTION(scope, false);
} else {
```
This diff isn't 100% correct but fast iteration through each of the leaf property descriptor objects when possible should improve perf
Here is a microbenchmark:
```
import { bench, run } from "../node_modules/mitata/src/cli.mjs";
const properties = {
closed: {
get() {
return this._writableState ? this._writableState.closed : false;
},
},
destroyed: {
get() {
return this._writableState ? this._writableState.destroyed : false;
},
set(value) {
if (this._writableState) {
this._writableState.destroyed = value;
}
},
},
writable: {
get() {
const w = this._writableState;
return (
!!w &&
w.writable !== false &&
!w.destroyed &&
!w.errored &&
!w.ending &&
!w.ended
);
},
set(val) {
if (this._writableState) {
this._writableState.writable = !!val;
}
},
},
writableFinished: {
get() {
return this._writableState ? this._writableState.finished : false;
},
},
writableObjectMode: {
get() {
return this._writableState ? this._writableState.objectMode : false;
},
},
writableBuffer: {
get() {
return this._writableState && this._writableState.getBuffer();
},
},
writableEnded: {
get() {
return this._writableState ? this._writableState.ending : false;
},
},
writableNeedDrain: {
get() {
const wState = this._writableState;
if (!wState) return false;
return !wState.destroyed && !wState.ending && wState.needDrain;
},
},
writableHighWaterMark: {
get() {
return this._writableState && this._writableState.highWaterMark;
},
},
writableCorked: {
get() {
return this._writableState ? this._writableState.corked : 0;
},
},
writableLength: {
get() {
return this._writableState && this._writableState.length;
},
},
errored: {
enumerable: false,
get() {
return this._writableState ? this._writableState.errored : null;
},
},
writableAborted: {
enumerable: false,
get: function () {
return !!(
this._writableState.writable !== false &&
(this._writableState.destroyed || this._writableState.errored) &&
!this._writableState.finished
);
},
},
};
var count = 10_000;
bench("Object.defineProperty x " + count, () => {
const prop = {
enumerable: false,
get: function () {
return !!(
this._writableState.writable !== false &&
(this._writableState.destroyed || this._writableState.errored) &&
!this._writableState.finished
);
},
};
for (let i = 0; i < count; i++) {
function Hey() {
return this;
}
Object.defineProperty(Hey.prototype, "writableAborted", prop);
}
});
bench("Object.defineProperties x " + count, () => {
for (let i = 0; i < count; i++) {
function Hey() {
return this;
}
Object.defineProperties(Hey.prototype, properties);
}
});
bench("(all the keys) Object.defineProperties x " + count, () => {
var first;
{
function Hey() {
return this;
}
Object.defineProperties(Hey.prototype, properties);
first = Object.getOwnPropertyDescriptors(Hey.prototype);
}
for (let i = 0; i < count; i++) {
function Hey() {
return this;
}
Object.defineProperties(Hey.prototype, first);
}
});
await run();
```
--
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20221205/d1d5037c/attachment-0001.htm>
More information about the webkit-unassigned
mailing list