Permalink
Show file tree
Hide file tree
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
[JSC] Remove unnecessary mov bytecodes when performing simple object …
…pattern destructuring to variables https://bugs.webkit.org/show_bug.cgi?id=220219 Reviewed by Alexey Shvayka. JSTests: * stress/object-pattern-simple-fast-path.js: Added. (shouldBe): (shouldThrow): (test1): Source/JavaScriptCore: Currently, we are first puts object pattern's expression into temporary variable, and then, we store it into local variable register. The following code ({ data } = object); emits this kind of bytecode. get_by_id dst:loc10, base:loc9, property:0 mov dst:loc6, src:loc10 However, this should be get_by_id dst:loc6, base:loc9, property:0 We are emitting many unnecessary movs since this destructuring pattern is common. Increasing amount of mov (1) discourages inlining unnecessarily and (2) simply makes bytecode memory large. Since this is very common pattern, we should carefully optimize it to remove such unnecessary movs. This patch looks into pattern when performing object pattern destructuring. And avoid emitting mov when it is possible. There are some cases we cannot remove movs, so this patch's writableDirectBindingIfPossible looks into whether this is possible (& profitable). * bytecompiler/NodesCodegen.cpp: (JSC::ObjectPatternNode::bindValue const): (JSC::BindingNode::writableDirectBindingIfPossible const): (JSC::BindingNode::finishDirectBindingAssignment const): (JSC::AssignmentElementNode::writableDirectBindingIfPossible const): (JSC::AssignmentElementNode::finishDirectBindingAssignment const): * parser/Nodes.h: (JSC::DestructuringPatternNode::writableDirectBindingIfPossible const): (JSC::DestructuringPatternNode::finishDirectBindingAssignment const): Canonical link: https://commits.webkit.org/232718@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271121 268f45cc-cd09-0410-ab3c-d52691b4dbfc
- Loading branch information
1 parent
9a400c0
commit 5629a596c77a98749acb993b28072d0ee1672720
Showing
5 changed files
with
284 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
function shouldBe(actual, expected) { | ||
if (actual !== expected) | ||
throw new Error('bad value: ' + actual); | ||
} | ||
|
||
function shouldThrow(func, errorMessage) { | ||
var errorThrown = false; | ||
var error = null; | ||
try { | ||
func(); | ||
} catch (e) { | ||
errorThrown = true; | ||
error = e; | ||
} | ||
if (!errorThrown) | ||
throw new Error('not thrown'); | ||
if (String(error) !== errorMessage) | ||
throw new Error(`bad error: ${String(error)}`); | ||
} | ||
|
||
function test1({ data }) { | ||
return data; | ||
} | ||
|
||
shouldBe(test1({ data: 42 }), 42); | ||
|
||
shouldThrow(() => { | ||
const data = 42; | ||
({ data } = { data: 50 }); | ||
}, `TypeError: Attempted to assign to readonly property.`); | ||
|
||
(function () { | ||
const { data } = { data: 50 }; | ||
shouldBe(data, 50); | ||
}()); | ||
|
||
shouldThrow(() => { | ||
const { data } = data; | ||
}, `ReferenceError: Cannot access uninitialized variable.`); | ||
|
||
shouldThrow(() => { | ||
const { [throwing()]: data } = { data: 50 }; | ||
function throwing() { | ||
data; | ||
} | ||
}, `ReferenceError: Cannot access uninitialized variable.`); | ||
|
||
(function () { | ||
let data = 42; | ||
({ data } = { data: 50 }); | ||
shouldBe(data, 50); | ||
}()); | ||
|
||
(function () { | ||
let { data } = { data: 50 }; | ||
shouldBe(data, 50); | ||
}()); | ||
|
||
shouldThrow(() => { | ||
let { data } = data; | ||
}, `ReferenceError: Cannot access uninitialized variable.`); | ||
|
||
shouldThrow(() => { | ||
let { [throwing()]: data } = { data: 50 }; | ||
function throwing() { | ||
data; | ||
} | ||
}, `ReferenceError: Cannot access uninitialized variable.`); | ||
|
||
shouldThrow(() => { | ||
let { [data = 'data']: data } = { data: 50 }; | ||
}, `ReferenceError: Cannot access uninitialized variable.`); | ||
|
||
(function () { | ||
let { [43]: data } = { 43: 50 }; | ||
shouldBe(data, 50); | ||
}()); | ||
|
||
(function () { | ||
let called1 = false; | ||
let called2 = false; | ||
let data = 42; | ||
({ [throwing()]: data, ...ok } = { data: 50 }); | ||
function throwing() { | ||
called1 = true; | ||
shouldBe(data, 42); | ||
return { | ||
toString() { | ||
called2 = true; | ||
shouldBe(data, 42); | ||
return 'data'; | ||
} | ||
}; | ||
} | ||
shouldBe(data, 50); | ||
shouldBe(called1, true); | ||
shouldBe(called2, true); | ||
}()); | ||
|
||
(function () { | ||
let data = 'ok'; | ||
let obj; | ||
({ [data]: data, ...obj } = { ok: 'bad', bad: 42 }); | ||
shouldBe(data, 'bad'); | ||
shouldBe(obj.bad, 42); | ||
}()); | ||
|
||
(function () { | ||
globalThis.testing = 42; | ||
({ testing } = { testing: 50 }); | ||
shouldBe(testing, 50); | ||
}()); | ||
|
||
(function () { | ||
var { data } = { data: 50 }; | ||
shouldBe(data, 50); | ||
}()); | ||
|
||
(function () { | ||
var { data } = { data: data }; | ||
shouldBe(data, undefined); | ||
}()); | ||
|
||
Reflect.defineProperty(globalThis, 'readOnly', { | ||
value: 30 | ||
}); | ||
|
||
shouldThrow(() => { | ||
'use strict'; | ||
({ readOnly } = { readOnly: 42 }); | ||
}, `TypeError: Attempted to assign to readonly property.`); | ||
|
||
(function () { | ||
({ readOnly } = { readOnly: 42 }); | ||
shouldBe(readOnly, 30); | ||
}()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters