Permalink
Browse files

Fixed cse.

  • Loading branch information...
1 parent a077e59 commit f3e58adcee8bd72ad019392904a4917138146272 @mbebenita mbebenita committed Jun 13, 2012
Showing with 74 additions and 47 deletions.
  1. +2 −4 src/avm2/bin/shu.py
  2. +66 −35 src/avm2/compiler/compiler.js
  3. +6 −8 src/avm2/runtime.js
View
@@ -293,8 +293,6 @@ def execute(self, args):
print "KINDOF - the \"PASSED\" and \"FAILED\" string appear in the output."
print "FAILED - the \"PASSED\" string doesn't appear anywhere."
print "---------------------------------------------------------------------------------------------------------"
- print "Interpreter Time, Time Ratio, Compiler, Time, Time Ratio, Interpreter/Compiler, Time Ratio, Number, File"
- print "---------------------------------------------------------------------------------------------------------"
tests = Queue.Queue();
@@ -338,8 +336,8 @@ def runTest(tests, counts):
modes = {}
modes["a"] = [self.avm, test]
modes["i"] = ["js", "-m", "-n", "avm.js", "-x", "-i", test];
- modes["c"] = ["js", "-m", "-n", "avm.js", "-x", "-cse=false", test];
- modes["o"] = ["js", "-m", "-n", "avm.js", "-x", "-acc=false", test];
+ modes["c"] = ["js", "-m", "-n", "avm.js", "-x", "-opt=false", test];
+ modes["o"] = ["js", "-m", "-n", "avm.js", "-x", test];
results = {}
@@ -1,5 +1,4 @@
-var enableCSE = options.register(new Option("cse", "cse", true, "Common Subexpression Elimination"));
-var enableAccessors = options.register(new Option("acc", "acc", true, "Use accessors to get/set values via runtime multinames. "));
+var enableOpt = options.register(new Option("opt", "opt", true, "Enable optimizations."));
const T = estransform;
@@ -121,6 +120,9 @@ var Compiler = (function () {
Literal.call(this, value);
}
}
+ constant.prototype.isEquivalent = function (other) {
+ return other instanceof Constant && this.value === other.value;
+ };
return constant;
})();
@@ -296,7 +298,9 @@ var Compiler = (function () {
};
findProperty.prototype = Object.create(CallExpression.prototype);
findProperty.prototype.isEquivalent = function isEquivalent(other) {
- return other instanceof findProperty && this.multiname === other.multiname && this.strict === other.strict;
+ return other instanceof findProperty &&
+ this.multiname.isEquivalent(other.multiname) &&
+ this.strict === other.strict;
};
return findProperty;
})();
@@ -322,23 +326,27 @@ var Compiler = (function () {
* Keeps track of a pool of variables that may be reused.
*/
var VariablePool = (function () {
- var count = 0;
function variablePool() {
+ this.count = 0;
this.used = [];
this.available = [];
}
variablePool.prototype.acquire = function () {
if (!this.available.empty()) {
return this.available.pop();
}
- var variable = new Variable("v" + count++);
+ var variable = new Variable("v" + this.count++);
this.used.push(variable);
return variable;
};
variablePool.prototype.release = function (variable) {
assert (this.used.contains(variable));
this.available.push(variable);
};
+ variablePool.prototype.releaseAll = function () {
+ this.available = this.available.concat(this.used);
+ this.used = [];
+ };
return variablePool;
})();
@@ -358,7 +366,7 @@ var Compiler = (function () {
/**
* Finds and returns an equivalent value or returns null if not found.
- * If [allocate] is true, then if an equivalent value is not found the
+ * If |allocate| is true and an equivalent value is not found, then
* a variable is allocated for the current value and the original value
* is returned.
*/
@@ -388,6 +396,11 @@ var Compiler = (function () {
return value;
};
+ cse.prototype.reset = function reset() {
+ this.values = [];
+ this.variablePool.releaseAll();
+ };
+
return cse;
})();
@@ -592,21 +605,26 @@ var Compiler = (function () {
function push(value) {
assert (typeof value !== "string");
- if (enableCSE.value && value instanceof FindProperty) {
- cseValue(value);
- } else {
- state.stack.push(value);
- }
+ state.stack.push(value);
}
function cseValue(value) {
- assert (value);
if (block.cse) {
var otherValue = block.cse.get(value, true);
if (otherValue === value) {
+ // flushStack();
emit(assignment(value.variable, value));
+ value.variable.value = value;
+ // print("CSE: " + generate(value) + " -> " + value.variable);
}
- state.stack.push(otherValue.variable);
+ return otherValue.variable;
+ }
+ return value;
+ }
+
+ function flushScope() {
+ if (block.cse) {
+ block.cse.reset();
}
}
@@ -671,7 +689,7 @@ var Compiler = (function () {
// TODO
}
- if (enableCSE.value) {
+ if (enableOpt.value) {
if (block.dominator === block) {
block.cse = new CSE(null, this.variablePool);
} else {
@@ -720,29 +738,24 @@ var Compiler = (function () {
* Find the scope object containing the specified multiname.
*/
function findProperty(multiname, strict) {
- /*
- if (false && !multiname.isQName()) {
- if (savedScope) {
- var resolved = savedScope.resolveMultiname(multiname);
- if (resolved) {
- return new FindProperty(resolved, strict);
- }
- }
- }
- */
- return new FindProperty(multiname, strict);
+ return cseValue(new FindProperty(multiname, strict));
}
function getProperty(obj, multiname) {
assert (!(multiname instanceof Multiname), multiname);
- /*
- if (obj instanceof FindProperty &&
- obj.multiname.name === multiname.name &&
- obj.multiname.isQName()) {
- return property(obj, obj.multiname.getQualifiedName());
+ if (enableOpt.value && multiname instanceof RuntimeMultiname) {
+ return new MemberExpression(obj, multiname.name, true);
+ }
+
+ if (multiname instanceof Constant) {
+ var val = obj instanceof Variable ? obj.value : obj;
+ if (val instanceof FindProperty && multiname.isEquivalent(val.multiname)) {
+ if (multiname.value.isQName()) {
+ return property(obj, multiname.value.getQualifiedName());
+ }
+ }
}
- */
/**
* Looping over arrays by index will use a MultinameL
@@ -770,14 +783,30 @@ var Compiler = (function () {
}
function setProperty(obj, multiname, value) {
+ if (enableOpt.value && multiname instanceof RuntimeMultiname) {
+ return assignment(new MemberExpression(obj, multiname.name, true), value);
+ }
return call(id("setProperty"), [obj, multiname, value]);
}
function getMultiname(index) {
- assert (!multinames[index].isRuntime());
- return constant(multinames[index]);
+ var multiname = multinames[index];
+ assert (!multiname.isRuntime());
+ var c = constant(multiname);
+ c.multiname = multiname;
+ return c;
}
+ var RuntimeMultiname = (function () {
+ function runtimeMultiname(multiname, ns, name) {
+ this.multiname = multiname;
+ this.ns = ns;
+ this.name = name;
+ NewExpression.call(this, id("Multiname"), [ns, name]);
+ };
+ return runtimeMultiname;
+ })();
+
function popMultiname(index) {
var multiname = multinames[index];
if (multiname.isRuntime()) {
@@ -788,7 +817,7 @@ var Compiler = (function () {
if (multiname.isRuntimeNamespace()) {
ns = state.stack.pop();
}
- return new NewExpression(id("Multiname"), [ns, name]);
+ return new RuntimeMultiname(multiname, ns, name);
} else {
return constant(multiname);
}
@@ -850,6 +879,7 @@ var Compiler = (function () {
break;
case OP_popscope:
flushStack();
+ flushScope();
emit(assignment(scopeName, property(scopeName, "parent")));
state.scopeHeight -= 1;
break;
@@ -889,6 +919,7 @@ var Compiler = (function () {
case OP_swap: state.stack.push(state.stack.pop(), state.stack.pop()); break;
case OP_pushscope:
flushStack();
+ flushScope();
obj = state.stack.pop();
emit(assignment(scopeName, new NewExpression(id("Scope"), [scopeName, obj])));
state.scopeHeight += 1;
@@ -1072,7 +1103,7 @@ var Compiler = (function () {
break;
case OP_coerce_b:
case OP_convert_b:
- push(call(id("toBoolean"), [state.stack.pop()]));
+ push(new UnaryExpression(Operator.FALSE, new UnaryExpression(Operator.FALSE, state.stack.pop())));
break;
case OP_convert_o: notImplemented(); break;
case OP_checkfilter: notImplemented(); break;
View
@@ -110,7 +110,7 @@ function toDouble(x) {
}
function toBoolean(x) {
- return Boolean(x);
+ return !!x;
}
function toUint(x) {
@@ -422,17 +422,15 @@ function setProperty(obj, multiname, value) {
}
var name = resolved.getQualifiedName();
- var type = obj.types[name];
-
- if (tracePropertyAccess.value && type) {
- print("setProperty: coercing to type:" + type);
- }
+ setPropertyQuick(obj, name, value);
+}
+function setPropertyQuick(obj, qualifiedName, value) {
+ var type = obj.types[qualifiedName];
if (type && type.coerce) {
value = type.coerce(value);
}
-
- obj[name] = value;
+ obj[qualifiedName] = value;
}
function throwErrorFromVM(errorClass, message) {

0 comments on commit f3e58ad

Please sign in to comment.