Author: Lars Wassermann <[email protected]>
Branch:
Changeset: r230:1330f5e597fe
Date: 2013-03-21 16:11 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/1330f5e597fe/
Log: added SIGNAL_AT_MILLISECONDS primitive and code which checks whether
to signal
diff --git a/spyvm/constants.py b/spyvm/constants.py
--- a/spyvm/constants.py
+++ b/spyvm/constants.py
@@ -90,7 +90,7 @@
SO_BYTEARRAY_CLASS = 26
SO_PROCESS_CLASS = 27
SO_COMPACT_CLASSES_ARRAY = 28
-SO_DELAY_SEMAPHORE = 29
+SO_TIMER_SEMAPHORE = 29
SO_USER_INTERRUPT_SEMAPHORE = 30
SO_FLOAT_ZERO = 31
SO_LARGEPOSITIVEINTEGER_ZERO = 32
@@ -139,6 +139,7 @@
"display" : SO_DISPLAY_OBJECT,
"doesNotUnderstand" : SO_DOES_NOT_UNDERSTAND,
"interrupt_semaphore" : SO_USER_INTERRUPT_SEMAPHORE,
+ "timerSemaphore" : SO_TIMER_SEMAPHORE,
}
LONG_BIT = 32
@@ -176,3 +177,10 @@
primitive = primitive + (highbit << 10) ##XXX todo, check this
assert tempsize >= numargs
return primitive, literalsize, islarge, tempsize, numargs
+
+#___________________________________________________________________________
+# Interpreter constants
+#
+
+MAX_LOOP_DEPTH = 100
+INTERRUPT_COUNTER_SIZE = 1000
\ No newline at end of file
diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -41,6 +41,8 @@
self.max_stack_depth = max_stack_depth
self.remaining_stack_depth = max_stack_depth
self._loop = False
+ self.next_wakeup_tick = 0
+ self.interrupt_check_counter = constants.INTERRUPT_COUNTER_SIZE
def interpret_with_w_frame(self, w_frame):
try:
@@ -80,10 +82,15 @@
# padding = ' ' * (self.max_stack_depth - self.remaining_stack_depth)
# print padding + s_context.short_str()
old_pc = 0
+ if not jit.we_are_jitted():
+ self.quick_check_for_interrupt(s_context)
while True:
pc = s_context._pc
method = s_context.s_method()
if pc < old_pc:
+ if jit.we_are_jitted():
+ self.quick_check_for_interrupt(s_context,
+ dec=self._get_adapted_tick_counter())
self.jit_driver.can_enter_jit(
pc=pc, self=self, method=method,
s_context=s_context)
@@ -100,6 +107,14 @@
else:
s_context.push(nlr.value)
+ def _get_adapted_tick_counter(self):
+ # Normally, the tick counter is decremented by 1 for every message
send.
+ # Since we don't know how many messages are called during this trace,
we
+ # just decrement by 10th of the trace length (num of bytecodes).
+ trace_length = jit.current_trace_length()
+ decr_by = int(trace_length // 10)
+ return max(decr_by, 1)
+
def stack_frame(self, s_new_frame):
if not self._loop:
return s_new_frame # this test is done to not loop in test,
@@ -138,6 +153,36 @@
except ReturnFromTopLevel, e:
return e.object
+ def quick_check_for_interrupt(self, s_frame, dec=1):
+ self.interrupt_check_counter -= dec
+ if self.interrupt_check_counter <= 0:
+ self.interrupt_check_counter = constants.INTERRUPT_COUNTER_SIZE
+ self.check_for_interrupts(s_frame)
+
+ 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))
+
+ # XXX the low space semaphore may be signaled here
+ # Process inputs
+ # Process User Interrupt?
+ if not self.next_wakeup_tick == 0 and now >= self.next_wakeup_tick:
+ self.next_wakeup_tick = 0
+ semaphore = self.space.objtable["w_timerSemaphore"]
+ if not semaphore.is_same_object(self.space.w_nil):
+ wrapper.SemaphoreWrapper(self.space,
semaphore).signal(s_frame.w_self())
+ # We have no finalization process, so far.
+ # We do not support external semaphores.
+ # In cog, the method to add such a semaphore is only called in GC.
+
+
+
class ReturnFromTopLevel(Exception):
def __init__(self, object):
self.object = object
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -823,14 +823,26 @@
#____________________________________________________________________________
# Time Primitives (135 - 137)
MILLISECOND_CLOCK = 135
+SIGNAL_AT_MILLISECONDS = 136
SECONDS_CLOCK = 137
@expose_primitive(MILLISECOND_CLOCK, unwrap_spec=[object])
def func(interp, s_frame, w_arg):
- import time
- import math
+ import time, math
return interp.space.wrap_int(int(math.fmod(time.time()*1000,
constants.TAGGED_MAXINT/2)))
+@expose_primitive(SIGNAL_AT_MILLISECONDS, unwrap_spec=[object, object, int])
+def func(interp, s_frame, w_delay, w_semaphore, timestamp):
+ if not w_semaphore.getclass(interp.space).is_same_object(
+ interp.space.w_Semaphore):
+ interp.space.objtable["w_timerSemaphore"] = interp.space.w_nil
+ interp.next_wakeup_tick = timestamp
+ else:
+ interp.space.objtable["w_timerSemaphore"] = w_semaphore
+ interp.next_wakeup_tick = timestamp
+ return w_delay
+
+
secs_between_1901_and_1970 = rarithmetic.r_uint((69 * 365 + 17) * 24 * 3600)
@@ -1114,7 +1126,7 @@
return wrapper.SemaphoreWrapper(interp.space,
w_rcvr).wait(s_frame.w_self())
@expose_primitive(RESUME, unwrap_spec=[object], result_is_new_frame=True)
-def func(interp, s_frame, w_rcvr,):
+def func(interp, s_frame, w_rcvr):
# XXX we might want to disable this check
if not w_rcvr.getclass(interp.space).is_same_object(
interp.space.w_Process):
@@ -1125,7 +1137,7 @@
return w_frame.as_context_get_shadow(interp.space)
@expose_primitive(SUSPEND, unwrap_spec=[object], result_is_new_frame=True)
-def func(interp, s_frame, w_rcvr, result_is_new_frame=True):
+def func(interp, s_frame, w_rcvr):
# XXX we might want to disable this check
if not w_rcvr.getclass(interp.space).is_same_object(
interp.space.w_Process):
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
@@ -173,7 +173,7 @@
SO_BYTEARRAY_CLASS = 26
SO_PROCESS_CLASS = 27
SO_COMPACT_CLASSES_ARRAY = 28
- SO_DELAY_SEMAPHORE = 29
+ SO_TIMER_SEMAPHORE = 29
SO_USER_INTERRUPT_SEMAPHORE = 30
SO_FLOAT_ZERO = 31
SO_LARGEPOSITIVEINTEGER_ZERO = 32
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
@@ -411,6 +411,13 @@
stop = prim(primitives.MILLISECOND_CLOCK, [0]).value
assert start + 250 <= stop
+def test_signal_at_milliseconds():
+ import time
+ future = prim(primitives.MILLISECOND_CLOCK, [0]).value + 400
+ sema = space.w_Semaphore.as_class_get_shadow(space).new()
+ prim(primitives.SIGNAL_AT_MILLISECONDS, [space.w_nil, sema, future])
+ assert space.objtable["w_timerSemaphore"] is sema
+
def test_inc_gc():
# Should not fail :-)
prim(primitives.INC_GC, [42]) # Dummy arg
diff --git a/spyvm/todo.txt b/spyvm/todo.txt
--- a/spyvm/todo.txt
+++ b/spyvm/todo.txt
@@ -42,7 +42,8 @@
[ ] Implement image writer
Shadows:
-[ ] Fix invalidation of methoddictshadow when the w_self of its values array
changes
+[ ] What to do with shadows when their w_self changes class?
+[ ] Weak references for subclasses
Optimizations:
@@ -53,3 +54,5 @@
return model.W_SmallInteger(rerased.erase_int(val))
except OverflowError:
raise WrappingError("integer too large to fit into a tagged
pointer")
+
+use special class for 1WordLargeIntegers
\ No newline at end of file
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit