From 018f1b255959fa922a23c2b4780dd7e8b9b64452 Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Tue, 21 Feb 2012 14:43:21 -0500 Subject: [PATCH] special-casing vector-ref and vector-set --- compiler/compiler.rkt | 2 + compiler/kernel-primitives.rkt | 11 ++- js-assembler/assemble-open-coded.rkt | 16 +++- .../runtime-src/baselib-primitives.js | 3 +- js-assembler/runtime-src/runtime.js | 77 +++++++++++++++++++ 5 files changed, 105 insertions(+), 4 deletions(-) diff --git a/compiler/compiler.rkt b/compiler/compiler.rkt index df6c632..0813988 100644 --- a/compiler/compiler.rkt +++ b/compiler/compiler.rkt @@ -1303,6 +1303,8 @@ (box? (Const-const knowledge))] [(list) (list? (Const-const knowledge))] + [(vector) + (vector? (Const-const knowledge))] [(pair) (pair? (Const-const knowledge))] [(caarpair) diff --git a/compiler/kernel-primitives.rkt b/compiler/kernel-primitives.rkt index 0eedcaa..34fc331 100644 --- a/compiler/kernel-primitives.rkt +++ b/compiler/kernel-primitives.rkt @@ -6,6 +6,7 @@ "../type-helpers.rkt") (define-type OperandDomain (U 'number 'string + 'vector 'box 'list 'pair @@ -178,6 +179,8 @@ 'null? 'not 'eq? + 'vector-ref + 'vector-set! )) (ensure-type-subsetof KernelPrimitiveName/Inline KernelPrimitiveName) @@ -288,4 +291,10 @@ (list 'any)] [(eq? prim 'eq?) - (list 'any 'any)])) \ No newline at end of file + (list 'any 'any)] + + [(eq? prim 'vector-ref) + (list 'vector 'number)] + + [(eq? prim 'vector-set!) + (list 'vector 'number 'any)])) \ No newline at end of file diff --git a/js-assembler/assemble-open-coded.rkt b/js-assembler/assemble-open-coded.rkt index b0eb98f..9578ba6 100644 --- a/js-assembler/assemble-open-coded.rkt +++ b/js-assembler/assemble-open-coded.rkt @@ -52,8 +52,10 @@ [(*) (cond [(empty? checked-operands) (assemble-numeric-constant 1)] + [(< (length operands) MAX-JAVASCRIPT-ARGS-AT-ONCE) + (format "RT.checkedMul(M, ~a)" (string-join operands ","))] [else - (assemble-binop-chain "plt.baselib.numbers.multiply" checked-operands)])] + (format "RT.checkedMulSlowPath(M, [~a])" (string-join operands ","))])] [(/) (assemble-binop-chain "plt.baselib.numbers.divide" checked-operands)] @@ -111,6 +113,14 @@ [(list?) (format "RT.isList(~a)" (first checked-operands))] + + [(vector-ref) + (format "RT.checkedVectorRef(M, ~a)" + (string-join operands ","))] + + [(vector-set!) + (format "RT.checkedVectorSet(M, ~a)" + (string-join operands ","))] [(pair?) (format "RT.isPair(~a)" @@ -186,7 +196,9 @@ [(caarpair) (format "RT.isCaarPair")] [(box) - (format "RT.isBox")])]) + (format "RT.isBox")] + [(vector) + (format "RT.isVector")])]) (format "RT.testArgument(M,~s,~a,~a,~a,~s)" (symbol->string domain) predicate diff --git a/js-assembler/runtime-src/baselib-primitives.js b/js-assembler/runtime-src/baselib-primitives.js index 9a1a2df..b31d51c 100644 --- a/js-assembler/runtime-src/baselib-primitives.js +++ b/js-assembler/runtime-src/baselib-primitives.js @@ -1057,7 +1057,8 @@ 2, function (M) { var elts = checkVector(M, 'vector-ref', 0).elts; - var index = M.e[M.e.length-2]; + var index = baselib.numbers.toFixnum( + checkNaturalInRange(M, 'vector-ref', 1, 0, elts.length)); return elts[index]; }); diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index 9168767..c3989de 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -860,6 +860,34 @@ return sum; }; + var checkedMul = function(M, x, y) { + var prod; + // fast path optimization: binop addition on fixnums + if (arguments.length === 3) { + if (typeof(x) === 'number' && typeof(y) === 'number') { + prod = x * y; + if (prod < -9e15 || prod > 9e15) { + return checkedMulSlowPath(M, Array.prototype.slice.call(arguments, 1)); + } + return prod; + } + } + return checkedMulSlowPath(M, Array.prototype.slice.call(arguments, 1)); + }; + + var checkedMulSlowPath = function(M, args) { + var i; + var prod = 1; + for (i = 0; i < args.length; i++) { + if (! isNumber(args[i])) { + raiseArgumentTypeError(M, '*', 'number', i, args[i]); + } + prod = plt.baselib.numbers.multiply(prod, args[i]); + } + return prod; + }; + + var checkedSub = function(M, x, y) { // Assumption: at least two arguments to subtract. var sum; @@ -969,6 +997,51 @@ raiseArgumentTypeError(M, 'cdr', 'pair', 0, v); }; + var checkedVectorRef = function(M, vec, i) { + var expectedTypeName; + if (isVector(vec)) { + if (typeof(i) === 'number') { + if (i >= 0 && i < vec.elts.length) { + return vec.elts[i]; + } + } else if (isNumber(i)) { + i = baselib.numbers.toFixnum(i); + if (i >= 0 && i < vec.elts.length) { + return vec.elts[i]; + } + } + expectedTypeName = baselib.format.format('natural between 0 and ~a', + [vec.elts.length]); + raiseArgumentTypeError(M, 'vector-ref', expectedTypeName, 1, i); + } else { + raiseArgumentTypeError(M, 'vector-ref', 'vector', 0, vec); + } + }; + + + var checkedVectorSet = function(M, vec, i, val) { + var expectedTypeName; + if (isVector(vec)) { + if (typeof(i) === 'number') { + if (i >= 0 && i < vec.elts.length) { + vec.elts[i] = val; + return VOID; + } + } else if (isNumber(i)) { + i = baselib.numbers.toFixnum(i); + if (i >= 0 && i < vec.elts.length) { + vec.elts[i] = val; + return VOID; + } + } + expectedTypeName = baselib.format.format('natural between 0 and ~a', + [vec.elts.length]); + raiseArgumentTypeError(M, 'vector-set!', expectedTypeName, 1, i); + } else { + raiseArgumentTypeError(M, 'vector-set!', 'vector', 0, vec); + } + }; + ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// @@ -1111,6 +1184,8 @@ exports['checkedNegate'] = checkedNegate; exports['checkedAdd'] = checkedAdd; exports['checkedAddSlowPath'] = checkedAddSlowPath; + exports['checkedMul'] = checkedMul; + exports['checkedMulSlowPath'] = checkedMulSlowPath; exports['checkedSub'] = checkedSub; exports['checkedSubSlowPath'] = checkedSubSlowPath; exports['checkedNumEquals'] = checkedNumEquals; @@ -1119,4 +1194,6 @@ exports['checkedGreaterThanSlowPath'] = checkedGreaterThanSlowPath; exports['checkedCar'] = checkedCar; exports['checkedCdr'] = checkedCdr; + exports['checkedVectorRef'] = checkedVectorRef; + exports['checkedVectorSet'] = checkedVectorSet; }(this.plt, this.plt.baselib)); \ No newline at end of file