[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