remove __label__ settings in hoisted blocks and if we are sure the label setting is unimportant because the next code after us is not a check for the label
This commit is contained in:
Родитель
b724d8ba0b
Коммит
a914110dac
|
@ -667,36 +667,44 @@ function optimizeShiftsAggressive(ast) {
|
|||
optimizeShiftsInternal(ast, false);
|
||||
}
|
||||
|
||||
function simplifyExpressionsPost(ast) {
|
||||
// We often have branchings that are simplified so one end vanishes, and
|
||||
// we then get
|
||||
// if (!(x < 5))
|
||||
// or such. Simplifying these saves space and time.
|
||||
function simplifyNotComps(ast) {
|
||||
traverse(ast, function(node, type) {
|
||||
if (type == 'unary-prefix' && node[1] == '!' && node[2][0] == 'binary') {
|
||||
if (node[2][1] == '<') {
|
||||
return ['binary', '>=', node[2][2], node[2][3]];
|
||||
} else if (node[2][1] == '>') {
|
||||
return ['binary', '<=', node[2][2], node[2][3]];
|
||||
} else if (node[2][1] == '==') {
|
||||
return ['binary', '!=', node[2][2], node[2][3]];
|
||||
} else if (node[2][1] == '!=') {
|
||||
return ['binary', '==', node[2][2], node[2][3]];
|
||||
} else if (node[2][1] == '===') {
|
||||
return ['binary', '!==', node[2][2], node[2][3]];
|
||||
} else if (node[2][1] == '!==') {
|
||||
return ['binary', '===', node[2][2], node[2][3]];
|
||||
}
|
||||
// We often have branchings that are simplified so one end vanishes, and
|
||||
// we then get
|
||||
// if (!(x < 5))
|
||||
// or such. Simplifying these saves space and time.
|
||||
function simplifyNotComps(ast) {
|
||||
traverse(ast, function(node, type) {
|
||||
if (type == 'unary-prefix' && node[1] == '!' && node[2][0] == 'binary') {
|
||||
if (node[2][1] == '<') {
|
||||
return ['binary', '>=', node[2][2], node[2][3]];
|
||||
} else if (node[2][1] == '>') {
|
||||
return ['binary', '<=', node[2][2], node[2][3]];
|
||||
} else if (node[2][1] == '==') {
|
||||
return ['binary', '!=', node[2][2], node[2][3]];
|
||||
} else if (node[2][1] == '!=') {
|
||||
return ['binary', '==', node[2][2], node[2][3]];
|
||||
} else if (node[2][1] == '===') {
|
||||
return ['binary', '!==', node[2][2], node[2][3]];
|
||||
} else if (node[2][1] == '!==') {
|
||||
return ['binary', '===', node[2][2], node[2][3]];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Go
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function simplifyExpressionsPost(ast) {
|
||||
simplifyNotComps(ast);
|
||||
}
|
||||
|
||||
function hasSideEffects(node) { // this is 99% incomplete and wrong! It just works on __label__ == X and number literals
|
||||
if (node[0] == 'num') return false;
|
||||
if (node[0] == 'binary' && (node[1] == '==' || node[1] == '!=') && node[2][0] == 'name' &&
|
||||
node[3][0] == 'num') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear out empty ifs and blocks, and redundant blocks/stats and so forth
|
||||
function vacuum(ast) {
|
||||
function isEmpty(node) {
|
||||
|
@ -729,18 +737,9 @@ function vacuum(ast) {
|
|||
}
|
||||
var type = node[0];
|
||||
if (type == 'defun' && isGenerated(node[1])) {
|
||||
simplifyNotComps(node);
|
||||
traverse(node, function(node, type) {
|
||||
if (type == 'if') {
|
||||
if (((node[2][0] == 'block' && (!node[2][1] || node[2][1].length == 0)) ||
|
||||
jsonCompare(node[2], emptyNode())) && !node[3]) {
|
||||
more = true;
|
||||
return emptyNode();
|
||||
} else if (node[3] && isEmpty(node[3])) {
|
||||
more = true;
|
||||
node[3] = null;
|
||||
return node;
|
||||
}
|
||||
} else if (type == 'block' && node[1] && node[1].length == 1 && node[1][0][0] == 'block') {
|
||||
if (type == 'block' && node[1] && node[1].length == 1 && node[1][0][0] == 'block') {
|
||||
more = true;
|
||||
return node[1][0];
|
||||
} else if (type == 'stat' && node[1][0] == 'block') {
|
||||
|
@ -762,9 +761,25 @@ function vacuum(ast) {
|
|||
} else if (type == 'label' && jsonCompare(node[2], emptyNode())) {
|
||||
more = true;
|
||||
return emptyNode();
|
||||
} else if (type == 'if' && isEmpty(node[3])) { // empty else clauses
|
||||
node[3] = null;
|
||||
return node;
|
||||
} else if (type == 'if') {
|
||||
var empty2 = isEmpty(node[2]), empty3 = isEmpty(node[3]), has3 = node.length == 4;
|
||||
if (!empty2 && empty3 && has3) { // empty else clauses
|
||||
more = true;
|
||||
return node.slice(0, 3);
|
||||
} else if (empty2 && !empty3) { // empty if blocks
|
||||
more = true;
|
||||
return ['if', ['unary-prefix', '!', node[1]], node[3]];
|
||||
} else if (empty2 && empty3) {
|
||||
more = true;
|
||||
if (hasSideEffects(node[1])) {
|
||||
return ['stat', node[1]];
|
||||
} else {
|
||||
return emptyNode();
|
||||
}
|
||||
}
|
||||
} else if (type == 'do' && isEmpty(node[2]) && !hasSideEffects(node[1])) {
|
||||
more = true;
|
||||
return emptyNode();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -772,6 +787,16 @@ function vacuum(ast) {
|
|||
}
|
||||
}
|
||||
|
||||
function getStatements(node) {
|
||||
if (node[0] == 'defun') {
|
||||
return node[3];
|
||||
} else if (node[0] == 'block') {
|
||||
return node[1];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Multiple blocks from the relooper are, in general, implemented by
|
||||
// if (__label__ == x) { } else if ..
|
||||
// and branching into them by
|
||||
|
@ -781,12 +806,7 @@ function hoistMultiples(ast) {
|
|||
ast[1].forEach(function(node, i) {
|
||||
if (!(node[0] == 'defun' && isGenerated(node[1]))) return;
|
||||
traverse(node, function(node, type) {
|
||||
var statements = null;
|
||||
if (type == 'defun') {
|
||||
statements = node[3];
|
||||
} else if (type == 'block') {
|
||||
statements = node[1];
|
||||
}
|
||||
var statements = getStatements(node);
|
||||
if (!statements) return;
|
||||
var modified = false;
|
||||
for (var i = 0; i < statements.length-1; i++) {
|
||||
|
@ -833,11 +853,11 @@ function hoistMultiples(ast) {
|
|||
if (!found && preType == 'assign' && preNode[2][0] == 'name' && preNode[2][1] == '__label__') {
|
||||
assert(preNode[3][0] == 'num');
|
||||
if (preNode[3][1] == labelNum) {
|
||||
// That's it! Hoist away
|
||||
// That's it! Hoist away. We can also throw away the __label__ setting as its goal has already been achieved
|
||||
found = true;
|
||||
modifiedI = true;
|
||||
postInner[2] = ['block', []];
|
||||
return ['block', [preNode].concat(labelBlock[1])];
|
||||
return labelBlock;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -850,6 +870,45 @@ function hoistMultiples(ast) {
|
|||
}
|
||||
if (modified) return node;
|
||||
});
|
||||
|
||||
// After hoisting in this function, it is safe to remove { __label__ = x; } blocks, because
|
||||
// if they were leading to the next code right after them, they would be hoisted, and if they
|
||||
// are going to some other place entirely, they would break or continue. The only risky
|
||||
// situation is if the code after us is a multiple, in which case we might be checking for
|
||||
// this label inside it (or in a later multiple, even)
|
||||
function tryEliminate(node) {
|
||||
if (node[0] == 'if') {
|
||||
if (tryEliminate(node[2])) node[2] = emptyNode();
|
||||
if (node[3] && tryEliminate(node[3])) node[3] = emptyNode();
|
||||
} else {
|
||||
if (node[0] == 'block' && node[1] && node[1].length == 1) {
|
||||
var subNode = node[1][0];
|
||||
if (subNode[0] == 'stat' && subNode[1][0] == 'assign' && subNode[1][2][0] == 'name' &&
|
||||
subNode[1][2][1] == '__label__' && subNode[1][3][0] == 'num') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function getActualStatement(node) { // find the actual active statement, ignoring a label and one-time do loop
|
||||
if (node[0] == 'label') node = node[2];
|
||||
if (node[0] == 'do') node = node[2];
|
||||
if (node[0] == 'block' && node[1].length == 1) node = node[1][0];
|
||||
return node;
|
||||
}
|
||||
vacuum([0, [node]]);
|
||||
traverse(node, function(node, type) {
|
||||
var statements = getStatements(node);
|
||||
if (!statements) return;
|
||||
for (var i = 0; i < statements.length-1; i++) {
|
||||
var curr = getActualStatement(statements[i]);
|
||||
var next = statements[i+1];
|
||||
if (curr[0] == 'if' && next[0] != 'if' && next[0] != 'label' && next[0] != 'do' && next[0] != 'while') {
|
||||
tryEliminate(curr);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
vacuum(ast);
|
||||
|
|
|
@ -99,62 +99,80 @@ function maths() {
|
|||
}
|
||||
function hoisting() {
|
||||
if ($i < $N) {
|
||||
__label__ = 2;
|
||||
callOther();
|
||||
}
|
||||
pause(1);
|
||||
$for_body3$$for_end$5 : do {
|
||||
if ($i < $N) {
|
||||
__label__ = 2;
|
||||
while (true) {
|
||||
break $for_body3$$for_end$5;
|
||||
}
|
||||
callOther();
|
||||
} else {
|
||||
__label__ = 3;
|
||||
}
|
||||
} while (0);
|
||||
pause(2);
|
||||
do {
|
||||
if ($i < $N) {
|
||||
__label__ = 2;
|
||||
if (callOther()) break;
|
||||
} else {
|
||||
__label__ = 3;
|
||||
}
|
||||
} while (0);
|
||||
pause(3);
|
||||
if ($i < $N) {
|
||||
__label__ = 2;
|
||||
callOther();
|
||||
} else {
|
||||
__label__ = 3;
|
||||
}
|
||||
pause(4);
|
||||
if ($i < $N) {
|
||||
__label__ = 2;
|
||||
callOther();
|
||||
} else {
|
||||
__label__ = 3;
|
||||
somethingElse();
|
||||
}
|
||||
pause(5);
|
||||
if ($i < $N) {
|
||||
__label__ = 2;
|
||||
} else {
|
||||
__label__ = 3;
|
||||
somethingElse();
|
||||
}
|
||||
if (__label__ == 55) {
|
||||
callOther();
|
||||
}
|
||||
pause(6);
|
||||
if ($i < $N) {
|
||||
__label__ = 2;
|
||||
} else {
|
||||
__label__ = 3;
|
||||
if ($i >= $N) {
|
||||
somethingElse();
|
||||
}
|
||||
pause(7);
|
||||
while (1) {
|
||||
if ($i < $N) {
|
||||
somethingElse();
|
||||
} else {
|
||||
__label__ = 3;
|
||||
break;
|
||||
}
|
||||
if ($i < $N) {
|
||||
somethingElse();
|
||||
}
|
||||
nothing();
|
||||
}
|
||||
pause(8);
|
||||
var $cmp95 = $69 == -1;
|
||||
do {
|
||||
if ($cmp95) {
|
||||
if (!$cmp103) {
|
||||
__label__ = 38;
|
||||
break;
|
||||
}
|
||||
if (!$cmp106) {
|
||||
__label__ = 38;
|
||||
break;
|
||||
}
|
||||
__label__ = 39;
|
||||
break;
|
||||
} else {
|
||||
__label__ = 38;
|
||||
}
|
||||
} while (0);
|
||||
if (__label__ == 38) {
|
||||
var $79 = $_pr6;
|
||||
}
|
||||
}
|
||||
var FS = {
|
||||
absolutePath: (function(relative, base) {
|
||||
|
@ -184,7 +202,6 @@ function demangle($cmp) {
|
|||
if ($cmp) {
|
||||
__label__ = 3;
|
||||
} else {
|
||||
__label__ = 1;
|
||||
if (something()) {
|
||||
__label__ = 3;
|
||||
break;
|
||||
|
@ -200,10 +217,7 @@ function demangle($cmp) {
|
|||
function lua() {
|
||||
while (1) {
|
||||
do {
|
||||
if ($14) {
|
||||
__label__ = 3;
|
||||
} else {
|
||||
__label__ = 4;
|
||||
if (!$14) {
|
||||
var $17 = $i;
|
||||
var $18 = $3;
|
||||
var $19 = $18 + ($17 << 2) | 0;
|
||||
|
@ -218,12 +232,15 @@ function lua() {
|
|||
pause();
|
||||
if ($1435 == 0) {
|
||||
__label__ = 176;
|
||||
} else if ($1435 == 1) {} else {
|
||||
cheez();
|
||||
} else if ($1435 != 1) {
|
||||
__label__ = 180;
|
||||
cheez();
|
||||
}
|
||||
pause();
|
||||
if ($1435 == 0) {
|
||||
__label__ = 176;
|
||||
cheez();
|
||||
}
|
||||
}
|
||||
function moreLabels() {
|
||||
|
|
|
@ -106,7 +106,6 @@ function hoisting() {
|
|||
if (__label__ == 2) {
|
||||
callOther();
|
||||
}
|
||||
// ok /*
|
||||
pause(1);
|
||||
if ($i < $N) {
|
||||
__label__ = 2;
|
||||
|
@ -170,6 +169,53 @@ function hoisting() {
|
|||
if (__label__ == 3) {
|
||||
somethingElse();
|
||||
}
|
||||
pause(7);
|
||||
free: while (1) {
|
||||
if ($i < $N) {
|
||||
__label__ = 2;
|
||||
} else {
|
||||
__label__ = 3; // this cannot be removed!
|
||||
break;
|
||||
}
|
||||
if (__label__ == 2) {
|
||||
somethingElse();
|
||||
}
|
||||
if ($i < $N) {
|
||||
__label__ = 2;
|
||||
} else {
|
||||
__label__ = 3; // this can be removed!
|
||||
}
|
||||
if (__label__ == 2) {
|
||||
somethingElse();
|
||||
}
|
||||
nothing();
|
||||
}
|
||||
pause(8);
|
||||
var $cmp95 = $69 == -1;
|
||||
if ($cmp95) {
|
||||
__label__ = 35;
|
||||
} else {
|
||||
__label__ = 38;
|
||||
}
|
||||
$if_then96$$if_end110thread_pre_split$48 : do {
|
||||
if (__label__ == 35) {
|
||||
if (!$cmp103) {
|
||||
__label__ = 38;
|
||||
break $if_then96$$if_end110thread_pre_split$48;
|
||||
}
|
||||
if (!$cmp106) {
|
||||
__label__ = 38;
|
||||
break $if_then96$$if_end110thread_pre_split$48;
|
||||
}
|
||||
__label__ = 39;
|
||||
break $if_then96$$if_end110thread_pre_split$48;
|
||||
}
|
||||
} while (0);
|
||||
$if_end110$$if_end110thread_pre_split$52 : do {
|
||||
if (__label__ == 38) {
|
||||
var $79 = $_pr6;
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
var FS = {
|
||||
absolutePath: function(relative, base) { // Don't touch this!
|
||||
|
@ -243,12 +289,15 @@ function lua() {
|
|||
pause();
|
||||
if ($1435 == 0) {
|
||||
__label__ = 176;
|
||||
cheez();
|
||||
} else if ($1435 == 1) {} else {
|
||||
__label__ = 180;
|
||||
cheez();
|
||||
}
|
||||
pause();
|
||||
if ($1435 == 0) {
|
||||
__label__ = 176;
|
||||
cheez();
|
||||
} else if ($1435 == 1) {}
|
||||
}
|
||||
function moreLabels() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче