Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always request a new tree-shaking pass when deoptimizations are performed #4111

Merged
merged 1 commit into from May 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Module.ts
Expand Up @@ -109,6 +109,7 @@ export interface AstContext {
moduleContext: string;
nodeConstructors: { [name: string]: typeof NodeBase };
options: NormalizedInputOptions;
requestTreeshakingPass: () => void;
traceExport: (name: string) => Variable | null;
traceVariable: (name: string) => Variable | null;
usesTopLevelAwait: boolean;
Expand Down Expand Up @@ -726,6 +727,7 @@ export default class Module {
moduleContext: this.context,
nodeConstructors,
options: this.options,
requestTreeshakingPass: () => (this.graph.needsTreeshakingPass = true),
traceExport: this.getVariableForExportName.bind(this),
traceVariable: this.traceVariable.bind(this),
usesTopLevelAwait: false,
Expand Down
1 change: 1 addition & 0 deletions src/ast/nodes/AssignmentExpression.ts
Expand Up @@ -126,5 +126,6 @@ export default class AssignmentExpression extends NodeBase {
this.deoptimized = true;
this.left.deoptimizePath(EMPTY_PATH);
this.right.deoptimizePath(UNKNOWN_PATH);
this.context.requestTreeshakingPass();
}
}
1 change: 1 addition & 0 deletions src/ast/nodes/AssignmentPattern.ts
Expand Up @@ -48,5 +48,6 @@ export default class AssignmentPattern extends NodeBase implements PatternNode {
this.deoptimized = true;
this.left.deoptimizePath(EMPTY_PATH);
this.right.deoptimizePath(UNKNOWN_PATH);
this.context.requestTreeshakingPass();
}
}
1 change: 1 addition & 0 deletions src/ast/nodes/CallExpression.ts
Expand Up @@ -298,6 +298,7 @@ export default class CallExpression extends NodeBase implements DeoptimizableEnt
// This will make sure all properties of parameters behave as "unknown"
argument.deoptimizePath(UNKNOWN_PATH);
}
this.context.requestTreeshakingPass();
}

private getReturnExpression(
Expand Down
1 change: 1 addition & 0 deletions src/ast/nodes/ForInStatement.ts
Expand Up @@ -65,5 +65,6 @@ export default class ForInStatement extends StatementBase {
protected applyDeoptimizations(): void {
this.deoptimized = true;
this.left.deoptimizePath(EMPTY_PATH);
this.context.requestTreeshakingPass();
}
}
1 change: 1 addition & 0 deletions src/ast/nodes/ForOfStatement.ts
Expand Up @@ -50,5 +50,6 @@ export default class ForOfStatement extends StatementBase {
protected applyDeoptimizations(): void {
this.deoptimized = true;
this.left.deoptimizePath(EMPTY_PATH);
this.context.requestTreeshakingPass();
}
}
1 change: 1 addition & 0 deletions src/ast/nodes/Identifier.ts
Expand Up @@ -178,6 +178,7 @@ export default class Identifier extends NodeBase implements PatternNode {
this.deoptimized = true;
if (this.variable !== null && this.variable instanceof LocalVariable) {
this.variable.consolidateInitializers();
this.context.requestTreeshakingPass();
}
}

Expand Down
1 change: 1 addition & 0 deletions src/ast/nodes/MemberExpression.ts
Expand Up @@ -329,6 +329,7 @@ export default class MemberExpression extends NodeBase implements DeoptimizableE
SHARED_RECURSION_TRACKER
);
}
this.context.requestTreeshakingPass();
}
}

Expand Down
1 change: 1 addition & 0 deletions src/ast/nodes/NewExpression.ts
Expand Up @@ -46,5 +46,6 @@ export default class NewExpression extends NodeBase {
// This will make sure all properties of parameters behave as "unknown"
argument.deoptimizePath(UNKNOWN_PATH);
}
this.context.requestTreeshakingPass();
}
}
1 change: 1 addition & 0 deletions src/ast/nodes/Property.ts
Expand Up @@ -46,6 +46,7 @@ export default class Property extends MethodBase implements PatternNode {
this.deoptimized = true;
if (this.declarationInit !== null) {
this.declarationInit.deoptimizePath([UnknownKey, UnknownKey]);
this.context.requestTreeshakingPass();
}
}
}
1 change: 1 addition & 0 deletions src/ast/nodes/RestElement.ts
Expand Up @@ -37,6 +37,7 @@ export default class RestElement extends NodeBase implements PatternNode {
this.deoptimized = true;
if (this.declarationInit !== null) {
this.declarationInit.deoptimizePath([UnknownKey, UnknownKey]);
this.context.requestTreeshakingPass();
}
}
}
1 change: 1 addition & 0 deletions src/ast/nodes/SpreadElement.ts
Expand Up @@ -30,5 +30,6 @@ export default class SpreadElement extends NodeBase {
// Only properties of properties of the argument could become subject to reassignment
// This will also reassign the return values of iterators
this.argument.deoptimizePath([UnknownKey, UnknownKey]);
this.context.requestTreeshakingPass();
}
}
1 change: 1 addition & 0 deletions src/ast/nodes/UnaryExpression.ts
Expand Up @@ -59,6 +59,7 @@ export default class UnaryExpression extends NodeBase {
this.deoptimized = true;
if (this.operator === 'delete') {
this.argument.deoptimizePath(EMPTY_PATH);
this.context.requestTreeshakingPass();
}
}
}
1 change: 1 addition & 0 deletions src/ast/nodes/UpdateExpression.ts
Expand Up @@ -87,5 +87,6 @@ export default class UpdateExpression extends NodeBase {
const variable = this.scope.findVariable(this.argument.name);
variable.isReassigned = true;
}
this.context.requestTreeshakingPass();
}
}
6 changes: 5 additions & 1 deletion src/ast/nodes/YieldExpression.ts
Expand Up @@ -30,6 +30,10 @@ export default class YieldExpression extends NodeBase {

protected applyDeoptimizations(): void {
this.deoptimized = true;
this.argument?.deoptimizePath(UNKNOWN_PATH);
const { argument } = this;
if (argument) {
argument.deoptimizePath(UNKNOWN_PATH);
this.context.requestTreeshakingPass();
}
}
}
@@ -0,0 +1,10 @@
const assert = require('assert');
const result = { value: 0 };

module.exports = {
description: 'makes sure to request additional passes when a variable is deoptimized',
context: { result },
exports() {
assert.strictEqual(result.value, 2);
}
};
17 changes: 17 additions & 0 deletions test/function/samples/deoptimize-request-treeshaking-pass/main.js
@@ -0,0 +1,17 @@
function heisenbug() {
var a = false;
function f(b) {
if (a) a === b.c ? result.value++ : result.value--;
a = b.c;
}
function g() {}
function h() {
f({
c: g
});
}
h();
h();
}
heisenbug();
heisenbug();