diff --git a/js-assembler/assemble-open-coded.rkt b/js-assembler/assemble-open-coded.rkt index a9f3b4f..b0eb98f 100644 --- a/js-assembler/assemble-open-coded.rkt +++ b/js-assembler/assemble-open-coded.rkt @@ -81,10 +81,11 @@ (format "RT.checkedNumEqualsSlowPath(M, [~a])" (string-join operands ","))])] [(>) - (format "RT.checkedGreaterThan(M, ~a)" - (string-join operands ",")) - ;; (assemble-boolean-chain "plt.baselib.numbers.greaterThan" checked-operands) - ] + (cond + [(< (length operands) MAX-JAVASCRIPT-ARGS-AT-ONCE) + (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)] diff --git a/js-assembler/runtime-src/baselib-check.js b/js-assembler/runtime-src/baselib-check.js index 64e4c32..44ed920 100644 --- a/js-assembler/runtime-src/baselib-check.js +++ b/js-assembler/runtime-src/baselib-check.js @@ -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) { @@ -172,15 +151,36 @@ baselib.bytes.isBytes, 'bytes'); - var checkNaturalInRange = makeCheckParameterizedArgumentType( - function (x, a, b) { - if (! baselib.numbers.isNatural(x)) { return false; } - return (baselib.numbers.lessThanOrEqual(a, x) && - baselib.numbers.lessThan(x, b)); - }, - function (a, b) { - return baselib.format.format('natural between ~a and ~a', [a, b]); - }); + var checkNaturalInRange = function(M, callerName, index, a, b) { + var expectedTypeName; + var x = M.e[M.e.length - 1 - index]; + // fast path: if a, b, and x are numbers + if (typeof(x) === 'number' && typeof(a) === 'number' && typeof(b) === 'number') { + if (a <= x && 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); + } + } 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( baselib.numbers.isInteger, @@ -271,7 +271,6 @@ exports.testArgument = testArgument; exports.testArity = testArity; exports.makeCheckArgumentType = makeCheckArgumentType; - exports.makeCheckParameterizedArgumentType = makeCheckParameterizedArgumentType; exports.makeCheckListofArgumentType = makeCheckListofArgumentType; exports.checkOutputPort = checkOutputPort; exports.checkInputPort = checkInputPort; diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index c5c3c37..9168767 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -834,12 +834,10 @@ }; var checkedAdd = function(M, x, y) { - var i; var sum; // fast path optimization: binop addition on fixnums if (arguments.length === 3) { - if (typeof(x) === 'number' && - typeof(y) === 'number') { + if (typeof(x) === 'number' && typeof(y) === 'number') { sum = x + y; if (sum < -9e15 || sum > 9e15) { return checkedAddSlowPath(M, Array.prototype.slice.call(arguments, 1)); @@ -847,19 +845,7 @@ return sum; } } - - 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; + return checkedAddSlowPath(M, Array.prototype.slice.call(arguments, 1)); }; var checkedAddSlowPath = function(M, args) { @@ -874,24 +860,20 @@ return sum; }; - var checkedSub = function(M) { + var checkedSub = function(M, x, y) { // Assumption: at least two arguments to subtract. - var i; - if (typeof(arguments[1]) !== 'number') { - return checkedSubSlowPath(M, Array.prototype.slice.call(arguments, 1)); - } - var sum = arguments[1]; - for (i = 2; i < arguments.length; i++) { - if (typeof(arguments[i]) === 'number') { - sum -= arguments[i]; + var sum; + // fast path optimization: binop subtraction on fixnums + if (arguments.length === 3) { + if (typeof(x) === 'number' && typeof(y) === 'number') { + sum = x - y; if (sum < -9e15 || sum > 9e15) { return checkedSubSlowPath(M, Array.prototype.slice.call(arguments, 1)); } - } else { - return checkedSubSlowPath(M, Array.prototype.slice.call(arguments, 1)); + return sum; } } - return sum; + return checkedSubSlowPath(M, Array.prototype.slice.call(arguments, 1)); }; var checkedSubSlowPath = function(M, args) { @@ -917,27 +899,35 @@ return x > y; } } + return checkedGreaterThanSlowPath(M, Array.prototype.slice.call(arguments, 1)); + }; - // Slow path. - if (! isNumber(arguments[1])) { - raiseArgumentTypeError(M, '>', 'number', 0, arguments[1]); + var checkedGreaterThanSlowPath = function(M, args) { + if (! isNumber(args[0])) { + raiseArgumentTypeError(M, '>', 'number', 0, args[0]); } - - for (i = 2; i < arguments.length ; i++) { - if (! isNumber(arguments[i])) { - raiseArgumentTypeError(M, '>', 'number', i-1, arguments[i]); + for (i = 1; i < args.length ; i++) { + if (! isNumber(args[i])) { + raiseArgumentTypeError(M, '>', 'number', i, args[i]); } - if (! plt.baselib.numbers.greaterThan(arguments[i-1], - arugments[i])) { + if (! plt.baselib.numbers.greaterThan(args[i-1], args[i])) { return false; } } return true; }; - var checkedNumEquals = function(M) { + + var checkedNumEquals = function(M, x, y) { // Assumption: at least two arguments to compare 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') { return checkedNumEqualsSlowPath(M, Array.prototype.slice.call(arguments, 1)); } @@ -1126,6 +1116,7 @@ exports['checkedNumEquals'] = checkedNumEquals; exports['checkedNumEqualsSlowPath'] = checkedNumEqualsSlowPath; exports['checkedGreaterThan'] = checkedGreaterThan; + exports['checkedGreaterThanSlowPath'] = checkedGreaterThanSlowPath; exports['checkedCar'] = checkedCar; exports['checkedCdr'] = checkedCdr; }(this.plt, this.plt.baselib)); \ No newline at end of file