Closed Bug 1700052 Opened 4 years ago Closed 4 years ago

Move getters/setters from AccessorShape to object slots

Categories

(Core :: JavaScript Engine, task, P3)

task

Tracking

()

RESOLVED FIXED
89 Branch
Tracking Status
firefox89 --- fixed

People

(Reporter: jandem, Assigned: jandem)

References

(Blocks 2 open bugs)

Details

Attachments

(17 files)

48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review

Getters/setters are currently stored in the shape tree, in AccessorShapes. The reasons for doing it this way were mostly historical, as far as I know: we already supported JSGetterOp and JSSetterOp getters/setters and that code was reused when implementing ES5 getter/setter objects.

There are a number of problems with this:

  • Branchy shape trees when lambdas are used as getters/setters can result in performance cliffs and wasting memory. See the micro-benchmark below for an example of this.
  • It complicates the shape code because data properties and accessor properties are so different.
  • Certain changes to the object layout we're considering are not possible.

The plan here is as follows:

  1. Remove JSGetterOp/JSSetterOp (bug 1404885). Today these are only used for array.length and ArgumentsObject, and I think we can handle these special cases with a special property attribute instead.

  2. Add a GetterSetterPair GC thing, a tuple holding just the getter/setter objects. Use this in AccessorShape.

  3. Store GetterSetterPair in an object slot as PrivateGCThingValue. Remove AccessorShape.

This will require an extra CacheIR guard for getter/setter calls. This is likely acceptable compared to the call overhead, and this could be optimized away in the future if needed (since most getters/setters are on prototype objects, we could use fuses to invalidate code when redefining an accessor property).


Here's a micro-benchmark where a getter property makes accessing a data property much slower (28 ms => 204 ms).

function init() {
	var objs = [];
	for (var i = 0; i < 128; i++) {
		objs.push({get foo() {}, x: 1});
	}
	return objs;
}
function test(objs) {
	var res = 0;
	for (var i = 0; i < 10_000_000; i++) {
		res += objs[i % 128].x;
	}
	return res;
}
var objs = init();
var t = dateNow();
var res = test(objs);
print(dateNow() - t);
print(res);
Depends on: 1701895
Depends on: 1701897

For now these just forward to the equivalent methods on the shape, but that
will change in a later patch.

This way the code will do the right thing when the shape no longer implies a specific
getter object.

A later patch will change this so we store just the slot number instead of the
species property shape.

Depends on D110248

This is preparing for a later patch.

Depends on D110250

Also clean up the similar Push method a bit to use PropertyKey instead of jsid.

Depends on D110251

We currently get the jsid from the property's shape, but in a later patch that
Shape* argument will be replaced with a GetterSetter* argument.

I considered using PropertyKey instead of jsid, but this matches similar code
using jsid.

Depends on D110252

This turned out to be a bit more work than expected because we were missing
branch32/branchPtr implementations taking a BaseIndex and a Register.

Depends on D110253

These will be used in a later patch to guard obj[slot] == PrivateGCThingValue(GetterSetter*).

Depends on D110254

There will be additional cleanup of the Shape code in follow-up patches.

Depends on D110257

Because these methods are now also used for accessor properties.

Depends on D110260

This is a bit faster than getting the slot number from the shape every time.

Depends on D110261

Keywords: leave-open
Pushed by jdemooij@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/3af530ddacc9 part 1 - Add methods to NativeObject for accessing getter/setter objects. r=jonco https://hg.mozilla.org/integration/autoland/rev/d5eb51b405c4 part 2 - Check getter object identity in ArraySpeciesLookup and PromiseLookup. r=jonco https://hg.mozilla.org/integration/autoland/rev/56f4a105ca52 part 3 - Use isDataProperty instead of !isAccessorShape in a few places. r=jonco https://hg.mozilla.org/integration/autoland/rev/a4d18ab82fef part 4 - Simplify and optimize AddOrChangeProperty a bit. r=jonco https://hg.mozilla.org/integration/autoland/rev/b3219fb7aa9b part 5 - Add movePropertyKey to the MacroAssembler. r=iain

Use this instead of checking !isCustomDataProperty (and before this stack, !isDataProperty).

Pushed by jdemooij@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/8540f6f82ab6 part 6 - Pass jsid to ObjectHasGetterSetterPure. r=iain https://hg.mozilla.org/integration/autoland/rev/bf62a6aa5aa4 part 7 - Add branchTestValue overload to the MacroAssembler. r=iain https://hg.mozilla.org/integration/autoland/rev/a91c9a837ba6 part 8 - Add GuardFixedSlotValue and GuardDynamicSlotValue CacheIR instructions. r=iain https://hg.mozilla.org/integration/autoland/rev/fc6b5fb92749 part 9 - Add js::GetterSetter GC thing. r=jonco https://hg.mozilla.org/integration/autoland/rev/7e3a27b38e56 part 10 - Add support for GetterSetter stub fields. r=iain
Regressions: 1703434
Pushed by jdemooij@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/c4825995d926 part 11 - Store getter/setter objects in slots instead of in the shape tree. r=jonco,evilpie https://hg.mozilla.org/integration/autoland/rev/40b1b6f502ca part 12 - Remove more AccessorShape code. r=jonco https://hg.mozilla.org/integration/autoland/rev/1bee1c7dabac part 13 - Simplify and rename some functions that are now only used for custom data properties. r=jonco https://hg.mozilla.org/integration/autoland/rev/89d1c5483930 part 14 - Rename DataProperty to Property in a few places. r=jonco https://hg.mozilla.org/integration/autoland/rev/3ad3acac6cf6 part 15 - Use slot number instead of property shape for ArraySpeciesLookup and PromiseLookup. r=jonco https://hg.mozilla.org/integration/autoland/rev/55012db38df0 part 16 - Add tests for accessor properties. r=jonco https://hg.mozilla.org/integration/autoland/rev/b00dca6a4995 part 17 - Add Shape::hasSlot. r=jonco
Keywords: leave-open
Blocks: 1703469
Blocks: 1703470
Blocks: ReShape
Regressions: 1705453
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: