return x === y;
}
+function try_finally(trythunk, finalthunk) {
+ /* Call the TRYTHUNK. When TRYTHUNK exits (even if it's with an exception)
+ * then call FINALTHUNK. If TRYTHUNK returned normally then return its
+ * value; otherwise continue with the non-local flow control.
+ *
+ * This is an unpleasant hack because V8 doesn't optimize functions which
+ * contain try/finally very well (despite this being an easy transformation
+ * for the compiler).
+ */
+
+ try { return trythunk(); }
+ finally { finalthunk(); }
+}
+
+function try_cleanup(trythunk, cleanthunk) {
+ /* Call the TRYTHUNK. If TRYTHUNK returns normally, just return its value;
+ * otherwise call CLEANTHUNK and re-throw the exception.
+ *
+ * This is an unpleasant hack because V8 doesn't optimize functions which
+ * contain try/catch very well (despite this being an easy transformation
+ * for the compiler).
+ */
+
+ var e;
+ try { return trythunk(); }
+ catch (e) { cleanthunk(); throw e; }
+}
+
/* A Tag is an object which is interesting only because of its identity, and
* that the set of Tags is basically determined by the static structure of
* the program.
*/
var old = EVALUATING;
- var val, e;
+ var me = this;
+ var val;
this._dependencies = { };
- try {
- EVALUATING = this;
- try {
- return this._value_function();
- } catch (e) {
- if (e === BAD) return BAD;
- else throw e;
- }
- } finally {
+ return try_finally(function () {
+ EVALUATING = me;
+ return orelse(function () { return me._value_function(); },
+ function () { return BAD; });
+ }, function() {
EVALUATING = old;
- }
+ });
},
_propagate: function () {
*/
var queued = this.__flags & F_QUEUED;
- var e;
var me = this;
// Update us with the given VALUE.
// Try to recompute our value. If that doesn't work then mark us as bad
// and propagate that.
- try {
- return update(this._new_value());
- } catch (e) {
- update(BAD);
- throw e;
- }
+ return try_cleanup(function () { return update(me._new_value()); },
+ function () { update(BAD); });
},
_force: function () {
var d, f;
state = 'recomputing';
- try {
+ try_finally(function () {
while (PENDING.length) {
d = PENDING.shift();
f = d.__flags;
d.__flags = f | F_DEPS;
}
}
- } finally {
+ }, function () {
while (PENDING.length) {
d = PENDING.shift();
d._value = BAD;
}
- }
+ });
}
function with_frozen(body, delay) {
case 'ready':
old_delayed = DELAYED;
old_pending = PENDING;
- try {
+ try_finally(function () {
DELAYED = [];
PENDING = [];
GENERATION = new Generation('dep-generation');
op = DELAYED.shift();
op();
}
- } finally {
+ }, function () {
DELAYED = old_delayed;
PENDING = old_pending;
- }
+ });
break;
}
}