Bug 760413 - Update in-tree V8 benchmark to v7. r=dvander
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 01 Jun 2012 13:54:54 +0200
changeset 95747 778ba119ded663eb5520f57fdf5df13785db69d2
parent 95746 1fa953e7d4c15b19a763b888e1f22ecb1ff81d05
child 95748 fc94f4339da76d758d62aa447eb7b420bd1caaba
child 95767 b6067aa7736029baafa3d8d98b146223e588e0c3
push idunknown
push userunknown
push dateunknown
reviewersdvander
bugs760413
milestone15.0a1
Bug 760413 - Update in-tree V8 benchmark to v7. r=dvander
js/src/v8/base.js
js/src/v8/crypto.js
js/src/v8/earley-boyer.js
js/src/v8/navier-stokes.js
js/src/v8/regexp.js
js/src/v8/run-navier-stokes.js
js/src/v8/run.js
--- a/js/src/v8/base.js
+++ b/js/src/v8/base.js
@@ -1,9 +1,9 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
 //
 //     * Redistributions of source code must retain the above copyright
 //       notice, this list of conditions and the following disclaimer.
 //     * Redistributions in binary form must reproduce the above
 //       copyright notice, this list of conditions and the following
@@ -73,17 +73,17 @@ function BenchmarkSuite(name, reference,
 
 // Keep track of all declared benchmark suites.
 BenchmarkSuite.suites = [];
 
 
 // Scores are not comparable across versions. Bump the version if
 // you're making changes that will affect that scores, e.g. if you add
 // a new benchmark or change an existing one.
-BenchmarkSuite.version = '6';
+BenchmarkSuite.version = '7';
 
 
 // To make the benchmark results predictable, we replace Math.random
 // with a 100% deterministic alternative.
 Math.random = (function() {
   var seed = 49734321;
   return function() {
     // Robert Jenkins' 32 bit integer hash function.
--- a/js/src/v8/crypto.js
+++ b/js/src/v8/crypto.js
@@ -1401,17 +1401,17 @@ function rng_seed_int(x) {
   rng_pool[rng_pptr++] ^= (x >> 8) & 255;
   rng_pool[rng_pptr++] ^= (x >> 16) & 255;
   rng_pool[rng_pptr++] ^= (x >> 24) & 255;
   if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;
 }
 
 // Mix in the current time (w/milliseconds) into the pool
 function rng_seed_time() {
-  // Use pre-computed date to avoid making the benchmark 
+  // Use pre-computed date to avoid making the benchmark
   // results dependent on the current date.
   rng_seed_int(1122926989487);
 }
 
 // Initialize the pool with junk if needed.
 if(rng_pool == null) {
   rng_pool = new Array();
   rng_pptr = 0;
--- a/js/src/v8/earley-boyer.js
+++ b/js/src/v8/earley-boyer.js
@@ -129,17 +129,17 @@ function sc_rempropBang(sym, key) {
     var ht = sc_properties[sym];
     if (ht)
 	delete ht[key];
 }
 
 /*** META ((export #t)) */
 function sc_any2String(o) {
     return jsstring2string(sc_toDisplayString(o));
-}    
+}
 
 /*** META ((export #t)
            (peephole (infix 2 2 "==="))
            (type bool))
 */
 function sc_isEqv(o1, o2) {
     return (o1 === o2);
 }
@@ -918,17 +918,17 @@ function sc_append() {
 function sc_dualAppendBang(l1, l2) {
     if (l1 === null) return l2;
     if (l2 === null) return l1;
     var tmp = l1;
     while (tmp.cdr !== null) tmp=tmp.cdr;
     tmp.cdr = l2;
     return l1;
 }
-    
+
 /*** META ((export #t)) */
 function sc_appendBang() {
     var res = null;
     for (var i = 0; i < arguments.length; i++)
 	res = sc_dualAppendBang(res, arguments[i]);
     return res;
 }
 
@@ -1158,17 +1158,17 @@ sc_Char.readable2char = {
     "sub": "\032",
     "esc": "\033",
     "fs": "\034",
     "gs": "\035",
     "rs": "\036",
     "us": "\037",
     "sp": "\040",
     "del": "\177"};
-    
+
 sc_Char.prototype.toString = function() {
     return this.val;
 };
 // sc_toDisplayString == toString
 sc_Char.prototype.sc_toWriteString = function() {
     var entry = sc_Char.char2readable[this.val];
     if (entry)
 	return entry;
@@ -1528,17 +1528,17 @@ function sc_mapBang(proc, l1) {
 	for (var i = 0; i < nbApplyArgs; i++) {
 	    applyArgs[i] = arguments[i + 1].car;
 	    arguments[i + 1] = arguments[i + 1].cdr;
 	}
 	tmp.car = proc.apply(null, applyArgs);
     }
     return l1_orig;
 }
-     
+
 /*** META ((export #t)) */
 function sc_forEach(proc, l1) {
     if (l1 === undefined)
 	return undefined;
     // else
     var nbApplyArgs = arguments.length - 1;
     var applyArgs = new Array(nbApplyArgs);
     while (l1 !== null) {
@@ -1866,42 +1866,42 @@ function sc_jsMethodCall(o, field) {
 */
 function sc_jsNew(c) {
     var evalStr = "new c(";
     evalStr +=arguments.length > 1? "arguments[1]": "";
     for (var i = 2; i < arguments.length; i++)
 	evalStr += ", arguments[" + i + "]";
     evalStr +=")";
     return eval(evalStr);
-}    
+}
 
 // ======================== RegExp ====================
 /*** META ((export #t)) */
 function sc_pregexp(re) {
     return new RegExp(sc_string2jsstring(re));
 }
 
 /*** META ((export #t)) */
 function sc_pregexpMatch(re, s) {
     var reg = (re instanceof RegExp) ? re : sc_pregexp(re);
     var tmp = reg.exec(sc_string2jsstring(s));
-    
+
     if (tmp == null) return false;
-    
+
     var res = null;
     for (var i = tmp.length-1; i >= 0; i--) {
 	if (tmp[i] !== null) {
 	    res = sc_cons(sc_jsstring2string(tmp[i]), res);
 	} else {
 	    res = sc_cons(false, res);
 	}
     }
     return res;
 }
-   
+
 /*** META ((export #t)) */
 function sc_pregexpReplace(re, s1, s2) {
    var reg;
    var jss1 = sc_string2jsstring(s1);
    var jss2 = sc_string2jsstring(s2);
 
    if (re instanceof RegExp) {
        if (re.global)
@@ -1909,17 +1909,17 @@ function sc_pregexpReplace(re, s1, s2) {
        else
 	   reg = new RegExp(re.source);
    } else {
        reg = new RegExp(sc_string2jsstring(re));
    }
 
    return jss1.replace(reg, jss2);
 }
-   
+
 /*** META ((export pregexp-replace*)) */
 function sc_pregexpReplaceAll(re, s1, s2) {
    var reg;
    var jss1 = sc_string2jsstring(s1);
    var jss2 = sc_string2jsstring(s2);
 
    if (re instanceof RegExp) {
       if (re.global)
@@ -1940,17 +1940,17 @@ function sc_pregexpSplit(re, s) {
 	      new RegExp(sc_string2jsstring(re)));
    var jss = sc_string2jsstring(s);
    var tmp = jss.split(reg);
 
    if (tmp == null) return false;
 
    return sc_vector2list(tmp);
 }
-   
+
 
 /* =========================================================================== */
 /* Other library stuff */
 /* =========================================================================== */
 
 /*** META ((export #t)
            (peephole (hole 1 "Math.floor(Math.random()*" 'n ")")))
 */
@@ -2131,17 +2131,17 @@ function sc_ErrorInputPort() {
 };
 sc_ErrorInputPort.prototype = new sc_InputPort();
 sc_ErrorInputPort.prototype.getNextChar = function() {
     throw "can't read from error-port.";
 };
 sc_ErrorInputPort.prototype.isCharReady = function() {
     return false;
 };
-    
+
 
 /* .............. String port ..........................*/
 
 function sc_StringInputPort(jsStr) {
     // we are going to do some charAts on the str.
     // instead of recreating all the time a String-object, we
     // create one in the beginning. (not sure, if this is really an optim)
     this.str = new String(jsStr);
@@ -2195,17 +2195,17 @@ sc_Tokenizer.prototype.peekToken = funct
 };
 sc_Tokenizer.prototype.readToken = function() {
     var tmp = this.peekToken();
     delete this.peeked;
     return tmp;
 };
 sc_Tokenizer.prototype.nextToken = function() {
     var port = this.port;
-    
+
     function isNumberChar(c) {
 	return (c >= "0" && c <= "9");
     };
     function isIdOrNumberChar(c) {
 	return SC_ID_CLASS.indexOf(c) != -1 || // ID-char
 	    (c >= "0" && c <= "9");
     }
     function isWhitespace(c) {
@@ -2275,17 +2275,17 @@ sc_Tokenizer.prototype.nextToken = funct
 	var res = firstChar;
 	while (isIdOrNumberChar(port.peekChar()))
 	    res += port.readChar();
 	if (isNaN(res))
 	    return new sc_Token(9/*ID*/, res);
 	else
 	    return new sc_Token(12/*NUMBER*/, res - 0);
     };
-    
+
     function skipWhitespaceAndComments() {
 	var done = false;
 	while (!done) {
 	    done = true;
 	    while (isWhitespace(port.peekChar()))
 		port.readChar();
 	    if (port.peekChar() === ';') {
 		port.readChar();
@@ -2294,17 +2294,17 @@ sc_Tokenizer.prototype.nextToken = funct
 		    curChar = port.readChar();
 		    if (curChar === SC_EOF_OBJECT ||
 			curChar === '\n')
 			break;
 		}
 	    }
 	}
     };
-    
+
     function readDot() {
 	if (isWhitespace(port.peekChar()))
 	    return new sc_Token(10/*DOT*/);
 	else
 	    return readIdOrNumber(".");
     };
 
     function readSharp() {
@@ -2424,17 +2424,17 @@ sc_Reader.prototype.read = function() {
 	    return open === 1/*OPEN_PAR*/ && close === 2/*CLOSE_PAR*/
 	    	|| open === 3/*OPEN_BRACE*/ && close === 4/*CLOSE_BRACE*/
 		|| open === 5/*OPEN_BRACKET*/ && close === 6/*CLOSE_BRACKET*/;
 	};
 	var res = null;
 
 	while (true) {
 	    var token = tokenizer.peekToken();
-	    
+
 	    switch (token.type) {
 	    case 2/*CLOSE_PAR*/:
 	    case 4/*CLOSE_BRACE*/:
 	    case 6/*CLOSE_BRACKET*/:
 		if (matchesPeer(listBeginType, token.type)) {
 		    tokenizer.readToken(); // consume token
 		    return sc_reverseBang(res);
 		} else
@@ -2486,25 +2486,25 @@ sc_Reader.prototype.read = function() {
     };
 	
     function readReference(nb) {
 	if (nb in this.backref)
 	    return this.backref[nb];
 	else
 	    throw "bad reference: " + nb;
     };
-    
+
     var tokenizer = this.tokenizer;
 
     var token = tokenizer.readToken();
 
     // handle error
     if (token.type === 13/*ERROR*/)
 	throw token.val;
-    
+
     switch (token.type) {
     case 1/*OPEN_PAR*/:
     case 3/*OPEN_BRACE*/:
     case 5/*OPEN_BRACKET*/:
 	return readList.call(this, token.type);
     case 8/*QUOTE*/:
 	return readQuote.call(this);
     case 11/*STRING*/:
@@ -2545,17 +2545,17 @@ function sc_readChar(port) {
     return t === SC_EOF_OBJECT? t: new sc_Char(t);
 }
 /*** META ((export #t)) */
 function sc_peekChar(port) {
     if (port === undefined) // we assume the port hasn't been given.
 	port = SC_DEFAULT_IN; // THREAD: shared var...
     var t = port.peekChar();
     return t === SC_EOF_OBJECT? t: new sc_Char(t);
-}    
+}
 /*** META ((export #t)
            (type bool))
 */
 function sc_isCharReady(port) {
     if (port === undefined) // we assume the port hasn't been given.
 	port = SC_DEFAULT_IN; // THREAD: shared var...
     return port.isCharReady();
 }
@@ -2717,17 +2717,17 @@ sc_StringOutputPort.prototype.appendJSSt
 sc_StringOutputPort.prototype.close = function() {
     return sc_jsstring2string(this.res);
 }
 
 /*** META ((export #t)) */
 function sc_getOutputString(sp) {
     return sc_jsstring2string(sp.res);
 }
-    
+
 
 function sc_ErrorOutputPort() {
 }
 sc_ErrorOutputPort.prototype = new sc_OutputPort();
 sc_ErrorOutputPort.prototype.appendJSString = function(s) {
     throw "don't write on ErrorPort!";
 }
 sc_ErrorOutputPort.prototype.close = function() {
@@ -2847,17 +2847,17 @@ function sc_toDisplayString(o) {
 /* ------------------ newline ---------------------------------------------------*/
 
 /*** META ((export #t)) */
 function sc_newline(p) {
     if (p === undefined) // we assume not given
 	p = SC_DEFAULT_OUT;
     p.appendJSString("\n");
 }
-    
+
 /* ------------------ write-char ---------------------------------------------------*/
 
 /*** META ((export #t)) */
 function sc_writeChar(c, p) {
     if (p === undefined) // we assume not given
 	p = SC_DEFAULT_OUT;
     p.appendJSString(c.val);
 }
@@ -2922,32 +2922,32 @@ sc_Pair.prototype.sc_toWriteCircleString
     }
     if (this[symb]-- === 0) { // if we are the last use. remove all fields.
 	delete this[symb];
 	delete this[symb + "nb"];
 	delete this[symb + "use"];
     }
 
     var res = "";
-    
+
     if (this[symb] !== undefined) { // implies > 0
 	this[symb + "use"] = true;
 	if (inList)
 	    res += '. #' + this[symb + "nb"] + '=';
 	else
 	    res += '#' + this[symb + "nb"] + '=';
 	inList = false;
     }
 
     if (!inList)
 	res += "(";
-    
+
     // print car
     res += sc_genToWriteCircleString(this.car, symb);
-    
+
     if (sc_isPair(this.cdr)) {
 	res += " " + this.cdr.sc_toWriteCircleString(symb, true);
     } else if (this.cdr !== null) {
 	res += " . " + sc_genToWriteCircleString(this.cdr, symb);
     }
     if (!inList)
 	res += ")";
     return res;
@@ -3067,17 +3067,17 @@ function sc_format(s, args) {
 	       break;
 
 	    case 66:
 	    case 98:
 	       // b
 	       p.appendJSString(arguments[j].toString(2));
 	       i += 2; j++;
 	       break;
-	       
+
 	    case 37:
 	    case 110:
 	       // %, n
 	       p.appendJSString("\n");
 	       i += 2; break;
 
 	    case 114:
 	       // r
@@ -3181,17 +3181,17 @@ function sc_isEqual(o1, o2) {
 	    (sc_isVector(o1) && sc_isVector(o2)
 	     && sc_isVectorEqual(o1, o2, sc_isEqual)));
 }
 
 /*** META ((export number->symbol integer->symbol)) */
 function sc_number2symbol(x, radix) {
     return sc_SYMBOL_PREFIX + sc_number2jsstring(x, radix);
 }
-    
+
 /*** META ((export number->string integer->string)) */
 var sc_number2string = sc_number2jsstring;
 
 /*** META ((export #t)) */
 function sc_symbol2number(s, radix) {
     return sc_jsstring2number(s.slice(1), radix);
 }
 
new file mode 100644
--- /dev/null
+++ b/js/src/v8/navier-stokes.js
@@ -0,0 +1,387 @@
+/**
+ * Copyright 2012 the V8 project authors. All rights reserved.
+ * Copyright 2009 Oliver Hunt <http://nerget.com>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+var NavierStokes = new BenchmarkSuite('NavierStokes', 1484000,
+                                      [new Benchmark('NavierStokes',
+                                                     runNavierStokes,
+                                                     setupNavierStokes,
+                                                     tearDownNavierStokes)]);
+
+var solver = null;
+
+function runNavierStokes()
+{
+    solver.update();
+}
+
+function setupNavierStokes()
+{
+    solver = new FluidField(null);
+    solver.setResolution(128, 128);
+    solver.setIterations(20);
+    solver.setDisplayFunction(function(){});
+    solver.setUICallback(prepareFrame);
+    solver.reset();
+}
+
+function tearDownNavierStokes()
+{
+    solver = null;
+}
+
+function addPoints(field) {
+    var n = 64;
+    for (var i = 1; i <= n; i++) {
+        field.setVelocity(i, i, n, n);
+        field.setDensity(i, i, 5);
+        field.setVelocity(i, n - i, -n, -n);
+        field.setDensity(i, n - i, 20);
+        field.setVelocity(128 - i, n + i, -n, -n);
+        field.setDensity(128 - i, n + i, 30);
+    }
+}
+
+var framesTillAddingPoints = 0;
+var framesBetweenAddingPoints = 5;
+
+function prepareFrame(field)
+{
+    if (framesTillAddingPoints == 0) {
+        addPoints(field);
+        framesTillAddingPoints = framesBetweenAddingPoints;
+        framesBetweenAddingPoints++;
+    } else {
+        framesTillAddingPoints--;
+    }
+}
+
+// Code from Oliver Hunt (http://nerget.com/fluidSim/pressure.js) starts here.
+function FluidField(canvas) {
+    function addFields(x, s, dt)
+    {
+        for (var i=0; i<size ; i++ ) x[i] += dt*s[i];
+    }
+
+    function set_bnd(b, x)
+    {
+        if (b===1) {
+            for (var i = 1; i <= width; i++) {
+                x[i] =  x[i + rowSize];
+                x[i + (height+1) *rowSize] = x[i + height * rowSize];
+            }
+
+            for (var j = 1; i <= height; i++) {
+                x[j * rowSize] = -x[1 + j * rowSize];
+                x[(width + 1) + j * rowSize] = -x[width + j * rowSize];
+            }
+        } else if (b === 2) {
+            for (var i = 1; i <= width; i++) {
+                x[i] = -x[i + rowSize];
+                x[i + (height + 1) * rowSize] = -x[i + height * rowSize];
+            }
+
+            for (var j = 1; j <= height; j++) {
+                x[j * rowSize] =  x[1 + j * rowSize];
+                x[(width + 1) + j * rowSize] =  x[width + j * rowSize];
+            }
+        } else {
+            for (var i = 1; i <= width; i++) {
+                x[i] =  x[i + rowSize];
+                x[i + (height + 1) * rowSize] = x[i + height * rowSize];
+            }
+
+            for (var j = 1; j <= height; j++) {
+                x[j * rowSize] =  x[1 + j * rowSize];
+                x[(width + 1) + j * rowSize] =  x[width + j * rowSize];
+            }
+        }
+        var maxEdge = (height + 1) * rowSize;
+        x[0]                 = 0.5 * (x[1] + x[rowSize]);
+        x[maxEdge]           = 0.5 * (x[1 + maxEdge] + x[height * rowSize]);
+        x[(width+1)]         = 0.5 * (x[width] + x[(width + 1) + rowSize]);
+        x[(width+1)+maxEdge] = 0.5 * (x[width + maxEdge] + x[(width + 1) + height * rowSize]);
+    }
+
+    function lin_solve(b, x, x0, a, c)
+    {
+        if (a === 0 && c === 1) {
+            for (var j=1 ; j<=height; j++) {
+                var currentRow = j * rowSize;
+                ++currentRow;
+                for (var i = 0; i < width; i++) {
+                    x[currentRow] = x0[currentRow];
+                    ++currentRow;
+                }
+            }
+            set_bnd(b, x);
+        } else {
+            var invC = 1 / c;
+            for (var k=0 ; k<iterations; k++) {
+                for (var j=1 ; j<=height; j++) {
+                    var lastRow = (j - 1) * rowSize;
+                    var currentRow = j * rowSize;
+                    var nextRow = (j + 1) * rowSize;
+                    var lastX = x[currentRow];
+                    ++currentRow;
+                    for (var i=1; i<=width; i++)
+                        lastX = x[currentRow] = (x0[currentRow] + a*(lastX+x[++currentRow]+x[++lastRow]+x[++nextRow])) * invC;
+                }
+                set_bnd(b, x);
+            }
+        }
+    }
+
+    function diffuse(b, x, x0, dt)
+    {
+        var a = 0;
+        lin_solve(b, x, x0, a, 1 + 4*a);
+    }
+
+    function lin_solve2(x, x0, y, y0, a, c)
+    {
+        if (a === 0 && c === 1) {
+            for (var j=1 ; j <= height; j++) {
+                var currentRow = j * rowSize;
+                ++currentRow;
+                for (var i = 0; i < width; i++) {
+                    x[currentRow] = x0[currentRow];
+                    y[currentRow] = y0[currentRow];
+                    ++currentRow;
+                }
+            }
+            set_bnd(1, x);
+            set_bnd(2, y);
+        } else {
+            var invC = 1/c;
+            for (var k=0 ; k<iterations; k++) {
+                for (var j=1 ; j <= height; j++) {
+                    var lastRow = (j - 1) * rowSize;
+                    var currentRow = j * rowSize;
+                    var nextRow = (j + 1) * rowSize;
+                    var lastX = x[currentRow];
+                    var lastY = y[currentRow];
+                    ++currentRow;
+                    for (var i = 1; i <= width; i++) {
+                        lastX = x[currentRow] = (x0[currentRow] + a * (lastX + x[currentRow] + x[lastRow] + x[nextRow])) * invC;
+                        lastY = y[currentRow] = (y0[currentRow] + a * (lastY + y[++currentRow] + y[++lastRow] + y[++nextRow])) * invC;
+                    }
+                }
+                set_bnd(1, x);
+                set_bnd(2, y);
+            }
+        }
+    }
+
+    function diffuse2(x, x0, y, y0, dt)
+    {
+        var a = 0;
+        lin_solve2(x, x0, y, y0, a, 1 + 4 * a);
+    }
+
+    function advect(b, d, d0, u, v, dt)
+    {
+        var Wdt0 = dt * width;
+        var Hdt0 = dt * height;
+        var Wp5 = width + 0.5;
+        var Hp5 = height + 0.5;
+        for (var j = 1; j<= height; j++) {
+            var pos = j * rowSize;
+            for (var i = 1; i <= width; i++) {
+                var x = i - Wdt0 * u[++pos];
+                var y = j - Hdt0 * v[pos];
+                if (x < 0.5)
+                    x = 0.5;
+                else if (x > Wp5)
+                    x = Wp5;
+                var i0 = x | 0;
+                var i1 = i0 + 1;
+                if (y < 0.5)
+                    y = 0.5;
+                else if (y > Hp5)
+                    y = Hp5;
+                var j0 = y | 0;
+                var j1 = j0 + 1;
+                var s1 = x - i0;
+                var s0 = 1 - s1;
+                var t1 = y - j0;
+                var t0 = 1 - t1;
+                var row1 = j0 * rowSize;
+                var row2 = j1 * rowSize;
+                d[pos] = s0 * (t0 * d0[i0 + row1] + t1 * d0[i0 + row2]) + s1 * (t0 * d0[i1 + row1] + t1 * d0[i1 + row2]);
+            }
+        }
+        set_bnd(b, d);
+    }
+
+    function project(u, v, p, div)
+    {
+        var h = -0.5 / Math.sqrt(width * height);
+        for (var j = 1 ; j <= height; j++ ) {
+            var row = j * rowSize;
+            var previousRow = (j - 1) * rowSize;
+            var prevValue = row - 1;
+            var currentRow = row;
+            var nextValue = row + 1;
+            var nextRow = (j + 1) * rowSize;
+            for (var i = 1; i <= width; i++ ) {
+                div[++currentRow] = h * (u[++nextValue] - u[++prevValue] + v[++nextRow] - v[++previousRow]);
+                p[currentRow] = 0;
+            }
+        }
+        set_bnd(0, div);
+        set_bnd(0, p);
+
+        lin_solve(0, p, div, 1, 4 );
+        var wScale = 0.5 * width;
+        var hScale = 0.5 * height;
+        for (var j = 1; j<= height; j++ ) {
+            var prevPos = j * rowSize - 1;
+            var currentPos = j * rowSize;
+            var nextPos = j * rowSize + 1;
+            var prevRow = (j - 1) * rowSize;
+            var currentRow = j * rowSize;
+            var nextRow = (j + 1) * rowSize;
+
+            for (var i = 1; i<= width; i++) {
+                u[++currentPos] -= wScale * (p[++nextPos] - p[++prevPos]);
+                v[currentPos]   -= hScale * (p[++nextRow] - p[++prevRow]);
+            }
+        }
+        set_bnd(1, u);
+        set_bnd(2, v);
+    }
+
+    function dens_step(x, x0, u, v, dt)
+    {
+        addFields(x, x0, dt);
+        diffuse(0, x0, x, dt );
+        advect(0, x, x0, u, v, dt );
+    }
+
+    function vel_step(u, v, u0, v0, dt)
+    {
+        addFields(u, u0, dt );
+        addFields(v, v0, dt );
+        var temp = u0; u0 = u; u = temp;
+        var temp = v0; v0 = v; v = temp;
+        diffuse2(u,u0,v,v0, dt);
+        project(u, v, u0, v0);
+        var temp = u0; u0 = u; u = temp;
+        var temp = v0; v0 = v; v = temp;
+        advect(1, u, u0, u0, v0, dt);
+        advect(2, v, v0, u0, v0, dt);
+        project(u, v, u0, v0 );
+    }
+    var uiCallback = function(d,u,v) {};
+
+    function Field(dens, u, v) {
+        // Just exposing the fields here rather than using accessors is a measurable win during display (maybe 5%)
+        // but makes the code ugly.
+        this.setDensity = function(x, y, d) {
+             dens[(x + 1) + (y + 1) * rowSize] = d;
+        }
+        this.getDensity = function(x, y) {
+             return dens[(x + 1) + (y + 1) * rowSize];
+        }
+        this.setVelocity = function(x, y, xv, yv) {
+             u[(x + 1) + (y + 1) * rowSize] = xv;
+             v[(x + 1) + (y + 1) * rowSize] = yv;
+        }
+        this.getXVelocity = function(x, y) {
+             return u[(x + 1) + (y + 1) * rowSize];
+        }
+        this.getYVelocity = function(x, y) {
+             return v[(x + 1) + (y + 1) * rowSize];
+        }
+        this.width = function() { return width; }
+        this.height = function() { return height; }
+    }
+    function queryUI(d, u, v)
+    {
+        for (var i = 0; i < size; i++)
+            u[i] = v[i] = d[i] = 0.0;
+        uiCallback(new Field(d, u, v));
+    }
+
+    this.update = function () {
+        queryUI(dens_prev, u_prev, v_prev);
+        vel_step(u, v, u_prev, v_prev, dt);
+        dens_step(dens, dens_prev, u, v, dt);
+        displayFunc(new Field(dens, u, v));
+    }
+    this.setDisplayFunction = function(func) {
+        displayFunc = func;
+    }
+
+    this.iterations = function() { return iterations; }
+    this.setIterations = function(iters) {
+        if (iters > 0 && iters <= 100)
+           iterations = iters;
+    }
+    this.setUICallback = function(callback) {
+        uiCallback = callback;
+    }
+    var iterations = 10;
+    var visc = 0.5;
+    var dt = 0.1;
+    var dens;
+    var dens_prev;
+    var u;
+    var u_prev;
+    var v;
+    var v_prev;
+    var width;
+    var height;
+    var rowSize;
+    var size;
+    var displayFunc;
+    function reset()
+    {
+        rowSize = width + 2;
+        size = (width+2)*(height+2);
+        dens = new Array(size);
+        dens_prev = new Array(size);
+        u = new Array(size);
+        u_prev = new Array(size);
+        v = new Array(size);
+        v_prev = new Array(size);
+        for (var i = 0; i < size; i++)
+            dens_prev[i] = u_prev[i] = v_prev[i] = dens[i] = u[i] = v[i] = 0;
+    }
+    this.reset = reset;
+    this.setResolution = function (hRes, wRes)
+    {
+        var res = wRes * hRes;
+        if (res > 0 && res < 1000000 && (wRes != width || hRes != height)) {
+            width = wRes;
+            height = hRes;
+            reset();
+            return true;
+        }
+        return false;
+    }
+    this.setResolution(64, 64);
+}
--- a/js/src/v8/regexp.js
+++ b/js/src/v8/regexp.js
@@ -28,31 +28,31 @@
 // Automatically generated on 2009-01-30. Manually updated on 2010-09-17.
 
 // This benchmark is generated by loading 50 of the most popular pages
 // on the web and logging all regexp operations performed.  Each
 // operation is given a weight that is calculated from an estimate of
 // the popularity of the pages where it occurs and the number of times
 // it is executed while loading each page.  Furthermore the literal
 // letters in the data are encoded using ROT13 in a way that does not
-// affect how the regexps match their input.  Finally the strings are 
+// affect how the regexps match their input.  Finally the strings are
 // scrambled to exercise the regexp engine on different input strings.
 
 
 var RegExp = new BenchmarkSuite('RegExp', 910985, [
   new Benchmark("RegExp", RegExpRun, RegExpSetup, RegExpTearDown)
 ]);
 
 var regExpBenchmark = null;
 
 function RegExpSetup() {
   regExpBenchmark = new RegExpBenchmark();
   RegExpRun(); // run once to get system initialized
 }
-  
+
 function RegExpRun() {
   regExpBenchmark.run();
 }
 
 function RegExpTearDown() {
   regExpBenchmark = null;
 }
 
@@ -1754,11 +1754,11 @@ function RegExpBenchmark() {
       runBlock6();
       runBlock7();
       runBlock8();
       runBlock9();
       runBlock10();
       runBlock11();
     }
   }
-  
+
   this.run = run;
 }
new file mode 100644
--- /dev/null
+++ b/js/src/v8/run-navier-stokes.js
@@ -0,0 +1,55 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+load('base.js');
+load('navier-stokes.js');
+
+var success = true;
+
+function PrintResult(name, result) {
+  print(name + ': ' + result);
+}
+
+
+function PrintError(name, error) {
+  PrintResult(name, error);
+  success = false;
+}
+
+
+function PrintScore(score) {
+  if (success) {
+    print('----');
+    print('Score (version ' + BenchmarkSuite.version + '): ' + score);
+  }
+}
+
+
+BenchmarkSuite.RunSuites({ NotifyResult: PrintResult,
+                           NotifyError: PrintError,
+                           NotifyScore: PrintScore });
--- a/js/src/v8/run.js
+++ b/js/src/v8/run.js
@@ -29,16 +29,17 @@
 load('base.js');
 load('richards.js');
 load('deltablue.js');
 load('crypto.js');
 load('raytrace.js');
 load('earley-boyer.js');
 load('regexp.js');
 load('splay.js');
+load('navier-stokes.js');
 
 var success = true;
 
 function PrintResult(name, result) {
   print(name + ': ' + result);
 }