[pypy-commit] lang-smalltalk default: merge

eseckler noreply at buildbot.pypy.org
Thu Apr 3 11:31:44 CEST 2014


Author: Eric Seckler <eric.seckler at student.hpi.uni-potsdam.de>
Branch: 
Changeset: r750:bead6833aef1
Date: 2014-01-14 14:28 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/bead6833aef1/

Log:	merge

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -1,8 +1,12 @@
 syntax: glob
 *.py[co]
 *~
-pypy-c-jit-62116-b027d4428675-linux
+pypy-c-jit-*
 images/Squeak*
+images/resources*
+*package-cache/
+Squeak*
+*TAGS
 targetimageloadingsmalltalk-*c
 images/package-cache
 versions
diff --git a/spyvm/constants.py b/spyvm/constants.py
--- a/spyvm/constants.py
+++ b/spyvm/constants.py
@@ -146,6 +146,8 @@
 TAGGED_MAXINT = 2 ** (LONG_BIT - 2) - 1
 TAGGED_MININT = -2 ** (LONG_BIT - 2)
 
+TAGGED_MASK = int(2 ** (LONG_BIT - 1) - 1)
+
 
 # Entries into SO_SPECIAL_SELECTORS_ARRAY:
 #(#+ 1 #- 1 #< 1 #> 1 #<= 1 #>= 1 #= 1 #~= 1 #* 1 #/ 1 #\\ 1 #@ 1 #bitShift: 1 #// 1 #bitAnd: 1 #bitOr: 1 #at: 1 #at:put: 2 #size 0 #next 0 #nextPut: 1 #atEnd 0 #== 1 #class 0 #blockCopy: 1 #value 0 #value: 1 #do: 1 #new 0 #new: 1 #x 0 #y 0)
diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -126,7 +126,9 @@
 
 
 class Interpreter(object):
-
+    _immutable_fields_ = ["space", "image", "image_name",
+                          "max_stack_depth", "interrupt_counter_size",
+                          "startup_time"]
     _w_last_active_context = None
     cnt = 0
     _last_indent = ""
@@ -140,9 +142,11 @@
 
     def __init__(self, space, image=None, image_name="", trace=False,
                 max_stack_depth=constants.MAX_LOOP_DEPTH):
+        import time
         self.space = space
         self.image = image
         self.image_name = image_name
+        self.startup_time = time.time()
         self.max_stack_depth = max_stack_depth
         self.remaining_stack_depth = max_stack_depth
         self._loop = False
@@ -325,13 +329,12 @@
 
     def check_for_interrupts(self, s_frame):
         # parallel to Interpreter>>#checkForInterrupts
-        import time, math
 
         # Profiling is skipped
         # We don't adjust the check counter size
 
         # use the same time value as the primitive MILLISECOND_CLOCK
-        now = int(math.fmod(time.time()*1000, constants.TAGGED_MAXINT/2))
+        now = self.time_now()
 
         # XXX the low space semaphore may be signaled here
         # Process inputs
@@ -345,6 +348,11 @@
         # We do not support external semaphores.
             # In cog, the method to add such a semaphore is only called in GC.
 
+    def time_now(self):
+        import time
+        from rpython.rlib.rarithmetic import intmask
+        return intmask(int((time.time() - self.startup_time) * 1000) & constants.TAGGED_MASK)
+
     def padding(self, symbol=' '):
         return symbol * (self.max_stack_depth - self.remaining_stack_depth)
 
diff --git a/spyvm/plugins/fileplugin.py b/spyvm/plugins/fileplugin.py
--- a/spyvm/plugins/fileplugin.py
+++ b/spyvm/plugins/fileplugin.py
@@ -40,7 +40,10 @@
         file_path = os.path.join(full_path, py_name)
     except OSError:
         raise PrimitiveFailedError
-    file_info = os.stat(file_path)
+    try:
+        file_info = os.stat(file_path)
+    except OSError:
+        raise PrimitiveFailedError
 
     w_name = space.wrap_string(py_name)
     w_creationTime = smalltalk_timestamp(space, file_info.st_ctime)
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -1019,8 +1019,7 @@
 
 @expose_primitive(MILLISECOND_CLOCK, unwrap_spec=[object])
 def func(interp, s_frame, w_arg):
-    import time, math
-    return interp.space.wrap_int(int(math.fmod(time.time()*1000, constants.TAGGED_MAXINT/2)))
+    return interp.space.wrap_int(interp.time_now())
 
 @expose_primitive(SIGNAL_AT_MILLISECONDS, unwrap_spec=[object, object, int])
 def func(interp, s_frame, w_delay, w_semaphore, timestamp):
diff --git a/spyvm/test/jittest/__init__.py b/spyvm/test/jittest/__init__.py
new file mode 100644
diff --git a/spyvm/test/jittest/base.py b/spyvm/test/jittest/base.py
new file mode 100644
--- /dev/null
+++ b/spyvm/test/jittest/base.py
@@ -0,0 +1,121 @@
+import subprocess
+import os
+
+# TODO:
+from pypy.tool.jitlogparser.parser import SimpleParser, Op
+from pypy.tool.jitlogparser.storage import LoopStorage
+
+from rpython.jit.metainterp.resoperation import opname
+from rpython.jit.tool import oparser
+from rpython.tool import logparser
+
+
+BasePath = os.path.abspath(
+    os.path.join(
+        os.path.join(os.path.dirname(__file__), os.path.pardir),
+        os.path.pardir,
+        os.path.pardir
+    )
+)
+BenchmarkImage = os.path.join(os.path.dirname(__file__), "benchmark.image")
+
+class BaseJITTest(object):
+    def run(self, spy, tmpdir, code):
+        proc = subprocess.Popen(
+            [str(spy), "-r", code.replace("\n", "\r\n"), BenchmarkImage],
+            cwd=str(tmpdir),
+            env={"PYPYLOG": "jit-log-opt:%s" % tmpdir.join("x.pypylog")}
+        )
+        proc.wait()
+        data = logparser.parse_log_file(str(tmpdir.join("x.pypylog")), verbose=False)
+        data = logparser.extract_category(data, "jit-log-opt-")
+
+        storage = LoopStorage()
+        traces = [SimpleParser.parse_from_input(t) for t in data]
+        main_loops = storage.reconnect_loops(traces)
+        traces_w = []
+        for trace in traces:
+            if trace in main_loops:
+                traces_w.append(Trace(trace))
+            else:
+                traces_w[len(traces_w) - 1].addbridge(trace)
+        return traces_w
+
+    def assert_matches(self, trace, expected):
+        expected_lines = [
+            line.strip()
+            for line in expected.splitlines()
+            if line and not line.isspace()
+        ]
+        parser = Parser(None, None, {}, "lltype", None, invent_fail_descr=None, nonstrict=True)
+        expected_ops = [parser.parse_next_op(l) for l in expected_lines]
+        aliases = {}
+        assert len(trace) == len(expected_ops)
+        for op, expected in zip(trace, expected_ops):
+            self._assert_ops_equal(aliases, op, expected)
+
+    def _assert_ops_equal(self, aliases, op, expected):
+        assert op.name == expected.name
+        assert len(op.args) == len(expected.args)
+        for arg, expected_arg in zip(op.args, expected.args):
+            if arg in aliases:
+                arg = aliases[arg]
+            elif arg != expected_arg and expected_arg not in aliases.viewvalues():
+                aliases[arg] = arg = expected_arg
+            assert arg == expected_arg
+
+
+class Parser(oparser.OpParser):
+    def get_descr(self, poss_descr, allow_invent):
+        if poss_descr.startswith(("TargetToken", "<Guard")):
+            return poss_descr
+        return super(Parser, self).get_descr(poss_descr, allow_invent)
+
+    def getvar(self, arg):
+        return arg
+
+    def create_op(self, opnum, args, res, descr):
+        return Op(opname[opnum].lower(), args, res, descr)
+
+
+class Trace(object):
+    def __init__(self, trace):
+        self._trace = trace
+        self._bridges = []
+        self._bridgeops = None
+        self._loop = None
+
+    def addbridge(self, trace):
+        self._bridges.append(trace)
+
+    @property
+    def bridges(self):
+        if self._bridgeops:
+            return self._bridgeops
+        else:
+            self._bridgeops = []
+            for bridge in self._bridges:
+                self._bridgeops.append([op for op in bridge.operations if not op.name.startswith("debug_")])
+            return self._bridgeops
+
+    @property
+    def loop(self):
+        if self._loop:
+            return self._loop
+        else:
+            self._loop = self._parse_loop_from(self._trace)
+            return self._loop
+
+    def _parse_loop_from(self, trace, label_seen=None):
+        _loop = []
+        for idx, op in enumerate(self._trace.operations):
+            if label_seen and not op.name.startswith("debug_"):
+                _loop.append(op)
+            if op.name == "label":
+                if label_seen is None: # first label
+                    label_seen = False
+                else:
+                    label_seen = True # second label
+        if len(_loop) == 0:
+            raise ValueError("Loop body couldn't be found")
+        return _loop
diff --git a/spyvm/test/jittest/benchmark.image b/spyvm/test/jittest/benchmark.image
new file mode 100644
index 0000000000000000000000000000000000000000..848cffbe175dbf07a5d4bdc4f958ce92779dd171
GIT binary patch

[cut]

diff --git a/spyvm/test/jittest/conftest.py b/spyvm/test/jittest/conftest.py
new file mode 100644
--- /dev/null
+++ b/spyvm/test/jittest/conftest.py
@@ -0,0 +1,15 @@
+import py
+
+
+def pytest_addoption(parser):
+    group = parser.getgroup("SPy JIT tests")
+    group.addoption(
+        "--spy",
+        dest="spy",
+        default=None,
+        help="Path to a compiled SPy binary"
+    )
+
+
+def pytest_funcarg__spy(request):
+    return str(py.path.local(request.config.getvalueorskip("spy")))
diff --git a/spyvm/test/jittest/test_basic.py b/spyvm/test/jittest/test_basic.py
new file mode 100644
--- /dev/null
+++ b/spyvm/test/jittest/test_basic.py
@@ -0,0 +1,83 @@
+import py
+
+from .base import BaseJITTest
+
+
+class TestBasic(BaseJITTest):
+    def test_while_loop(self, spy, tmpdir):
+        traces = self.run(spy, tmpdir, """
+        0 to: 1000000000 do: [:t|nil].
+        """)
+        self.assert_matches(traces[0].loop, """
+        guard_not_invalidated(descr=<Guard0xa15ec7c>)
+        i60 = int_le(i49, 10000)
+        guard_true(i60, descr=<Guard0xa15ec40>)
+        i61 = int_add(i49, 1)
+        i62 = int_sub(i61, -1073741824)
+        i63 = uint_lt(i62, -2147483648)
+        guard_true(i63, descr=<Guard0xa15ec04>)
+        i64 = int_sub(i57, 1)
+        setfield_gc(ConstPtr(ptr54), i64, descr=<FieldS spyvm.interpreter.Interpreter.inst_interrupt_check_counter 16>)
+        i65 = int_le(i64, 0)
+        guard_false(i65, descr=<Guard0xa15ebc8>)
+        jump(p0, p3, i61, p12, p14, p16, p18, p20, p22, p24, p26, p28, p30, p32, p34, p36, p38, i64, descr=TargetToken(169145008))
+        """)
+        self.assert_matches(traces[0].bridges[0], """
+        f18 = call(ConstClass(ll_time.ll_time_time), descr=<Callf 8 EF=4>)
+        setfield_gc(ConstPtr(ptr19), 10000, descr=<FieldS spyvm.interpreter.Interpreter.inst_interrupt_check_counter 24>)
+        guard_no_exception(descr=<Guard0x9732d30>)
+        f22 = float_sub(f18, 1387380038.806162)
+        f24 = float_mul(f22, 1000.000000)
+        i25 = cast_float_to_int(f24)
+        i27 = int_and(i25, 2147483647)
+        i28 = getfield_gc(ConstPtr(ptr19), descr=<FieldS spyvm.interpreter.Interpreter.inst_next_wakeup_tick 36>)
+        i29 = int_is_zero(i28)
+        guard_true(i29, descr=<Guard0x9761ad8>)
+        label(p0, p1, i16, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, descr=TargetToken(158475216))
+        guard_class(p0, ConstClass(MethodContextShadow), descr=<Guard0x9761a9c>)
+        p31 = getfield_gc(p0, descr=<FieldP spyvm.shadow.MethodContextShadow.inst__w_method 44>)
+        guard_value(p31, ConstPtr(ptr32), descr=<Guard0x9761a60>)
+        guard_not_invalidated(descr=<Guard0x9761a24>)
+        i34 = int_le(i16, 1000000000)
+        guard_true(i34, descr=<Guard0x97619e8>)
+        i36 = int_add(i16, 1)
+        i38 = int_sub(i36, -1073741824)
+        i40 = uint_lt(i38, -2147483648)
+        guard_true(i40, descr=<Guard0x97619ac>)
+        setfield_gc(ConstPtr(ptr19), 9999, descr=<FieldS spyvm.interpreter.Interpreter.inst_interrupt_check_counter 24>)
+        jump(p0, p1, i36, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, 9999, descr=TargetToken(158474976))
+        """)
+
+    def test_constant_string(self, spy, tmpdir):
+        traces = self.run(spy, tmpdir, """
+        | i |
+        i := 0.
+        [i <= 10000] whileTrue: [ i := i + 'a' size].
+        ^ i
+        """)
+        self.assert_matches(traces[0].loop, """
+        label(p0, p3, i58, p12, p14, p16, p18, p20, p22, p24, p26, p28, p30, p32, p34, p36, p38, i65, descr=TargetToken(153187472))
+        debug_merge_point(0, 0, '2: [0x10]pushTemporaryVariableBytecode (codeTest1387373494)')
+        guard_not_invalidated(descr=<Guard0x92520c4>)
+        debug_merge_point(0, 0, '3: [0x21]pushLiteralConstantBytecode (codeTest1387373494)')
+        debug_merge_point(0, 0, '4: [0xb4]bytecodePrimLessOrEqual (codeTest1387373494)')
+        i68 = int_le(i58, 10000)
+        guard_true(i68, descr=<Guard0x9252088>)
+        debug_merge_point(0, 0, '5: [0x9e]shortConditionalJump (codeTest1387373494)')
+        debug_merge_point(0, 0, '6: [0x10]pushTemporaryVariableBytecode (codeTest1387373494)')
+        debug_merge_point(0, 0, '7: [0x20]pushLiteralConstantBytecode (codeTest1387373494)')
+        debug_merge_point(0, 0, '8: [0xc2]bytecodePrimSize (codeTest1387373494)')
+        debug_merge_point(0, 0, '9: [0xb0]bytecodePrimAdd (codeTest1387373494)')
+        i69 = int_add(i58, 1)
+        i70 = int_sub(i69, -1073741824)
+        i71 = uint_lt(i70, -2147483648)
+        guard_true(i71, descr=<Guard0x925204c>)
+        debug_merge_point(0, 0, '10: [0x68]storeAndPopTemporaryVariableBytecode (codeTest1387373494)')
+        debug_merge_point(0, 0, '11: [0xa3]longUnconditionalJump (codeTest1387373494)')
+        i72 = int_sub(i65, 1)
+        setfield_gc(ConstPtr(ptr55), i72, descr=<FieldS spyvm.interpreter.Interpreter.inst_interrupt_check_counter 16>)
+        i73 = int_le(i72, 0)
+        guard_false(i73, descr=<Guard0x9252010>)
+        debug_merge_point(0, 0, '2: [0x10]pushTemporaryVariableBytecode (codeTest1387373494)')
+        jump(p0, p3, i69, p12, p14, p16, p18, p20, p22, p24, p26, p28, p30, p32, p34, p36, p38, i72, descr=TargetToken(153187472))
+        """)
diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py
--- a/targetimageloadingsmalltalk.py
+++ b/targetimageloadingsmalltalk.py
@@ -59,6 +59,42 @@
     except error.Exit, e:
         print e.msg
 
+def _run_code(interp, code, as_benchmark=False):
+    import time
+    selector = "codeTest%d" % int(time.time())
+    try:
+        w_result = interp.perform(
+            interp.space.w_SmallInteger,
+            "compile:classified:notifying:",
+            space.wrap_string("%s\r\n%s" % (selector, code)),
+            space.wrap_string("spy-run-code"),
+            space.w_nil
+        )
+    except interpreter.ReturnFromTopLevel, e:
+        print e.object
+        return 1
+    except error.Exit, e:
+        print e.msg
+        return 1
+
+    if not as_benchmark:
+        try:
+            w_result = interp.perform(space.wrap_int(0), selector)
+        except interpreter.ReturnFromTopLevel, e:
+            print e.object
+            return 1
+        except error.Exit, e:
+            print e.msg
+            return 1
+        if w_result:
+            if isinstance(w_result, model.W_BytesObject):
+                print w_result.as_string().replace('\r', '\n')
+            else:
+                print w_result.as_repr_string().replace('\r', '\n')
+        return 0
+    else:
+        return _run_benchmark(interp, 0, selector, "")
+
 
 space = objspace.ObjSpace()
 
@@ -85,6 +121,8 @@
           -m|--method [benchmark on smallint]
           -a|--arg [string argument to #method]
           --stm
+          -r|--run [code string]
+          -b|--benchmark [code string]
           [image path, default: Squeak.image]
     """ % argv[0]
 
@@ -102,6 +140,8 @@
     trace = False
     use_stm = False
     stringarg = ""
+    code = None
+    as_benchmark = False
 
     while idx < len(argv):
         arg = argv[idx]
@@ -129,6 +169,16 @@
             idx += 1
         elif arg in ["--stm"]:
             use_stm = True
+        elif arg in ["-r", "--run"]:
+            _arg_missing(argv, idx, arg)
+            code = argv[idx + 1]
+            as_benchmark = False
+            idx += 1
+        elif arg in ["-b", "--benchmark"]:
+            _arg_missing(argv, idx, arg)
+            code = argv[idx + 1]
+            as_benchmark = True
+            idx += 1
         elif path is None:
             path = argv[idx]
         else:
@@ -157,6 +207,8 @@
     if benchmark is not None:
         print "Running Benchmark"
         return _run_benchmark(interp, number, benchmark, stringarg, use_stm)
+    elif code is not None:
+        return _run_code(interp, code, as_benchmark=as_benchmark)
     else:
         print "Running Image"
         _run_image(interp)


More information about the pypy-commit mailing list