bug 584787, r=pcwalton: Node shouldn't subclass Array

This commit is contained in:
Dave Herman 2010-10-07 10:59:45 -07:00
Родитель e2941e77c7
Коммит b3fd89a22a
5 изменённых файлов: 243 добавлений и 147 удалений

Просмотреть файл

@ -313,8 +313,8 @@ Narcissus.interpreter = (function() {
return; return;
for (var i = 0, j = ps.length; i < j; i++) { for (var i = 0, j = ps.length; i < j; i++) {
// If the thing we're valuating is already equal to the thing we want // If the thing we're evaluating is already equal to the thing we want
// to valuate it to, we have fully saturated (and have a cycle), and // to evaluate it to, we have fully saturated (and have a cycle), and
// thus we should break. // thus we should break.
if (ps[i].v === v) if (ps[i].v === v)
break; break;
@ -324,7 +324,7 @@ Narcissus.interpreter = (function() {
} }
function execute(n, x) { function execute(n, x) {
var a, f, i, j, r, s, t, u, v; var a, c, f, i, j, r, s, t, u, v;
switch (n.type) { switch (n.type) {
case FUNCTION: case FUNCTION:
@ -370,8 +370,9 @@ Narcissus.interpreter = (function() {
// FALL THROUGH // FALL THROUGH
case BLOCK: case BLOCK:
for (i = 0, j = n.length; i < j; i++) c = n.children;
execute(n[i], x); for (i = 0, j = c.length; i < j; i++)
execute(c[i], x);
break; break;
case IF: case IF:
@ -405,7 +406,7 @@ Narcissus.interpreter = (function() {
} }
if (u === s) { if (u === s) {
for (;;) { // this loop exits switch_loop for (;;) { // this loop exits switch_loop
if (t.statements.length) { if (t.statements.children.length) {
try { try {
execute(t.statements, x); execute(t.statements, x);
} catch (e if e === BREAK && x.target === n) { } catch (e if e === BREAK && x.target === n) {
@ -532,11 +533,12 @@ Narcissus.interpreter = (function() {
case VAR: case VAR:
case CONST: case CONST:
for (i = 0, j = n.length; i < j; i++) { c = n.children;
u = n[i].initializer; for (i = 0, j = c.length; i < j; i++) {
u = c[i].initializer;
if (!u) if (!u)
continue; continue;
t = n[i].name; t = c[i].name;
for (s = x.scope; s; s = s.parent) { for (s = x.scope; s; s = s.parent) {
if (hasDirectProperty(s.object, t)) if (hasDirectProperty(s.object, t))
break; break;
@ -565,16 +567,18 @@ Narcissus.interpreter = (function() {
break; break;
case COMMA: case COMMA:
for (i = 0, j = n.length; i < j; i++) c = n.children;
v = getValue(execute(n[i], x)); for (i = 0, j = c.length; i < j; i++)
v = getValue(execute(c[i], x));
break; break;
case ASSIGN: case ASSIGN:
r = execute(n[0], x); c = n.children;
r = execute(c[0], x);
t = n.assignOp; t = n.assignOp;
if (t) if (t)
u = getValue(r); u = getValue(r);
v = getValue(execute(n[1], x)); v = getValue(execute(c[1], x));
if (t) { if (t) {
switch (t) { switch (t) {
case BITWISE_OR: v = u | v; break; case BITWISE_OR: v = u | v; break;
@ -590,73 +594,89 @@ Narcissus.interpreter = (function() {
case MOD: v = u % v; break; case MOD: v = u % v; break;
} }
} }
putValue(r, v, n[0]); putValue(r, v, c[0]);
break; break;
case HOOK: case HOOK:
v = getValue(execute(n[0], x)) ? getValue(execute(n[1], x)) c = n.children;
: getValue(execute(n[2], x)); v = getValue(execute(c[0], x)) ? getValue(execute(c[1], x))
: getValue(execute(c[2], x));
break; break;
case OR: case OR:
v = getValue(execute(n[0], x)) || getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) || getValue(execute(c[1], x));
break; break;
case AND: case AND:
v = getValue(execute(n[0], x)) && getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) && getValue(execute(c[1], x));
break; break;
case BITWISE_OR: case BITWISE_OR:
v = getValue(execute(n[0], x)) | getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) | getValue(execute(c[1], x));
break; break;
case BITWISE_XOR: case BITWISE_XOR:
v = getValue(execute(n[0], x)) ^ getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) ^ getValue(execute(c[1], x));
break; break;
case BITWISE_AND: case BITWISE_AND:
v = getValue(execute(n[0], x)) & getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) & getValue(execute(c[1], x));
break; break;
case EQ: case EQ:
v = getValue(execute(n[0], x)) == getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) == getValue(execute(c[1], x));
break; break;
case NE: case NE:
v = getValue(execute(n[0], x)) != getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) != getValue(execute(c[1], x));
break; break;
case STRICT_EQ: case STRICT_EQ:
v = getValue(execute(n[0], x)) === getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) === getValue(execute(c[1], x));
break; break;
case STRICT_NE: case STRICT_NE:
v = getValue(execute(n[0], x)) !== getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) !== getValue(execute(c[1], x));
break; break;
case LT: case LT:
v = getValue(execute(n[0], x)) < getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) < getValue(execute(c[1], x));
break; break;
case LE: case LE:
v = getValue(execute(n[0], x)) <= getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) <= getValue(execute(c[1], x));
break; break;
case GE: case GE:
v = getValue(execute(n[0], x)) >= getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) >= getValue(execute(c[1], x));
break; break;
case GT: case GT:
v = getValue(execute(n[0], x)) > getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) > getValue(execute(c[1], x));
break; break;
case IN: case IN:
v = getValue(execute(n[0], x)) in getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) in getValue(execute(c[1], x));
break; break;
case INSTANCEOF: case INSTANCEOF:
t = getValue(execute(n[0], x)); c = n.children;
u = getValue(execute(n[1], x)); t = getValue(execute(c[0], x));
u = getValue(execute(c[1], x));
if (isObject(u) && typeof u.__hasInstance__ === "function") if (isObject(u) && typeof u.__hasInstance__ === "function")
v = u.__hasInstance__(t); v = u.__hasInstance__(t);
else else
@ -664,111 +684,122 @@ Narcissus.interpreter = (function() {
break; break;
case LSH: case LSH:
v = getValue(execute(n[0], x)) << getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) << getValue(execute(c[1], x));
break; break;
case RSH: case RSH:
v = getValue(execute(n[0], x)) >> getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) >> getValue(execute(c[1], x));
break; break;
case URSH: case URSH:
v = getValue(execute(n[0], x)) >>> getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) >>> getValue(execute(c[1], x));
break; break;
case PLUS: case PLUS:
v = getValue(execute(n[0], x)) + getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) + getValue(execute(c[1], x));
break; break;
case MINUS: case MINUS:
v = getValue(execute(n[0], x)) - getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) - getValue(execute(c[1], x));
break; break;
case MUL: case MUL:
v = getValue(execute(n[0], x)) * getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) * getValue(execute(c[1], x));
break; break;
case DIV: case DIV:
v = getValue(execute(n[0], x)) / getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) / getValue(execute(c[1], x));
break; break;
case MOD: case MOD:
v = getValue(execute(n[0], x)) % getValue(execute(n[1], x)); c = n.children;
v = getValue(execute(c[0], x)) % getValue(execute(c[1], x));
break; break;
case DELETE: case DELETE:
t = execute(n[0], x); t = execute(n.children[0], x);
v = !(t instanceof Reference) || delete t.base[t.propertyName]; v = !(t instanceof Reference) || delete t.base[t.propertyName];
break; break;
case VOID: case VOID:
getValue(execute(n[0], x)); getValue(execute(n.children[0], x));
break; break;
case TYPEOF: case TYPEOF:
t = execute(n[0], x); t = execute(n.children[0], x);
if (t instanceof Reference) if (t instanceof Reference)
t = t.base ? t.base[t.propertyName] : undefined; t = t.base ? t.base[t.propertyName] : undefined;
v = typeof t; v = typeof t;
break; break;
case NOT: case NOT:
v = !getValue(execute(n[0], x)); v = !getValue(execute(n.children[0], x));
break; break;
case BITWISE_NOT: case BITWISE_NOT:
v = ~getValue(execute(n[0], x)); v = ~getValue(execute(n.children[0], x));
break; break;
case UNARY_PLUS: case UNARY_PLUS:
v = +getValue(execute(n[0], x)); v = +getValue(execute(n.children[0], x));
break; break;
case UNARY_MINUS: case UNARY_MINUS:
v = -getValue(execute(n[0], x)); v = -getValue(execute(n.children[0], x));
break; break;
case INCREMENT: case INCREMENT:
case DECREMENT: case DECREMENT:
t = execute(n[0], x); t = execute(n.children[0], x);
u = Number(getValue(t)); u = Number(getValue(t));
if (n.postfix) if (n.postfix)
v = u; v = u;
putValue(t, (n.type === INCREMENT) ? ++u : --u, n[0]); putValue(t, (n.type === INCREMENT) ? ++u : --u, n.children[0]);
if (!n.postfix) if (!n.postfix)
v = u; v = u;
break; break;
case DOT: case DOT:
r = execute(n[0], x); c = n.children;
r = execute(c[0], x);
t = getValue(r); t = getValue(r);
u = n[1].value; u = c[1].value;
v = new Reference(toObject(t, r, n[0]), u, n); v = new Reference(toObject(t, r, c[0]), u, n);
break; break;
case INDEX: case INDEX:
r = execute(n[0], x); c = n.children;
r = execute(c[0], x);
t = getValue(r); t = getValue(r);
u = getValue(execute(n[1], x)); u = getValue(execute(c[1], x));
v = new Reference(toObject(t, r, n[0]), String(u), n); v = new Reference(toObject(t, r, c[0]), String(u), n);
break; break;
case LIST: case LIST:
// Curse ECMA for specifying that arguments is not an Array object! // Curse ECMA for specifying that arguments is not an Array object!
v = {}; v = {};
for (i = 0, j = n.length; i < j; i++) { c = n.children;
u = getValue(execute(n[i], x)); for (i = 0, j = c.length; i < j; i++) {
u = getValue(execute(c[i], x));
definitions.defineProperty(v, i, u, false, false, true); definitions.defineProperty(v, i, u, false, false, true);
} }
definitions.defineProperty(v, "length", i, false, false, true); definitions.defineProperty(v, "length", i, false, false, true);
break; break;
case CALL: case CALL:
r = execute(n[0], x); c = n.children;
a = execute(n[1], x); r = execute(c[0], x);
a = execute(c[1], x);
f = getValue(r); f = getValue(r);
if (isPrimitive(f) || typeof f.__call__ !== "function") { if (isPrimitive(f) || typeof f.__call__ !== "function") {
throw new TypeError(r + " is not callable", throw new TypeError(r + " is not callable", c[0].filename, c[0].lineno);
n[0].filename, n[0].lineno);
} }
t = (r instanceof Reference) ? r.base : null; t = (r instanceof Reference) ? r.base : null;
if (t instanceof Activation) if (t instanceof Activation)
@ -778,36 +809,39 @@ Narcissus.interpreter = (function() {
case NEW: case NEW:
case NEW_WITH_ARGS: case NEW_WITH_ARGS:
r = execute(n[0], x); c = n.children;
r = execute(c[0], x);
f = getValue(r); f = getValue(r);
if (n.type === NEW) { if (n.type === NEW) {
a = {}; a = {};
definitions.defineProperty(a, "length", 0, false, false, true); definitions.defineProperty(a, "length", 0, false, false, true);
} else { } else {
a = execute(n[1], x); a = execute(c[1], x);
} }
if (isPrimitive(f) || typeof f.__construct__ !== "function") { if (isPrimitive(f) || typeof f.__construct__ !== "function") {
throw new TypeError(r + " is not a constructor", throw new TypeError(r + " is not a constructor", c[0].filename, c[0].lineno);
n[0].filename, n[0].lineno);
} }
v = f.__construct__(a, x); v = f.__construct__(a, x);
break; break;
case ARRAY_INIT: case ARRAY_INIT:
v = []; v = [];
for (i = 0, j = n.length; i < j; i++) { c = n.children;
if (n[i]) for (i = 0, j = c.length; i < j; i++) {
v[i] = getValue(execute(n[i], x)); if (c[i])
v[i] = getValue(execute(c[i], x));
} }
v.length = j; v.length = j;
break; break;
case OBJECT_INIT: case OBJECT_INIT:
v = {}; v = {};
for (i = 0, j = n.length; i < j; i++) { c = n.children;
t = n[i]; for (i = 0, j = c.length; i < j; i++) {
t = c[i];
if (t.type === PROPERTY_INIT) { if (t.type === PROPERTY_INIT) {
v[t[0].value] = getValue(execute(t[1], x)); let c2 = t.children;
v[c2[0].value] = getValue(execute(c2[1], x));
} else { } else {
f = newFunction(t, x); f = newFunction(t, x);
u = (t.type === GETTER) ? '__defineGetter__' u = (t.type === GETTER) ? '__defineGetter__'
@ -834,6 +868,9 @@ Narcissus.interpreter = (function() {
break; break;
case IDENTIFIER: case IDENTIFIER:
if (typeof n.resolve !== "function")
throw n;
// Identifiers with forward pointers that weren't intervened can't be // Identifiers with forward pointers that weren't intervened can't be
// lvalues, so we safely get the cached value directly. // lvalues, so we safely get the cached value directly.
var resolved = n.resolve(); var resolved = n.resolve();
@ -859,7 +896,7 @@ Narcissus.interpreter = (function() {
break; break;
case GROUP: case GROUP:
v = execute(n[0], x); v = execute(n.children[0], x);
break; break;
default: default:
@ -1132,6 +1169,22 @@ Narcissus.interpreter = (function() {
print(e.toString()); print(e.toString());
} catch (e) { } catch (e) {
print("internal Narcissus error"); print("internal Narcissus error");
if (typeof e === "object" && e.stack) {
let st = String(e.stack).split(/\n/);
// beautify stack trace:
// - eliminate blank lines
// - sanitize confusing trace lines for getters and js -e expressions
// - simplify source location reporting
// - indent
for (let i = 0; i < st.length; i++) {
let line = st[i].trim();
if (line) {
line = line.replace(/^(\(\))?@/, "<unknown>@");
line = line.replace(/@(.*\/|\\)?([^\/\\]+:[0-9]+)/, " at $2");
print(" in " + line);
}
}
}
throw e; throw e;
} }
} }

Просмотреть файл

@ -657,15 +657,15 @@ Narcissus.parser = (function() {
}, },
setCondition: function(n, e) { setCondition: function(n, e) {
n[0] = e; n.children[0] = e;
}, },
setThenPart: function(n, n2) { setThenPart: function(n, n2) {
n[1] = n2; n.children[1] = n2;
}, },
setElsePart: function(n, n2) { setElsePart: function(n, n2) {
n[2] = n2; n.children[2] = n2;
}, },
finish: function(n) { finish: function(n) {
@ -906,11 +906,12 @@ Narcissus.parser = (function() {
// Nodes use a tokenizer for debugging (getSource, filename getter). // Nodes use a tokenizer for debugging (getSource, filename getter).
this.tokenizer = t; this.tokenizer = t;
this.children = [];
for (var i = 2; i < arguments.length; i++) for (var i = 2; i < arguments.length; i++)
this.push(arguments[i]); this.push(arguments[i]);
} }
var Np = Node.prototype = new Array; var Np = Node.prototype = {};
Np.constructor = Node; Np.constructor = Node;
Np.toSource = Object.prototype.toSource; Np.toSource = Object.prototype.toSource;
@ -923,7 +924,7 @@ Narcissus.parser = (function() {
if (this.end < kid.end) if (this.end < kid.end)
this.end = kid.end; this.end = kid.end;
} }
return Array.prototype.push.call(this, kid); return this.children.push(kid);
} }
Node.indentLevel = 0; Node.indentLevel = 0;
@ -959,6 +960,11 @@ Narcissus.parser = (function() {
return this.tokenizer.filename; return this.tokenizer.filename;
}); });
definitions.defineGetter(Np, "length",
function() {
throw new Error("Node.prototype.length is gone; use n.children.length instead");
});
definitions.defineProperty(String.prototype, "repeat", definitions.defineProperty(String.prototype, "repeat",
function(n) { function(n) {
var s = "", t = this + s; var s = "", t = this + s;
@ -1027,7 +1033,7 @@ Narcissus.parser = (function() {
* Parses a Statement. * Parses a Statement.
*/ */
function Statement(t, x) { function Statement(t, x) {
var i, label, n, n2, ss, tt = t.get(true); var i, label, n, n2, c, ss, tt = t.get(true);
var builder = x.builder, b, b2, b3; var builder = x.builder, b, b2, b3;
// Cases for statements ending in a right curly return early, avoiding the // Cases for statements ending in a right curly return early, avoiding the
@ -1141,17 +1147,19 @@ Narcissus.parser = (function() {
b.rebuildForIn(n); b.rebuildForIn(n);
b.setObject(n, Expression(t, x)); b.setObject(n, Expression(t, x));
if (n2.type === VAR || n2.type === LET) { if (n2.type === VAR || n2.type === LET) {
c = n2.children;
// Destructuring turns one decl into multiples, so either // Destructuring turns one decl into multiples, so either
// there must be only one destructuring or only one // there must be only one destructuring or only one
// decl. // decl.
if (n2.length !== 1 && n2.destructurings.length !== 1) { if (c.length !== 1 && n2.destructurings.length !== 1) {
throw new SyntaxError("Invalid for..in left-hand side", throw new SyntaxError("Invalid for..in left-hand side",
t.filename, n2.lineno); t.filename, n2.lineno);
} }
if (n2.destructurings.length > 0) { if (n2.destructurings.length > 0) {
b.setIterator(n, n2.destructurings[0], n2, forBlock); b.setIterator(n, n2.destructurings[0], n2, forBlock);
} else { } else {
b.setIterator(n, n2[0], n2, forBlock); b.setIterator(n, c[0], n2, forBlock);
} }
} else { } else {
if (n2.type === ARRAY_INIT || n2.type === OBJECT_INIT) { if (n2.type === ARRAY_INIT || n2.type === OBJECT_INIT) {
@ -1181,8 +1189,9 @@ Narcissus.parser = (function() {
if (forBlock) { if (forBlock) {
builder.BLOCK.finish(forBlock); builder.BLOCK.finish(forBlock);
x.stmtStack.pop(); x.stmtStack.pop();
for (var i = 0, j = forBlock.length; i < j; i++) { c = forBlock.children;
n.body.unshift(forBlock[i]); for (var i = 0, j = c.length; i < j; i++) {
n.body.unshift(c[i]);
} }
} }
return n; return n;
@ -1726,13 +1735,14 @@ Narcissus.parser = (function() {
return; return;
var lhss = {}; var lhss = {};
var nn, n2, idx, sub; var nn, n2, idx, sub, cc, c = n.children;
for (var i = 0, j = n.length; i < j; i++) { for (var i = 0, j = c.length; i < j; i++) {
if (!(nn = n[i])) if (!(nn = c[i]))
continue; continue;
if (nn.type === PROPERTY_INIT) { if (nn.type === PROPERTY_INIT) {
sub = nn[1]; cc = nn.children;
idx = nn[0].value; sub = cc[1];
idx = cc[0].value;
} else if (n.type === OBJECT_INIT) { } else if (n.type === OBJECT_INIT) {
// Do we have destructuring shorthand {foo, bar}? // Do we have destructuring shorthand {foo, bar}?
sub = nn; sub = nn;
@ -1891,7 +1901,7 @@ Narcissus.parser = (function() {
b.addOperand(n2, n); b.addOperand(n2, n);
n = n2; n = n2;
do { do {
n2 = n[n.length-1]; n2 = n.children[n.children.length-1];
if (n2.type === YIELD && !n2.parenthesized) if (n2.type === YIELD && !n2.parenthesized)
throw t.newSyntaxError("Yield expression must be parenthesized"); throw t.newSyntaxError("Yield expression must be parenthesized");
b.addOperand(n, AssignExpression(t, x)); b.addOperand(n, AssignExpression(t, x));
@ -2233,7 +2243,7 @@ Narcissus.parser = (function() {
throw t.newSyntaxError("Yield " + err); throw t.newSyntaxError("Yield " + err);
if (t.match(FOR)) { if (t.match(FOR)) {
n2 = GeneratorExpression(t, x, n2); n2 = GeneratorExpression(t, x, n2);
if (n.length > 1 || t.peek(true) === COMMA) if (n.children.length > 1 || t.peek(true) === COMMA)
throw t.newSyntaxError("Generator " + err); throw t.newSyntaxError("Generator " + err);
} }
b.addOperand(n, n2); b.addOperand(n, n2);
@ -2274,9 +2284,9 @@ Narcissus.parser = (function() {
// If we matched exactly one element and got a FOR, we have an // If we matched exactly one element and got a FOR, we have an
// array comprehension. // array comprehension.
if (n.length === 1 && t.match(FOR)) { if (n.children.length === 1 && t.match(FOR)) {
n2 = bArrayComp.build(t); n2 = bArrayComp.build(t);
bArrayComp.setExpression(n2, n[0]); bArrayComp.setExpression(n2, n.children[0]);
bArrayComp.setTail(n2, comprehensionTail(t, x)); bArrayComp.setTail(n2, comprehensionTail(t, x));
n = n2; n = n2;
} }
@ -2379,9 +2389,6 @@ Narcissus.parser = (function() {
parse: parse, parse: parse,
Node: Node, Node: Node,
DefaultBuilder: DefaultBuilder, DefaultBuilder: DefaultBuilder,
get SSABuilder() {
throw new Error("SSA builder not yet supported");
},
bindSubBuilders: bindSubBuilders, bindSubBuilders: bindSubBuilders,
DECLARED_FORM: DECLARED_FORM, DECLARED_FORM: DECLARED_FORM,
EXPRESSED_FORM: EXPRESSED_FORM, EXPRESSED_FORM: EXPRESSED_FORM,

Просмотреть файл

@ -41,7 +41,7 @@
* SSA builder and optimizations. * SSA builder and optimizations.
*/ */
(function() { Narcissus.parser.SSABuilder = (function() {
const parser = Narcissus.parser; const parser = Narcissus.parser;
const definitions = Narcissus.definitions; const definitions = Narcissus.definitions;
@ -717,7 +717,7 @@
if (allDashes) { if (allDashes) {
return null; return null;
} }
rhs.reverse(); rhs.children.reverse();
e = new Node(ft, ASSIGN); e = new Node(ft, ASSIGN);
e.push(lhs); e.push(lhs);
@ -732,20 +732,21 @@
continue; continue;
} }
rhs = e2[1]; rhs = e2.children[1];
// Optimize away phis that are only one branch, but we still need // Optimize away phis that are only one branch, but we still need
// to propagate them! // to propagate them!
if (branches == 1) { if (branches == 1) {
rhs = rhs[0]; rhs = rhs.children[0];
} else { } else {
// Push a phi use for each operand so the phis can be filled // Push a phi use for each operand so the phis can be filled
// in during exec. // in during exec.
for (var i = 0, j = rhs.length; i < j; i++) { var rhsc = rhs.children;
if (rhs[i].type == INTERVENED) { for (var i = 0, j = rhsc.length; i < j; i++) {
if (rhsc[i].type == INTERVENED) {
rhs.intervened = true; rhs.intervened = true;
} }
rhs[i].pushPhiUse(rhs); rhsc[i].pushPhiUse(rhs);
} }
e.push(e2); e.push(e2);
} }
@ -753,7 +754,7 @@
propagate(x, rhs); propagate(x, rhs);
} }
return e.length > 0 ? e : null; return e.children.length > 0 ? e : null;
} }
SSAJoin.prototype = { SSAJoin.prototype = {
@ -904,9 +905,10 @@
uu = u[i]; uu = u[i];
// Phi nodes might have stale branches. // Phi nodes might have stale branches.
if (uu.type == PHI) { if (uu.type == PHI) {
for (var k = 0, l = uu.length; k < l; k++) { var uuc = uu.children;
if (uu[k] === old.def) { for (var k = 0, l = uuc.length; k < l; k++) {
uu[k] = rhs; if (uuc[k] === old.def) {
uuc[k] = rhs;
rhs.pushPhiUse(uu); rhs.pushPhiUse(uu);
} }
} }
@ -1279,7 +1281,7 @@
// do. // do.
var bComma = this.COMMA; var bComma = this.COMMA;
e2.push(n.setup[0]); e2.push(n.setup.children[0]);
n.setup = e2; n.setup = e2;
var comma = bComma.build(t); var comma = bComma.build(t);
@ -1318,7 +1320,7 @@
this.join = breakJoin.parent; this.join = breakJoin.parent;
// Add update to the top if we were a for-in // Add update to the top if we were a for-in
if (n.type == FOR_IN) { if (n.type == FOR_IN) {
n.body.unshift(n.update); n.body.children.unshift(n.update);
n.update = null; n.update = null;
n.type = FOR; n.type = FOR;
} }
@ -1973,7 +1975,7 @@
ASSIGN: { ASSIGN: {
addOperand: function(n, n2) { addOperand: function(n, n2) {
if (n.length == 0) { if (n.children.length === 0) {
this.binds.inRHS++; this.binds.inRHS++;
} }
@ -1981,15 +1983,16 @@
}, },
finish: function(n) { finish: function(n) {
if (n.length == 0) { if (n.children.length === 0) {
return; return;
} }
var join = this.join; var join = this.join;
var binds = this.binds; var binds = this.binds;
var fb = binds.nearestFunction; var fb = binds.nearestFunction;
var lhs = n[0]; var nc = n.children;
var init = n[1]; var lhs = nc[0];
var init = nc[1];
var upvars = init.upvars || new Upvars; var upvars = init.upvars || new Upvars;
if (--binds.inRHS > 0) { if (--binds.inRHS > 0) {
@ -2001,7 +2004,7 @@
var t = n.tokenizer; var t = n.tokenizer;
// Rebuild as COMMA. // Rebuild as COMMA.
n.type = COMMA; n.type = COMMA;
n.length = 0; n.children = [];
desugarDestructuringAssign(this, n, lhs, init); desugarDestructuringAssign(this, n, lhs, init);
return; return;
} }
@ -2053,12 +2056,11 @@
// Transform op= into a normal assignment only if the // Transform op= into a normal assignment only if the
// lhs is an identifier we _know_ to be from a var. // lhs is an identifier we _know_ to be from a var.
var nt = n.tokenizer; var nt = n.tokenizer;
var lhs = n[0];
var n2 = mkRawIdentifier(nt, name, null, true); var n2 = mkRawIdentifier(nt, name, null, true);
this.PRIMARY.finish(n2); this.PRIMARY.finish(n2);
var o = n.assignOp; var o = n.assignOp;
n.assignOp = undefined; n.assignOp = undefined;
n.length = 0; n.children = [];
n.push(lhs); n.push(lhs);
n.push(new Node(nt, o, n2, init)); n.push(new Node(nt, o, n2, init));
n2.setForward(c.def); n2.setForward(c.def);
@ -2066,17 +2068,17 @@
} }
// Clear the forward pointer and upvars on lefthand side. // Clear the forward pointer and upvars on lefthand side.
if (n[0].forward) { if (lhs.forward) {
n[0].forward = null; lhs.forward = null;
n[0].upvars = null; lhs.upvars = null;
} }
// Set local to help decomp to do value numbering. // Set local to help decomp to do value numbering.
n[0].local = c.type; lhs.local = c.type;
// Get the rightmost expression in case of compound // Get the rightmost expression in case of compound
// assignment. // assignment.
while (init.type == ASSIGN) while (init.type == ASSIGN)
init = init[1]; init = init.children[1];
if (join) { if (join) {
// If the name is not a local let, we need a phi. // If the name is not a local let, we need a phi.
@ -2124,21 +2126,21 @@
}, },
setCondition: function(n, e) { setCondition: function(n, e) {
n[0] = e; n.children[0] = e;
n.rhsUnionUpvars(e); n.rhsUnionUpvars(e);
this.join = new SSAJoin(this.join, this.binds, false); this.join = new SSAJoin(this.join, this.binds, false);
}, },
setThenPart: function(n, n2) { setThenPart: function(n, n2) {
var join = this.join; var join = this.join;
n[1] = n2; n.children[1] = n2;
n.rhsUnionUpvars(n2); n.rhsUnionUpvars(n2);
join.finishBranch(); join.finishBranch();
join.restore(this.binds); join.restore(this.binds);
}, },
setElsePart: function(n, n2) { setElsePart: function(n, n2) {
n[2] = n2; n.children[2] = n2;
n.rhsUnionUpvars(n2); n.rhsUnionUpvars(n2);
}, },
@ -2158,7 +2160,7 @@
}, },
addOperand: function(n, n2) { addOperand: function(n, n2) {
if (n.length == 0) { if (n.children.length == 0) {
// Short circuiting means the right hand expression needs // Short circuiting means the right hand expression needs
// to be parsed in a new context. // to be parsed in a new context.
var join = this.join = new SSAJoin(this.join, this.binds, false); var join = this.join = new SSAJoin(this.join, this.binds, false);
@ -2186,7 +2188,7 @@
}, },
addOperand: function(n, n2) { addOperand: function(n, n2) {
if (n.length == 0) { if (n.children.length == 0) {
// Short circuiting means the right hand expression needs // Short circuiting means the right hand expression needs
// to be parsed in a new context. // to be parsed in a new context.
var join = this.join = new SSAJoin(this.join, this.binds, false); var join = this.join = new SSAJoin(this.join, this.binds, false);
@ -2213,7 +2215,9 @@
var join = this.join; var join = this.join;
var binds = this.binds; var binds = this.binds;
if (!(n[0].type == IDENTIFIER && binds.hasCurrent(n[0].value))) var nc = n.children;
var lhs = nc[0];
if (!(lhs.type == IDENTIFIER && binds.hasCurrent(lhs.value)))
return; return;
// //
@ -2230,7 +2234,7 @@
// effect, so we do not duplicate side effects in an unsafe // effect, so we do not duplicate side effects in an unsafe
// fashion. // fashion.
// //
var name = n[0].value; var name = lhs.value;
var c = binds.current(name); var c = binds.current(name);
// Don't transform vars inside of withs // Don't transform vars inside of withs
if (binds.isWith && c.type == VAR) if (binds.isWith && c.type == VAR)
@ -2255,7 +2259,7 @@
if (n.postfix) { if (n.postfix) {
n.parenthesized = true; n.parenthesized = true;
n.type = COMMA; n.type = COMMA;
n.length = 0; n.children = [];
n.push(mkAssignSimple(this, t, ptmp, n.push(mkAssignSimple(this, t, ptmp,
mkIdentifier(this, t, name))); mkIdentifier(this, t, name)));
} }
@ -2270,9 +2274,11 @@
n.push(mkIdentifier(this, t, ptmp)); n.push(mkIdentifier(this, t, ptmp));
} else { } else {
n.type = ASSIGN; n.type = ASSIGN;
n.length = 0; n.children = [];
n.push(assign[0]);
n.push(assign[1]); var assignc = assign.children;
n.push(assignc[0]);
n.push(assignc[1]);
} }
} }
}, },
@ -2296,12 +2302,13 @@
var join = this.join; var join = this.join;
var binds = this.binds; var binds = this.binds;
var fb = binds.nearestFunction; var fb = binds.nearestFunction;
var nc = n.children;
if (--binds.inRHS > 0) { if (--binds.inRHS > 0) {
if (unionOnRight) { if (unionOnRight) {
n.upvars = n[1].upvars; n.upvars = nc[1].upvars;
} else { } else {
n.upvars = n[0].upvars; n.upvars = nc[0].upvars;
} }
} }
@ -2357,8 +2364,9 @@
// local ones, so blast away context. // local ones, so blast away context.
// //
var inners = this.binds.inners; var inners = this.binds.inners;
var base = baseOfCall(n[0]); var call = nc[0];
var target = targetOfCall(n[0], IDENTIFIER); var base = baseOfCall(call);
var target = targetOfCall(call, IDENTIFIER);
if (target == "eval") { if (target == "eval") {
escapeEval(join, binds); escapeEval(join, binds);
@ -2454,7 +2462,7 @@
var unionOnRight = n.type == CALL || n.type == NEW_WITH_ARGS || var unionOnRight = n.type == CALL || n.type == NEW_WITH_ARGS ||
n.type == INDEX; n.type == INDEX;
if (unionOnRight) { if (unionOnRight) {
escapeVars(join, binds, n[1].upvars || new Upvars); escapeVars(join, binds, nc[1].upvars || new Upvars);
} }
} }
}, },
@ -2581,7 +2589,7 @@
}, },
finish: function(n) { finish: function(n) {
n.rhsUnionUpvars(n[1]); n.rhsUnionUpvars(n.children[1]);
} }
}, },
@ -2837,9 +2845,9 @@
function baseOfCall(n) { function baseOfCall(n) {
switch (n.type) { switch (n.type) {
case DOT: case DOT:
return baseOfCall(n[0]); return baseOfCall(n.children[0]);
case INDEX: case INDEX:
return baseOfCall(n[0]); return baseOfCall(n.children[0]);
default: default:
return n; return n;
} }
@ -2850,9 +2858,9 @@
case ident: case ident:
return n.value; return n.value;
case DOT: case DOT:
return targetOfCall(n[1], IDENTIFIER); return targetOfCall(n.children[1], IDENTIFIER);
case INDEX: case INDEX:
return targetOfCall(n[1], STRING); return targetOfCall(n.children[1], STRING);
default: default:
return null; return null;
} }
@ -2948,9 +2956,9 @@
builder.genDestructuringSym(), builder.genDestructuringSym(),
e, false); e, false);
builder.binds.block.push(decl); builder.binds.block.push(decl);
decl[0].setForward(e); var declc = decl.children[0];
declc[0].setForward(e);
go(n.destructuredNames, decl[0]); go(n.destructuredNames, declc[0]);
} }
function desugarDestructuringInit(builder, n, e) { function desugarDestructuringInit(builder, n, e) {
@ -2984,8 +2992,9 @@
var dtmp = builder.genDestructuringSym(); var dtmp = builder.genDestructuringSym();
var decl = mkDecl(builder, "LET", t, dtmp, e, false); var decl = mkDecl(builder, "LET", t, dtmp, e, false);
block.push(decl); block.push(decl);
decl[0].setForward(e); var declc = decl.children[0];
go(ddecls, decl[0]); declc[0].setForward(e);
go(ddecls, declc[0]);
} else { } else {
// This only happens when we have destructuring for a catch var, // This only happens when we have destructuring for a catch var,
// in which case that catch var already has let-scoping, so we // in which case that catch var already has let-scoping, so we
@ -3139,6 +3148,6 @@
this.phiUses.push(p); this.phiUses.push(p);
}; };
parser.SSABuilder = SSABuilder; return SSABuilder;
}()); }());

Просмотреть файл

@ -16,6 +16,7 @@ js_cmd = os.path.abspath(os.path.join(THIS_DIR, "js"))
narc_jsdefs = os.path.join(NARC_JS_DIR, "jsdefs.js") narc_jsdefs = os.path.join(NARC_JS_DIR, "jsdefs.js")
narc_jslex = os.path.join(NARC_JS_DIR, "jslex.js") narc_jslex = os.path.join(NARC_JS_DIR, "jslex.js")
narc_jsparse = os.path.join(NARC_JS_DIR, "jsparse.js") narc_jsparse = os.path.join(NARC_JS_DIR, "jsparse.js")
narc_jsssa = os.path.join(NARC_JS_DIR, "jsssa.js")
narc_jsexec = os.path.join(NARC_JS_DIR, "jsexec.js") narc_jsexec = os.path.join(NARC_JS_DIR, "jsexec.js")
def handler(signum, frame): def handler(signum, frame):
@ -62,5 +63,5 @@ if __name__ == '__main__':
if options.js_interactive: if options.js_interactive:
cmd += 'Narcissus.interpreter.repl();' cmd += 'Narcissus.interpreter.repl();'
Popen([js_cmd, '-f', narc_jsdefs, '-f', narc_jslex, '-f', narc_jsparse, '-f', narc_jsexec, '-e', cmd]).wait() Popen([js_cmd, '-f', narc_jsdefs, '-f', narc_jslex, '-f', narc_jsparse, '-f', narc_jsssa, '-f', narc_jsexec, '-e', cmd]).wait()

Просмотреть файл

@ -259,6 +259,7 @@ e4x/extensions/regress-410192.js
e4x/extensions/regress-450871-01.js e4x/extensions/regress-450871-01.js
e4x/extensions/regress-450871-02.js e4x/extensions/regress-450871-02.js
e4x/extensions/regress-462734-01.js e4x/extensions/regress-462734-01.js
e4x/extensions/extensibility.js
ecma/Array/15.4.4.3-1.js ecma/Array/15.4.4.3-1.js
ecma/Boolean/15.6.4.1.js ecma/Boolean/15.6.4.1.js
ecma/Boolean/15.6.4.2-4-n.js ecma/Boolean/15.6.4.2-4-n.js
@ -606,10 +607,13 @@ ecma_5/Object/15.2.3.6-redefinition-2-of-4.js
ecma_5/Object/15.2.3.6-redefinition-3-of-4.js ecma_5/Object/15.2.3.6-redefinition-3-of-4.js
ecma_5/Object/15.2.3.6-redefinition-4-of-4.js ecma_5/Object/15.2.3.6-redefinition-4-of-4.js
ecma_5/Object/15.2.3.7-01.js ecma_5/Object/15.2.3.7-01.js
ecma_5/Object/extensibility-01.js
ecma_5/Object/vacuous-accessor-unqualified-name.js
ecma_5/RegExp/15.10.7.5-01.js ecma_5/RegExp/15.10.7.5-01.js
ecma_5/Types/8.12.5-01.js ecma_5/Types/8.12.5-01.js
ecma_5/extensions/8.12.5-01.js ecma_5/extensions/8.12.5-01.js
ecma_5/extensions/string-literal-getter-setter-decompilation.js ecma_5/extensions/string-literal-getter-setter-decompilation.js
ecma_5/extensions/15.4.4.11.js
ecma_5/misc/enumerate-undefined.js ecma_5/misc/enumerate-undefined.js
ecma_5/misc/global-numeric-properties.js ecma_5/misc/global-numeric-properties.js
ecma_5/strict/10.4.2.js ecma_5/strict/10.4.2.js
@ -629,6 +633,21 @@ ecma_5/strict/8.7.2.js
ecma_5/strict/B.1.1.js ecma_5/strict/B.1.1.js
ecma_5/strict/B.1.2.js ecma_5/strict/B.1.2.js
ecma_5/strict/regress-532254.js ecma_5/strict/regress-532254.js
ecma_5/strict/8.12.5.js
ecma_5/strict/8.12.7.js
ecma_5/strict/10.6.js
ecma_5/strict/15.3.5.1.js
ecma_5/strict/15.3.5.2.js
ecma_5/strict/15.4.4.9.js
ecma_5/strict/15.4.4.6.js
ecma_5/strict/15.4.4.8.js
ecma_5/strict/15.4.4.12.js
ecma_5/strict/15.4.5.1.js
ecma_5/strict/15.4.4.13.js
ecma_5/strict/15.5.5.1.js
ecma_5/strict/15.5.5.2.js
ecma_5/strict/15.10.7.js
ecma_5/strict/function-name-arity.js
js1_2/regexp/RegExp_multiline.js js1_2/regexp/RegExp_multiline.js
js1_2/regexp/RegExp_multiline_as_array.js js1_2/regexp/RegExp_multiline_as_array.js
js1_2/regexp/alphanumeric.js js1_2/regexp/alphanumeric.js
@ -1335,6 +1354,9 @@ js1_8_5/extensions/destructure-accessor.js
js1_8_5/extensions/reflect-parse.js js1_8_5/extensions/reflect-parse.js
js1_8_5/extensions/scripted-proxies.js js1_8_5/extensions/scripted-proxies.js
js1_8_5/extensions/typedarray.js js1_8_5/extensions/typedarray.js
js1_8_5/extensions/clone-object.js
js1_8_5/extensions/clone-errors.js
js1_8_5/extensions/clone-typed-array.js
js1_8_5/regress/regress-500528.js js1_8_5/regress/regress-500528.js
js1_8_5/regress/regress-533876.js js1_8_5/regress/regress-533876.js
js1_8_5/regress/regress-541255-0.js js1_8_5/regress/regress-541255-0.js
@ -1354,6 +1376,10 @@ js1_8_5/regress/regress-577648-1.js
js1_8_5/regress/regress-577648-2.js js1_8_5/regress/regress-577648-2.js
js1_8_5/regress/regress-584355.js js1_8_5/regress/regress-584355.js
js1_8_5/regress/regress-588339.js js1_8_5/regress/regress-588339.js
js1_8_5/regress/regress-592217.js
js1_8_5/regress/regress-596805-2.js
js1_8_5/regress/regress-597870.js
js1_8_5/regress/regress-597945-1.js
narcissus/../ecma/Date/15.9.5.10-2.js narcissus/../ecma/Date/15.9.5.10-2.js
narcissus/../ecma/Date/15.9.5.11-2.js narcissus/../ecma/Date/15.9.5.11-2.js
narcissus/../ecma/Date/15.9.5.12-2.js narcissus/../ecma/Date/15.9.5.12-2.js