More optimizations. Also removed makeCheckParameterizedArgumentType: it's expensive. Rewrote baselib.checkNaturalInRange out explicitly for better performance.

This commit is contained in:
Danny Yoo 2012-02-21 14:03:07 -05:00
parent 06bc6ad34e
commit def882c23d
3 changed files with 64 additions and 73 deletions

View File

@ -81,10 +81,11 @@
(format "RT.checkedNumEqualsSlowPath(M, [~a])" (string-join operands ","))])] (format "RT.checkedNumEqualsSlowPath(M, [~a])" (string-join operands ","))])]
[(>) [(>)
(format "RT.checkedGreaterThan(M, ~a)" (cond
(string-join operands ",")) [(< (length operands) MAX-JAVASCRIPT-ARGS-AT-ONCE)
;; (assemble-boolean-chain "plt.baselib.numbers.greaterThan" checked-operands) (format "RT.checkedGreaterThan(M, ~a)" (string-join operands ","))]
] [else
(format "RT.checkedGreaterThanSlowPath(M, [~a])" (string-join operands ","))])]
[(>=) [(>=)
(assemble-boolean-chain "plt.baselib.numbers.greaterThanOrEqual" checked-operands)] (assemble-boolean-chain "plt.baselib.numbers.greaterThanOrEqual" checked-operands)]

View File

@ -51,27 +51,6 @@
}; };
}; };
var makeCheckParameterizedArgumentType = function (parameterizedPredicate,
parameterizedPredicateName) {
return function (MACHINE, callerName, position) {
var args = [], i;
for (i = 3; i < arguments.length; i++) {
args.push(arguments[i]);
}
return testArgument(
MACHINE,
function () { return parameterizedPredicateName.apply(null, args); },
function (x) {
return parameterizedPredicate.apply(null, [x].concat(args));
},
MACHINE.e[MACHINE.e.length - 1 - position],
position,
callerName);
};
};
var makeCheckListofArgumentType = function (predicate, predicateName) { var makeCheckListofArgumentType = function (predicate, predicateName) {
@ -172,15 +151,36 @@
baselib.bytes.isBytes, baselib.bytes.isBytes,
'bytes'); 'bytes');
var checkNaturalInRange = makeCheckParameterizedArgumentType( var checkNaturalInRange = function(M, callerName, index, a, b) {
function (x, a, b) { var expectedTypeName;
if (! baselib.numbers.isNatural(x)) { return false; } var x = M.e[M.e.length - 1 - index];
return (baselib.numbers.lessThanOrEqual(a, x) && // fast path: if a, b, and x are numbers
baselib.numbers.lessThan(x, b)); if (typeof(x) === 'number' && typeof(a) === 'number' && typeof(b) === 'number') {
}, if (a <= x && x < b) {
function (a, b) { return x;
return baselib.format.format('natural between ~a and ~a', [a, b]); }
}); else {
expectedTypeName = baselib.format.format('natural between ~a and ~a', [a, b]);
return baselib.exceptions.raiseArgumentTypeError(m,
callerName,
expectedTypeName,
index,
x);
}
} else {
if (baselib.numbers.lessThanOrEqual(a, x) && baselib.numbers.lessThan(x, b)) {
return x;
} else {
expectedTypeName = baselib.format.format('natural between ~a and ~a', [a, b]);
return baselib.exceptions.raiseArgumentTypeError(m,
callerName,
expectedTypeName,
index,
x);
}
}
};
var checkInteger = makeCheckArgumentType( var checkInteger = makeCheckArgumentType(
baselib.numbers.isInteger, baselib.numbers.isInteger,
@ -271,7 +271,6 @@
exports.testArgument = testArgument; exports.testArgument = testArgument;
exports.testArity = testArity; exports.testArity = testArity;
exports.makeCheckArgumentType = makeCheckArgumentType; exports.makeCheckArgumentType = makeCheckArgumentType;
exports.makeCheckParameterizedArgumentType = makeCheckParameterizedArgumentType;
exports.makeCheckListofArgumentType = makeCheckListofArgumentType; exports.makeCheckListofArgumentType = makeCheckListofArgumentType;
exports.checkOutputPort = checkOutputPort; exports.checkOutputPort = checkOutputPort;
exports.checkInputPort = checkInputPort; exports.checkInputPort = checkInputPort;

View File

@ -834,12 +834,10 @@
}; };
var checkedAdd = function(M, x, y) { var checkedAdd = function(M, x, y) {
var i;
var sum; var sum;
// fast path optimization: binop addition on fixnums // fast path optimization: binop addition on fixnums
if (arguments.length === 3) { if (arguments.length === 3) {
if (typeof(x) === 'number' && if (typeof(x) === 'number' && typeof(y) === 'number') {
typeof(y) === 'number') {
sum = x + y; sum = x + y;
if (sum < -9e15 || sum > 9e15) { if (sum < -9e15 || sum > 9e15) {
return checkedAddSlowPath(M, Array.prototype.slice.call(arguments, 1)); return checkedAddSlowPath(M, Array.prototype.slice.call(arguments, 1));
@ -847,19 +845,7 @@
return sum; return sum;
} }
} }
return checkedAddSlowPath(M, Array.prototype.slice.call(arguments, 1));
sum = 0;
for (i = 1; i < arguments.length; i++) {
if (typeof(arguments[i]) === 'number') {
sum += arguments[i];
if (sum < -9e15 || sum > 9e15) {
return checkedAddSlowPath(M, Array.prototype.slice.call(arguments, 1));
}
} else {
return checkedAddSlowPath(M, Array.prototype.slice.call(arguments, 1));
}
}
return sum;
}; };
var checkedAddSlowPath = function(M, args) { var checkedAddSlowPath = function(M, args) {
@ -874,24 +860,20 @@
return sum; return sum;
}; };
var checkedSub = function(M) { var checkedSub = function(M, x, y) {
// Assumption: at least two arguments to subtract. // Assumption: at least two arguments to subtract.
var i; var sum;
if (typeof(arguments[1]) !== 'number') { // fast path optimization: binop subtraction on fixnums
return checkedSubSlowPath(M, Array.prototype.slice.call(arguments, 1)); if (arguments.length === 3) {
} if (typeof(x) === 'number' && typeof(y) === 'number') {
var sum = arguments[1]; sum = x - y;
for (i = 2; i < arguments.length; i++) {
if (typeof(arguments[i]) === 'number') {
sum -= arguments[i];
if (sum < -9e15 || sum > 9e15) { if (sum < -9e15 || sum > 9e15) {
return checkedSubSlowPath(M, Array.prototype.slice.call(arguments, 1)); return checkedSubSlowPath(M, Array.prototype.slice.call(arguments, 1));
} }
} else { return sum;
return checkedSubSlowPath(M, Array.prototype.slice.call(arguments, 1));
} }
} }
return sum; return checkedSubSlowPath(M, Array.prototype.slice.call(arguments, 1));
}; };
var checkedSubSlowPath = function(M, args) { var checkedSubSlowPath = function(M, args) {
@ -917,27 +899,35 @@
return x > y; return x > y;
} }
} }
return checkedGreaterThanSlowPath(M, Array.prototype.slice.call(arguments, 1));
};
// Slow path. var checkedGreaterThanSlowPath = function(M, args) {
if (! isNumber(arguments[1])) { if (! isNumber(args[0])) {
raiseArgumentTypeError(M, '>', 'number', 0, arguments[1]); raiseArgumentTypeError(M, '>', 'number', 0, args[0]);
} }
for (i = 1; i < args.length ; i++) {
for (i = 2; i < arguments.length ; i++) { if (! isNumber(args[i])) {
if (! isNumber(arguments[i])) { raiseArgumentTypeError(M, '>', 'number', i, args[i]);
raiseArgumentTypeError(M, '>', 'number', i-1, arguments[i]);
} }
if (! plt.baselib.numbers.greaterThan(arguments[i-1], if (! plt.baselib.numbers.greaterThan(args[i-1], args[i])) {
arugments[i])) {
return false; return false;
} }
} }
return true; return true;
}; };
var checkedNumEquals = function(M) {
var checkedNumEquals = function(M, x, y) {
// Assumption: at least two arguments to compare // Assumption: at least two arguments to compare
var i; var i;
// fast path optimization: binop comparison on fixnums
if (arguments.length === 3) {
if (typeof(x) === 'number' && typeof(y) === 'number') {
return x === y;
}
}
if (typeof(arguments[1]) !== 'number') { if (typeof(arguments[1]) !== 'number') {
return checkedNumEqualsSlowPath(M, Array.prototype.slice.call(arguments, 1)); return checkedNumEqualsSlowPath(M, Array.prototype.slice.call(arguments, 1));
} }
@ -1126,6 +1116,7 @@
exports['checkedNumEquals'] = checkedNumEquals; exports['checkedNumEquals'] = checkedNumEquals;
exports['checkedNumEqualsSlowPath'] = checkedNumEqualsSlowPath; exports['checkedNumEqualsSlowPath'] = checkedNumEqualsSlowPath;
exports['checkedGreaterThan'] = checkedGreaterThan; exports['checkedGreaterThan'] = checkedGreaterThan;
exports['checkedGreaterThanSlowPath'] = checkedGreaterThanSlowPath;
exports['checkedCar'] = checkedCar; exports['checkedCar'] = checkedCar;
exports['checkedCdr'] = checkedCdr; exports['checkedCdr'] = checkedCdr;
}(this.plt, this.plt.baselib)); }(this.plt, this.plt.baselib));