diff options
author | Michaƫl Zasso <targos@protonmail.com> | 2018-01-24 20:16:06 +0100 |
---|---|---|
committer | Myles Borins <mylesborins@google.com> | 2018-01-24 15:02:20 -0800 |
commit | 4c4af643e5042d615a60c6bbc05aee9d81b903e5 (patch) | |
tree | 3fb0a97988fe4439ae3ae06f26915d1dcf8cab92 /deps/v8/tools/bigint-tester.py | |
parent | fa9f31a4fda5a3782c652e56e394465805ebb50f (diff) | |
download | android-node-v8-4c4af643e5042d615a60c6bbc05aee9d81b903e5.tar.gz android-node-v8-4c4af643e5042d615a60c6bbc05aee9d81b903e5.tar.bz2 android-node-v8-4c4af643e5042d615a60c6bbc05aee9d81b903e5.zip |
deps: update V8 to 6.4.388.40
PR-URL: https://github.com/nodejs/node/pull/17489
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Diffstat (limited to 'deps/v8/tools/bigint-tester.py')
-rwxr-xr-x | deps/v8/tools/bigint-tester.py | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/deps/v8/tools/bigint-tester.py b/deps/v8/tools/bigint-tester.py new file mode 100755 index 0000000000..0452a0d1db --- /dev/null +++ b/deps/v8/tools/bigint-tester.py @@ -0,0 +1,347 @@ +#!/usr/bin/python +# Copyright 2017 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import argparse +import math +import multiprocessing +import os +import random +import subprocess +import sys +import tempfile + +# Configuration. +kChars = "0123456789abcdefghijklmnopqrstuvwxyz" +kBase = 16 +kLineLength = 71 # A bit less than 80. +kNumInputsGenerate = 20 +kNumInputsStress = 1000 + +# Internally used sentinels. +kNo = 0 +kYes = 1 +kRandom = 2 + +TEST_HEADER = """\ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Generated by %s. + +// Flags: --harmony-bigint +""" % sys.argv[0] + +TEST_BODY = """ +var error_count = 0; +for (var i = 0; i < data.length; i++) { + var d = data[i]; +%s +} +if (error_count !== 0) { + print("Finished with " + error_count + " errors.") + quit(1); +}""" + +def GenRandom(length, negative=kRandom): + if length == 0: return "0" + s = [] + if negative == kYes or (negative == kRandom and (random.randint(0, 1) == 0)): + s.append("-") # 50% chance of negative. + s.append(kChars[random.randint(1, kBase - 1)]) # No leading zero. + for i in range(1, length): + s.append(kChars[random.randint(0, kBase - 1)]) + return "".join(s) + +def Format(x, base): + original = x + negative = False + if x == 0: return "0" + if x < 0: + negative = True + x = -x + s = "" + while x > 0: + s = kChars[x % base] + s + x = x / base + if negative: + s = "-" + s + assert int(s, base) == original + return s + +class TestGenerator(object): + # Subclasses must implement these. + # Returns a JSON snippet defining inputs and expected output for one test. + def EmitOne(self): raise NotImplementedError + # Returns a snippet of JavaScript that will operate on a variable "d" + # whose content is defined by the result of a call to "EmitOne". + def EmitTestCore(self): raise NotImplementedError + + def EmitHeader(self): + return TEST_HEADER + + def EmitData(self, count): + s = [] + for i in range(count): + s.append(self.EmitOne()) + return "var data = [" + ", ".join(s) + "];" + + def EmitTestBody(self): + return TEST_BODY % self.EmitTestCore() + + def PrintTest(self, count): + print(self.EmitHeader()) + print(self.EmitData(count)) + print(self.EmitTestBody()) + + def RunTest(self, count, binary): + try: + fd, path = tempfile.mkstemp(suffix=".js", prefix="bigint-test-") + with open(path, "w") as f: + f.write(self.EmitData(count)) + f.write(self.EmitTestBody()) + return subprocess.call("%s --harmony-bigint %s" % (binary, path), + shell=True) + finally: + os.close(fd) + os.remove(path) + +class UnaryOp(TestGenerator): + # Subclasses must implement these two. + def GetOpString(self): raise NotImplementedError + def GenerateResult(self, x): raise NotImplementedError + + # Subclasses may override this: + def GenerateInput(self): + return GenRandom(random.randint(0, kLineLength)) + + # Subclasses should not override anything below. + def EmitOne(self): + x_str = self.GenerateInput() + x_num = int(x_str, kBase) + result_num = self.GenerateResult(x_num) + result_str = Format(result_num, kBase) + return "{\n a: \"%s\",\n r: \"%s\"\n}" % (x_str, result_str) + + def EmitTestCore(self): + return """\ + var a = BigInt.parseInt(d.a, %(base)d); + var r = %(op)sa; + if (d.r !== r.toString(%(base)d)) { + print("Input: " + a.toString(%(base)d)); + print("Result: " + r.toString(%(base)d)); + print("Expected: " + d.r); + error_count++; + }""" % {"op": self.GetOpString(), "base": kBase} + +class BinaryOp(TestGenerator): + # Subclasses must implement these two. + def GetOpString(self): raise NotImplementedError + def GenerateResult(self, left, right): raise NotImplementedError + + # Subclasses may override these: + def GenerateInputLengths(self): + return random.randint(0, kLineLength), random.randint(0, kLineLength) + + def GenerateInputs(self): + left_length, right_length = self.GenerateInputLengths() + return GenRandom(left_length), GenRandom(right_length) + + # Subclasses should not override anything below. + def EmitOne(self): + left_str, right_str = self.GenerateInputs() + left_num = int(left_str, kBase) + right_num = int(right_str, kBase) + result_num = self.GenerateResult(left_num, right_num) + result_str = Format(result_num, kBase) + return ("{\n a: \"%s\",\n b: \"%s\",\n r: \"%s\"\n}" % + (left_str, right_str, result_str)) + + def EmitTestCore(self): + return """\ + var a = BigInt.parseInt(d.a, %(base)d); + var b = BigInt.parseInt(d.b, %(base)d); + var r = a %(op)s b; + if (d.r !== r.toString(%(base)d)) { + print("Input A: " + a.toString(%(base)d)); + print("Input B: " + b.toString(%(base)d)); + print("Result: " + r.toString(%(base)d)); + print("Expected: " + d.r); + print("Op: %(op)s"); + error_count++; + }""" % {"op": self.GetOpString(), "base": kBase} + +class Neg(UnaryOp): + def GetOpString(self): return "-" + def GenerateResult(self, x): return -x + +class BitNot(UnaryOp): + def GetOpString(self): return "~" + def GenerateResult(self, x): return ~x + +class Inc(UnaryOp): + def GetOpString(self): return "++" + def GenerateResult(self, x): return x + 1 + +class Dec(UnaryOp): + def GetOpString(self): return "--" + def GenerateResult(self, x): return x - 1 + +class Add(BinaryOp): + def GetOpString(self): return "+" + def GenerateResult(self, a, b): return a + b + +class Sub(BinaryOp): + def GetOpString(self): return "-" + def GenerateResult(self, a, b): return a - b + +class Mul(BinaryOp): + def GetOpString(self): return "*" + def GenerateResult(self, a, b): return a * b + def GenerateInputLengths(self): + left_length = random.randint(1, kLineLength) + return left_length, kLineLength - left_length + +class Div(BinaryOp): + def GetOpString(self): return "/" + def GenerateResult(self, a, b): + result = abs(a) / abs(b) + if (a < 0) != (b < 0): result = -result + return result + def GenerateInputLengths(self): + # Let the left side be longer than the right side with high probability, + # because that case is more interesting. + min_left = kLineLength * 6 / 10 + max_right = kLineLength * 7 / 10 + return random.randint(min_left, kLineLength), random.randint(1, max_right) + +class Mod(Div): # Sharing GenerateInputLengths. + def GetOpString(self): return "%" + def GenerateResult(self, a, b): + result = a % b + if a < 0 and result > 0: + result -= abs(b) + if a > 0 and result < 0: + result += abs(b) + return result + +class Shl(BinaryOp): + def GetOpString(self): return "<<" + def GenerateInputsInternal(self, small_shift_positive): + left_length = random.randint(0, kLineLength - 1) + left = GenRandom(left_length) + small_shift = random.randint(0, 1) == 0 + if small_shift: + right_length = 1 + int(math.log((kLineLength - left_length), kBase)) + neg = kNo if small_shift_positive else kYes + else: + right_length = random.randint(0, 3) + neg = kYes if small_shift_positive else kNo + right = GenRandom(right_length, negative=neg) + return left, right + + def GenerateInputs(self): return self.GenerateInputsInternal(True) + def GenerateResult(self, a, b): + if b < 0: return a >> -b + return a << b + +class Sar(Shl): # Sharing GenerateInputsInternal. + def GetOpString(self): return ">>" + def GenerateInputs(self): + return self.GenerateInputsInternal(False) + def GenerateResult(self, a, b): + if b < 0: return a << -b + return a >> b + +class BitAnd(BinaryOp): + def GetOpString(self): return "&" + def GenerateResult(self, a, b): return a & b + +class BitOr(BinaryOp): + def GetOpString(self): return "|" + def GenerateResult(self, a, b): return a | b + +class BitXor(BinaryOp): + def GetOpString(self): return "^" + def GenerateResult(self, a, b): return a ^ b + +OPS = { + "add": Add, + "sub": Sub, + "mul": Mul, + "div": Div, + "mod": Mod, + "inc": Inc, + "dec": Dec, + "neg": Neg, + "not": BitNot, + "shl": Shl, + "sar": Sar, + "and": BitAnd, + "or": BitOr, + "xor": BitXor +} + +OPS_NAMES = ", ".join(sorted(OPS.keys())) + +def RunOne(op, num_inputs, binary): + return OPS[op]().RunTest(num_inputs, binary) +def WrapRunOne(args): + return RunOne(*args) +def RunAll(args): + for op in args.op: + for r in xrange(args.runs): + yield (op, args.num_inputs, args.binary) + +def Main(): + parser = argparse.ArgumentParser( + description="Helper for generating or running BigInt tests.") + parser.add_argument( + "action", help="Action to perform: 'generate' or 'stress'") + parser.add_argument( + "op", nargs="+", + help="Operation(s) to test, one or more of: %s. In 'stress' mode, " + "special op 'all' tests all ops." % OPS_NAMES) + parser.add_argument( + "-n", "--num-inputs", type=int, default=-1, + help="Number of input/output sets in each generated test. Defaults to " + "%d for 'generate' and '%d' for 'stress' mode." % + (kNumInputsGenerate, kNumInputsStress)) + + stressopts = parser.add_argument_group("'stress' mode arguments") + stressopts.add_argument( + "-r", "--runs", type=int, default=1000, + help="Number of tests (with NUM_INPUTS each) to generate and run. " + "Default: %(default)s.") + stressopts.add_argument( + "-b", "--binary", default="out/x64.debug/d8", + help="The 'd8' binary to use. Default: %(default)s.") + args = parser.parse_args() + + for op in args.op: + if op not in OPS.keys() and op != "all": + print("Invalid op '%s'. See --help." % op) + return 1 + + if len(args.op) == 1 and args.op[0] == "all": + args.op = OPS.keys() + + if args.action == "generate": + if args.num_inputs < 0: args.num_inputs = kNumInputsGenerate + for op in args.op: + OPS[op]().PrintTest(args.num_inputs) + elif args.action == "stress": + if args.num_inputs < 0: args.num_inputs = kNumInputsStress + result = 0 + pool = multiprocessing.Pool(multiprocessing.cpu_count()) + for r in pool.imap_unordered(WrapRunOne, RunAll(args)): + result = result or r + return result + else: + print("Invalid action '%s'. See --help." % args.action) + return 1 + +if __name__ == "__main__": + sys.exit(Main()) |