Author: Lars Wassermann <lars.wasserm...@gmail.com> Branch: Changeset: r154:9e0d98ab4de6 Date: 2013-03-08 17:12 +0100 http://bitbucket.org/pypy/lang-smalltalk/changeset/9e0d98ab4de6/
Log: merged diff --git a/images/mini.image b/images/mini.image index ef63740cadf1c61bd59bdf34a7ff21a801cc727d..4e0739b0aa769798ae904fee0eff0b0eac8c8368 GIT binary patch [cut] diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -70,6 +70,9 @@ s_new_context.mark_returned() s_new_context = s_sender s_new_context.push(nlr.value) + except ProcessSwitch, p: + self.remaining_stack_depth = self.max_stack_depth + s_new_context = p.s_new_context def c_loop(self, s_context): # padding = ' ' * (self.max_stack_depth - self.remaining_stack_depth) @@ -146,11 +149,17 @@ class StackOverflow(Exception): def __init__(self, s_top_context): self.s_context = s_top_context + class Return(Exception): def __init__(self, object, s_context): self.value = object self.s_target_context = s_context +class ProcessSwitch(Exception): + def __init__(self, s_context): + self.s_new_context = s_context + + def make_call_primitive_bytecode(primitive, selector, argcount): def callPrimitive(self, interp, current_bytecode): # WARNING: this is used for bytecodes for which it is safe to diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -1,3 +1,4 @@ +import os import inspect import math import operator @@ -753,10 +754,40 @@ DIRECTORY_LOOKUP = 162 DIRECTORY_DELTE = 163 +@expose_primitive(FILE_CLOSE, unwrap_spec=[object, int]) +def func(interp, s_frame, w_rcvr, fd): + try: + os.close(fd) + except OSError: + raise PrimitiveFailedError() + return w_rcvr + +@expose_primitive(FILE_OPEN, unwrap_spec=[object, str, object]) +def func(interp, s_frame, w_rcvr, filename, w_writeable_flag): + if w_writeable_flag is interp.space.w_true: + mode = os.O_RDWR | os.O_CREAT | os.O_TRUNC + else: + mode = os.O_RDONLY + try: + fd = os.open(filename, mode, 0666) + except OSError: + raise PrimitiveFailedError() + return interp.space.wrap_int(fd) + +@expose_primitive(FILE_WRITE, unwrap_spec=[object, int, str, int, int]) +def func(interp, s_frame, w_rcvr, fd, src, start, count): + start = start - 1 + end = start + count + if end < 0 or start < 0: + raise PrimitiveFailedError() + try: + os.write(fd, src[start:end]) + except OSError: + raise PrimitiveFailedError() + return w_rcvr @expose_primitive(DIRECTORY_DELIMITOR, unwrap_spec=[object]) def func(interp, s_frame, _): - import os.path return interp.space.wrap_char(os.path.sep) diff --git a/spyvm/test/test_miniimage.py b/spyvm/test/test_miniimage.py --- a/spyvm/test/test_miniimage.py +++ b/spyvm/test/test_miniimage.py @@ -47,9 +47,9 @@ def test_read_header(): reader = open_miniimage(space) reader.read_header() - assert reader.endofmemory == 0x93174 - assert reader.oldbaseaddress == 0x6649000 - assert reader.specialobjectspointer == 0x6668380 + assert reader.endofmemory == 655196 + assert reader.oldbaseaddress == -1220960256 + assert reader.specialobjectspointer == -1220832384 def test_read_all_header(): reader = open_miniimage(space) diff --git a/spyvm/test/test_primitives.py b/spyvm/test/test_primitives.py --- a/spyvm/test/test_primitives.py +++ b/spyvm/test/test_primitives.py @@ -1,4 +1,5 @@ import py +import os import math from spyvm.primitives import prim_table, PrimitiveFailedError from spyvm import model, shadow, interpreter @@ -32,7 +33,9 @@ if isinstance(x, str): return space.wrap_string(x) if isinstance(x, list): return space.wrap_list(x) raise NotImplementedError - + +IMAGENAME = "anImage.image" + def mock(stack, context = None): mapped_stack = [wrap(x) for x in stack] if context is None: @@ -41,7 +44,7 @@ frame = context for i in range(len(stack)): frame.as_context_get_shadow(space).push(stack[i]) - interp = interpreter.Interpreter(space) + interp = interpreter.Interpreter(space, image_name=IMAGENAME) return (interp, frame, len(stack)) def prim(code, stack, context = None): @@ -428,7 +431,7 @@ def test_image_name(): w_v = prim(primitives.IMAGE_NAME, [2]) - assert w_v.bytes == [] + assert w_v.bytes == list(IMAGENAME) def test_clone(): w_obj = mockclass(space, 1, varsized=True).as_class_get_shadow(space).new(1) @@ -438,12 +441,69 @@ w_obj.atput0(space, 0, space.wrap_int(2)) assert space.unwrap_int(w_v.at0(space, 0)) == 1 +def test_file_open_write(monkeypatch): + def open_write(filename, mode): + assert filename == "nonexistant" + assert mode == os.O_RDWR | os.O_CREAT | os.O_TRUNC + return 42 + monkeypatch.setattr(os, "open", open_write) + try: + w_c = prim(primitives.FILE_OPEN, [1, space.wrap_string("nonexistant"), space.w_true]) + finally: + monkeypatch.undo() + assert space.unwrap_int(w_c) == 42 + +def test_file_open_read(monkeypatch): + def open_read(filename, mode): + assert filename == "file" + assert mode == os.O_RDONLY + return 42 + monkeypatch.setattr(os, "open", open_read) + try: + w_c = prim(primitives.FILE_OPEN, [1, space.wrap_string("file"), space.w_false]) + finally: + monkeypatch.undo() + assert space.unwrap_int(w_c) == 42 + +def test_file_close(monkeypatch): + def close(fd): + assert fd == 42 + monkeypatch.setattr(os, "close", close) + try: + w_c = prim(primitives.FILE_CLOSE, [1, space.wrap_int(42)]) + finally: + monkeypatch.undo() + +def test_file_write(monkeypatch): + def write(fd, string): + assert fd == 42 + assert string == "ell" + monkeypatch.setattr(os, "write", write) + try: + w_c = prim( + primitives.FILE_WRITE, + [1, space.wrap_int(42), space.wrap_string("hello"), space.wrap_int(2), space.wrap_int(3)] + ) + finally: + monkeypatch.undo() + +def test_file_write_errors(monkeypatch): + with py.test.raises(PrimitiveFailedError): + w_c = prim( + primitives.FILE_WRITE, + [1, space.wrap_int(42), space.wrap_string("hello"), space.wrap_int(-1), space.wrap_int(3)] + ) + with py.test.raises(PrimitiveFailedError): + w_c = prim( + primitives.FILE_WRITE, + [1, space.wrap_int(42), space.wrap_string("hello"), space.wrap_int(2), space.wrap_int(-1)] + ) + def test_directory_delimitor(): import os.path w_c = prim(primitives.DIRECTORY_DELIMITOR, [1]) assert space.unwrap_char(w_c) == os.path.sep - def test_primitive_closure_copyClosure(): from test_interpreter import new_frame w_frame, s_frame = new_frame("<never called, but used for method generation>", diff --git a/spyvm/test/test_wrapper.py b/spyvm/test/test_wrapper.py --- a/spyvm/test/test_wrapper.py +++ b/spyvm/test/test_wrapper.py @@ -1,11 +1,14 @@ import py -from spyvm import wrapper -from spyvm import model +from spyvm import wrapper, model, interpreter, objspace from spyvm.error import WrapperException, FatalError -from spyvm import objspace + +from spyvm.test.test_interpreter import new_frame as new_frame_tuple space = objspace.ObjSpace() +def new_frame(): + return new_frame_tuple("")[0] + def test_simpleread(): w_o = model.W_PointersObject(None, 2) w = wrapper.Wrapper(space, w_o) @@ -143,18 +146,20 @@ assert process.my_list() is space.w_nil def test_suspend_active(self): - process, old_process = self.make_processes(4, 2, space.w_false) - old_process.suspend(space.w_true) + suspended_context = new_frame() + process, old_process = self.make_processes(4, 2, suspended_context) + current_context = new_frame() + with py.test.raises(interpreter.ProcessSwitch): + old_process.suspend(current_context) process_list = wrapper.scheduler(space).get_process_list(old_process.priority()) assert process_list.first_link() is process_list.last_link() assert process_list.first_link() is space.w_nil assert old_process.my_list() is space.w_nil + assert old_process.suspended_context() is current_context assert wrapper.scheduler(space).active_process() is process._w_self - def new_process_consistency(self, process, old_process, w_active_context, - old_active_context, new_active_context): + def new_process_consistency(self, process, old_process, w_active_context): scheduler = wrapper.scheduler(space) - assert w_active_context is new_active_context assert scheduler.active_process() is process._w_self priority_list = wrapper.scheduler(space).get_process_list(process.priority()) assert priority_list.first_link() is priority_list.last_link() @@ -180,23 +185,29 @@ def test_activate(self): - process, old_process = self.make_processes(4, 2, space.w_false) - w_frame = process.activate(space.w_true) - self.new_process_consistency(process, old_process, w_frame, - space.w_true, space.w_false) + sleepingcontext = new_frame() + process, old_process = self.make_processes(4, 2, sleepingcontext) + try: + process.activate() + except interpreter.ProcessSwitch, e: + w_frame = e.s_new_context._w_self + self.new_process_consistency(process, old_process, w_frame) def test_resume(self): - process, old_process = self.make_processes(4, 2, space.w_false) - w_frame = process.resume(space.w_true) - self.new_process_consistency(process, old_process, w_frame, - space.w_true, space.w_false) - self.old_process_consistency(old_process, space.w_true) + sleepingcontext = new_frame() + currentcontext = new_frame() + process, old_process = self.make_processes(4, 2, sleepingcontext) + try: + process.resume(currentcontext) + except interpreter.ProcessSwitch, e: + w_frame = e.s_new_context._w_self + self.new_process_consistency(process, old_process, w_frame) + self.old_process_consistency(old_process, currentcontext) # Does not reactivate old_process because lower priority w_frame = old_process.resume(w_frame) - self.new_process_consistency(process, old_process, w_frame, - space.w_true, space.w_false) - self.old_process_consistency(old_process, space.w_true) + self.new_process_consistency(process, old_process, w_frame) + self.old_process_consistency(old_process, currentcontext) def test_semaphore_excess_signal(self): semaphore = new_semaphore() @@ -217,8 +228,11 @@ def test_semaphore_wait(self): semaphore = new_semaphore() - process, old_process = self.make_processes(4, 2, space.w_false) - semaphore.wait(space.w_true) + suspendedcontext = new_frame() + currentcontext = new_frame() + process, old_process = self.make_processes(4, 2, suspendedcontext) + with py.test.raises(interpreter.ProcessSwitch): + semaphore.wait(currentcontext) assert semaphore.first_link() is old_process._w_self assert wrapper.scheduler(space).active_process() is process._w_self @@ -226,11 +240,14 @@ semaphore = new_semaphore() self.space = space semaphore.signal(self) - process, old_process = self.make_processes(4, 2, space.w_false) - semaphore.wait(space.w_true) + suspendedcontext = new_frame() + currentcontext = new_frame() + process, old_process = self.make_processes(4, 2, suspendedcontext) + semaphore.wait(currentcontext) assert semaphore.is_empty_list() assert wrapper.scheduler(space).active_process() is old_process._w_self - semaphore.wait(space.w_true) + with py.test.raises(interpreter.ProcessSwitch): + semaphore.wait(currentcontext) assert semaphore.first_link() is old_process._w_self assert wrapper.scheduler(space).active_process() is process._w_self @@ -238,21 +255,28 @@ def test_semaphore_wait_signal(self): semaphore = new_semaphore() - process, old_process = self.make_processes(4, 2, space.w_false) + suspendedcontext = new_frame() + currentcontext = new_frame() + process, old_process = self.make_processes(4, 2, suspendedcontext) - semaphore.wait(space.w_true) + with py.test.raises(interpreter.ProcessSwitch): + semaphore.wait(currentcontext) + assert wrapper.scheduler(space).active_process() is process._w_self - semaphore.signal(space.w_true) + semaphore.signal(currentcontext) assert wrapper.scheduler(space).active_process() is process._w_self process_list = wrapper.scheduler(space).get_process_list(old_process.priority()) assert process_list.remove_first_link_of_list() is old_process._w_self process.write(2, space.wrap_int(1)) - old_process.resume(space.w_true) + with py.test.raises(interpreter.ProcessSwitch): + old_process.resume(currentcontext) assert wrapper.scheduler(space).active_process() is old_process._w_self - semaphore.wait(space.w_true) + with py.test.raises(interpreter.ProcessSwitch): + semaphore.wait(currentcontext) assert wrapper.scheduler(space).active_process() is process._w_self - semaphore.signal(space.w_true) + with py.test.raises(interpreter.ProcessSwitch): + semaphore.signal(currentcontext) assert wrapper.scheduler(space).active_process() is old_process._w_self process_list = wrapper.scheduler(space).get_process_list(process.priority()) diff --git a/spyvm/wrapper.py b/spyvm/wrapper.py --- a/spyvm/wrapper.py +++ b/spyvm/wrapper.py @@ -71,13 +71,16 @@ process_list = sched.get_process_list(priority) process_list.add_process(self._w_self) - def activate(self, w_current_frame): + def activate(self): + from spyvm.interpreter import ProcessSwitch + assert not self.is_active_process() sched = scheduler(self.space) sched.store_active_process(self._w_self) w_frame = self.suspended_context() self.store_suspended_context(self.space.w_nil) self.store_my_list(self.space.w_nil) - return w_frame + assert isinstance(w_frame, model.W_PointersObject) + raise ProcessSwitch(w_frame.as_context_get_shadow(self.space)) def deactivate(self, w_current_frame): self.put_to_sleep() @@ -90,7 +93,7 @@ priority = self.priority() if priority > active_priority: active_process.deactivate(w_current_frame) - return self.activate(w_current_frame) + return self.activate() else: self.put_to_sleep() return w_current_frame @@ -102,7 +105,8 @@ if self.is_active_process(): assert self.my_list().is_same_object(self.space.w_nil) w_process = scheduler(self.space).highest_priority_process() - return ProcessWrapper(self.space, w_process).activate(w_current_frame) + self.store_suspended_context(w_current_frame) + return ProcessWrapper(self.space, w_process).activate() else: process_list = ProcessListWrapper(self.space, self.my_list()) process_list.remove(self._w_self) diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py --- a/targetimageloadingsmalltalk.py +++ b/targetimageloadingsmalltalk.py @@ -54,7 +54,7 @@ def entry_point(argv): idx = 1 - image = None + path = None number = 0 benchmark = None @@ -76,20 +76,20 @@ _arg_missing(argv, idx, arg) benchmark = argv[idx + 1] idx += 1 - elif image is None: - image = argv[idx] + elif path is None: + path = argv[idx] else: _usage(argv) return -1 idx += 1 - if image is None: - image = "Squeak.image" + if path is None: + path = "Squeak.image" try: - f = open_file_as_stream(image) + f = open_file_as_stream(path) except OSError as e: - os.write(2, "%s -- %s (LoadError)\n" % (os.strerror(e.errno), image)) + os.write(2, "%s -- %s (LoadError)\n" % (os.strerror(e.errno), path)) return 1 try: imagedata = f.readall() @@ -98,7 +98,7 @@ image_reader = squeakimage.reader_for_image(space, squeakimage.Stream(data=imagedata)) image = create_image(space, image_reader) - interp = interpreter.Interpreter(space, image) + interp = interpreter.Interpreter(space, image, image_name=os.path.abspath(path)) if benchmark is not None: return _run_benchmark(interp, number, benchmark) else: _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit