aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@mozilla.com>2011-01-27 21:31:20 -0800
committerAlon Zakai <azakai@mozilla.com>2011-01-27 21:31:20 -0800
commit5958a6a754324de9eeff39fe1f21ba2b7042f833 (patch)
treeb9a5f9929c3cbe64f9b45ae7be4b6037f2b7b33d
parent8e51dd91884b48f9c59fed12e995ed9fdbdcd5f8 (diff)
reSign parallel to unSign to fix rare signing issues; CHECK_SIGNS option
-rw-r--r--src/jsifier.js12
-rw-r--r--src/preamble.js22
-rw-r--r--src/settings.js5
-rw-r--r--tests/runner.py12
4 files changed, 43 insertions, 8 deletions
diff --git a/src/jsifier.js b/src/jsifier.js
index c64c2ced..3f3c4161 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -752,9 +752,10 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria
return makeOne(0);
});
- function makeUnSign(value, type) {
+ function makeSignOp(value, type, op) {
if (type in Runtime.INT_TYPES) {
- return 'unSign(' + value + ', ' + type.substr(1) + ')';
+ var bits = parseInt(type.substr(1));
+ return op + 'Sign(' + value + ', ' + type.substr(1) + ')';
} else {
return value;
}
@@ -768,8 +769,11 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria
}
if (GUARD_SIGNS) {
if (op[0] == 'u' || (variant && variant[0] == 'u')) {
- ident1 = makeUnSign(ident1, type);
- ident2 = makeUnSign(ident2, type);
+ ident1 = makeSignOp(ident1, type, 'un');
+ ident2 = makeSignOp(ident2, type, 'un');
+ } else if (op[0] == 's' || (variant && variant[0] == 's')) {
+ ident1 = makeSignOp(ident1, type, 're');
+ ident2 = makeSignOp(ident2, type, 're');
}
}
var bits = null;
diff --git a/src/preamble.js b/src/preamble.js
index e375b90a..ade02496 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -349,7 +349,27 @@ function intArrayToString(array) {
// example, -1 in int32 would be a very large number as unsigned.
function unSign(value, bits) {
if (value >= 0) return value;
- return 2*Math.abs(1 << (bits-1)) + value;
+#if CHECK_SIGNS
+ print('WARNING: unSign needed, ' + [value, bits] + ' at ' + new Error().stack);
+#endif
+ return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts
+ : Math.pow(2, bits) + value;
+ // TODO: clean up previous line
+}
+
+// Converts a value we have as unsigned, into a signed value. For
+// example, 200 in a uint8 would be a negative number.
+function reSign(value, bits) {
+ if (value <= 0) return value;
+ var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32
+ : Math.pow(2, bits-1);
+ if (value >= half) {
+#if CHECK_SIGNS
+ print('WARNING: reSign needed, ' + [value, bits] + ' at ' + new Error().stack);
+#endif
+ value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts
+ }
+ return value;
}
// === Body ===
diff --git a/src/settings.js b/src/settings.js
index 1b0b2bce..c4335838 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -16,6 +16,11 @@ QUANTUM_SIZE = 4; // This is the size of an individual field in a structure. 1 w
GUARD_SIGNS = 1; // Whether we make sure to convert unsigned values to signed values.
// Decreases performance with additional runtime checks. Might not be
// needed in some kinds of code.
+CHECK_SIGNS = 0; // Runtime warning for signing issues that need correcting. Note:
+ // *requires* GUARD_SIGNS to work. It is recommended to use this in
+ // order to find if your code needs GUARD_SIGNS. If you can get your
+ // code to run without GUARD_SIGNS, it will run much faster
+
GUARD_LABELS = 0; // Whether we should throw if we encounter a bad __label__, i.e.,
// if code flow runs into a fault
GUARD_MEMORY = 1; // Whether we should check that each allocation to the stack does not
diff --git a/tests/runner.py b/tests/runner.py
index dd30f40c..9d7a53fa 100644
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -300,15 +300,21 @@ if 'benchmark' not in sys.argv:
def test_unsigned(self):
src = '''
#include <stdio.h>
+ const signed char cvals[2] = { -1, -2 }; // compiler can store this is a string, so -1 becomes \FF, and needs re-signing
int main()
{
int varey = 100;
unsigned int MAXEY = -1, MAXEY2 = -77;
printf("*%u,%d,%u*\\n", MAXEY, varey >= MAXEY, MAXEY2); // 100 >= -1? not in unsigned!
+
+ int y = cvals[0];
+ printf("*%d,%d,%d,%d*\\n", cvals[0], cvals[0] < 0, y, y < 0);
+ y = cvals[1];
+ printf("*%d,%d,%d,%d*\\n", cvals[1], cvals[1] < 0, y, y < 0);
return 0;
}
'''
- self.do_test(src, '*4294967295,0,4294967219*')
+ self.do_test(src, '*4294967295,0,4294967219*\n*-1,1,-1,1*\n*-2,1,-2,1*')
def test_bitfields(self):
global SAFE_HEAP; SAFE_HEAP = 0 # bitfields do loads on invalid areas, by design
@@ -1327,11 +1333,11 @@ if 'benchmark' not in sys.argv:
def post(filename):
src = open(filename, 'r').read().replace(
'// {{PRE_RUN_ADDITIONS}}',
- '''this._STDIO.prepare('somefile.binary', [100, 200, 50, 25, 10, 77, 123]);'''
+ '''this._STDIO.prepare('somefile.binary', [100, 200, 50, 25, 10, 77, 123]);''' # 200 becomes -56, since signed chars are used in memory
)
open(filename, 'w').write(src)
src = open(path_from_root('tests', 'files.cpp'), 'r').read()
- self.do_test(src, 'size: 7\ndata: 100,200,50,25,10,77,123\ntexto\ntexte\n5 : 10,30,20,11,88\n', post_build=post)
+ self.do_test(src, 'size: 7\ndata: 100,-56,50,25,10,77,123\ntexto\ntexte\n5 : 10,30,20,11,88\n', post_build=post)
### 'Big' tests