Skip to content

Commit

Permalink
Preserve asm.js code (#3362)
Browse files Browse the repository at this point in the history
* Preserve asm.js code

* Actually TEST what we want to fix, and fix the implementation. Note: If we add "initial values" to instance variables in TypeScript, they are assigned AFTER the constructor is done, while "initialise" is done DURING the constructor call
  • Loading branch information
lukastaegert committed Jan 31, 2020
1 parent a54155d commit 13d807f
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 4 deletions.
24 changes: 20 additions & 4 deletions src/ast/nodes/BlockStatement.ts
Expand Up @@ -5,13 +5,17 @@ import BlockScope from '../scopes/BlockScope';
import ChildScope from '../scopes/ChildScope';
import Scope from '../scopes/Scope';
import { UNKNOWN_EXPRESSION } from '../values';
import ExpressionStatement from './ExpressionStatement';
import * as NodeType from './NodeType';
import { IncludeChildren, Node, StatementBase, StatementNode } from './shared/Node';

export default class BlockStatement extends StatementBase {
body!: StatementNode[];
type!: NodeType.tBlockStatement;

private deoptimizeBody!: boolean;
private directlyIncluded = false;

addImplicitReturnExpressionToScope() {
const lastStatement = this.body[this.body.length - 1];
if (!lastStatement || lastStatement.type !== NodeType.ReturnStatement) {
Expand All @@ -26,6 +30,7 @@ export default class BlockStatement extends StatementBase {
}

hasEffects(context: HasEffectsContext) {
if (this.deoptimizeBody) return true;
for (const node of this.body) {
if (node.hasEffects(context)) return true;
if (context.brokenFlow) break;
Expand All @@ -34,13 +39,24 @@ export default class BlockStatement extends StatementBase {
}

include(context: InclusionContext, includeChildrenRecursively: IncludeChildren) {
this.included = true;
for (const node of this.body) {
if (includeChildrenRecursively || node.shouldBeIncluded(context))
node.include(context, includeChildrenRecursively);
if (!this.deoptimizeBody || !this.directlyIncluded) {
this.included = true;
this.directlyIncluded = true;
if (this.deoptimizeBody) includeChildrenRecursively = true;
for (const node of this.body) {
if (includeChildrenRecursively || node.shouldBeIncluded(context))
node.include(context, includeChildrenRecursively);
}
}
}

initialise() {
const firstBodyStatement = this.body[0];
this.deoptimizeBody =
firstBodyStatement instanceof ExpressionStatement &&
firstBodyStatement.directive === 'use asm';
}

render(code: MagicString, options: RenderOptions) {
if (this.body.length) {
renderStatementList(this.body, code, this.start + 1, this.end - 1, options);
Expand Down
3 changes: 3 additions & 0 deletions test/form/samples/preserve-asm-js/_config.js
@@ -0,0 +1,3 @@
module.exports = {
description: 'Preserves asm.js code (#3360)'
};
34 changes: 34 additions & 0 deletions test/form/samples/preserve-asm-js/_expected.js
@@ -0,0 +1,34 @@
function asmjs_included_1() {
'use asm';

function noop(e) {
// this is crucial
e = e | 0;
}

return { noop: noop };
}

function asmjs_included_2() {
'use asm';

function noop(e) {
e = e | 0;

switch (e | 0) {
case 10:
return 10;

default:
return e | 0;
}

// this is crucial
return e | 0;
}

return { noop: noop };
}

console.log(asmjs_included_1().noop(3));
console.log(asmjs_included_2().noop(3));
44 changes: 44 additions & 0 deletions test/form/samples/preserve-asm-js/main.js
@@ -0,0 +1,44 @@
function asmjs_included_1() {
'use asm';

function noop(e) {
// this is crucial
e = e | 0;
}

return { noop: noop };
}

function asmjs_included_2() {
'use asm';

function noop(e) {
e = e | 0;

switch (e | 0) {
case 10:
return 10;

default:
return e | 0;
}

// this is crucial
return e | 0;
}

return { noop: noop };
}

function asmjs_removed() {
'use asm';

function noop(e) {
e = e | 0;
}

return { noop: noop };
}

console.log(asmjs_included_1().noop(3));
console.log(asmjs_included_2().noop(3));

0 comments on commit 13d807f

Please sign in to comment.