Skip to content

Commit

Permalink
try to save a few ops by removing the native_* checks in byte and words
Browse files Browse the repository at this point in the history
  • Loading branch information
timfel committed May 10, 2016
1 parent dc8b8e2 commit 19ec5f9
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 153 deletions.
3 changes: 0 additions & 3 deletions rsqueakvm/model/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,6 @@ def can_become(self, w_other):
# TODO - implement _become() for this class. Impossible due to _immutable_fields_?
return False

def convert_to_c_layout(self):
return self._real_depth_buffer

def __del__(self):
lltype.free(self._real_depth_buffer, flavor='raw')

Expand Down
125 changes: 12 additions & 113 deletions rsqueakvm/model/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


class W_BytesObject(W_AbstractObjectWithClassReference):
_attrs_ = ['version', 'bytes', 'native_bytes']
_attrs_ = ['version', 'bytes']
repr_classname = 'W_BytesObject'
bytes_per_slot = 1
_immutable_fields_ = ['version?']
Expand All @@ -19,7 +19,6 @@ def __init__(self, space, w_class, size):
assert isinstance(size, int)
self.mutate()
self.bytes = ['\x00'] * size
self.native_bytes = None

def mutate(self):
self.version = Version()
Expand All @@ -28,7 +27,6 @@ def fillin(self, space, g_self):
W_AbstractObjectWithClassReference.fillin(self, space, g_self)
self.mutate()
self.bytes = g_self.get_bytes()
self.native_bytes = None

def at0(self, space, index0):
return space.wrap_int(ord(self.getchar(index0)))
Expand All @@ -37,18 +35,12 @@ def atput0(self, space, index0, w_value):
self.setchar(index0, chr(space.unwrap_int(w_value)))

def getchar(self, n0):
if self.native_bytes is not None:
return self.native_bytes.getchar(n0)
else:
return self.bytes[n0]
return self.bytes[n0]

def setchar(self, n0, character):
assert isinstance(character, str)
assert len(character) == 1
if self.native_bytes is not None:
self.native_bytes.setchar(n0, character)
else:
self.bytes[n0] = character
self.bytes[n0] = character
self.mutate()

def short_at0(self, space, index0):
Expand All @@ -71,10 +63,7 @@ def short_atput0(self, space, index0, w_value):
self.setchar(byte_index0 + 1, chr(byte1))

def size(self):
if self.native_bytes is not None:
return self.native_bytes.size
else:
return len(self.bytes)
return len(self.bytes)

def str_content(self):
if self.getclass(None).has_space():
Expand All @@ -89,16 +78,10 @@ def unwrap_string(self, space):

@jit.elidable
def _pure_as_string(self, version):
if self.native_bytes is not None:
return self.native_bytes.as_string()
else:
return "".join(self.bytes)
return "".join(self.bytes)

def getbytes(self):
if self.native_bytes is not None:
return self.native_bytes.copy_bytes()
else:
return self.bytes
return self.bytes

def selector_string(self):
return "#" + self.unwrap_string(None)
Expand All @@ -114,10 +97,7 @@ def invariant(self):
def clone(self, space):
size = self.size()
w_result = W_BytesObject(space, self.getclass(space), size)
if self.native_bytes is not None:
w_result.bytes = self.native_bytes.copy_bytes()
else:
w_result.bytes = list(self.bytes)
w_result.bytes = list(self.bytes)
return w_result

@jit.unroll_safe
Expand Down Expand Up @@ -173,59 +153,23 @@ def is_array_object(self):
def _become(self, w_other):
assert isinstance(w_other, W_BytesObject)
self.bytes, w_other.bytes = w_other.bytes, self.bytes
self.native_bytes, w_other.native_bytes = w_other.native_bytes, self.native_bytes
self.mutate()
W_AbstractObjectWithClassReference._become(self, w_other)

def convert_to_c_layout(self):
if self.bytes is not None:
self.native_bytes = NativeBytesWrapper(self.unwrap_string(None))
self.bytes = None
self.mutate()
return self.native_bytes.c_bytes


# This indirection avoids a call for alloc_with_del in Jitted code
class NativeBytesWrapper(object):
_attrs_ = ["c_bytes", "size"]
_immutable_fields_ = ["c_bytes", "size"]
def __init__(self, string):
self.size = len(string)
self.c_bytes = rffi.str2charp(string)

def setchar(self, n0, char):
self.c_bytes[n0] = char

def getchar(self, n0):
if n0 >= self.size:
raise IndexError
return self.c_bytes[n0]

def as_string(self):
return "".join([self.c_bytes[i] for i in range(self.size)])

def copy_bytes(self):
return [self.c_bytes[i] for i in range(self.size)]

def __del__(self):
rffi.free_charp(self.c_bytes)


class W_WordsObject(W_AbstractObjectWithClassReference):
# TODO: this assumes only 32-bit words objects
_attrs_ = ['words', 'native_words']
_attrs_ = ['words']
repr_classname = "W_WordsObject"
_immutable_fields_ = ['words?']

def __init__(self, space, w_class, size):
W_AbstractObjectWithClassReference.__init__(self, space, w_class)
self.words = [r_uint(0)] * size
self.native_words = None

def fillin(self, space, g_self):
W_AbstractObjectWithClassReference.fillin(self, space, g_self)
self.words = g_self.get_ruints()
self.native_words = None

def at0(self, space, index0):
val = self.getword(index0)
Expand All @@ -237,16 +181,10 @@ def atput0(self, space, index0, w_value):

def getword(self, n):
assert self.size() > n >= 0
if self.native_words is not None:
return r_uint(self.native_words.getword(n))
else:
return self.words[n]
return self.words[n]

def setword(self, n, word):
if self.native_words is not None:
self.native_words.setword(n, intmask(word))
else:
self.words[n] = r_uint(word)
self.words[n] = r_uint(word)

def getchar(self, n0):
return chr(self.getword(n0))
Expand Down Expand Up @@ -288,10 +226,7 @@ def short_atput0(self, space, index0, w_value):
self.setword(word_index0, value)

def size(self):
if self.native_words is not None:
return self.native_words.size
else:
return len(self.words)
return len(self.words)

@jit.look_inside_iff(lambda self, space: jit.isconstant(self.size()))
def unwrap_string(self, space):
Expand All @@ -311,10 +246,7 @@ def invariant(self):
def clone(self, space):
size = self.size()
w_result = W_WordsObject(space, self.getclass(space), size)
if self.native_words is not None:
w_result.words = self.native_words.copy_words()
else:
w_result.words = list(self.words)
w_result.words = list(self.words)
return w_result

def is_array_object(self):
Expand All @@ -323,37 +255,4 @@ def is_array_object(self):
def _become(self, w_other):
assert isinstance(w_other, W_WordsObject)
self.words, w_other.words = w_other.words, self.words
self.native_words, w_other.native_words = w_other.native_words, self.native_words
W_AbstractObjectWithClassReference._become(self, w_other)

def convert_to_c_layout(self):
if self.words is not None:
self.native_words = NativeWordsWrapper(self.words)
self.words = None
return self.native_words.c_words


class NativeWordsWrapper(object):
_attrs_ = ["c_words", "size"]
_immutable_fields_ = ["c_words", "size"]

def __init__(self, words):
self.size = len(words)
from rsqueakvm.plugins.squeak_plugin_proxy import sqIntArrayPtr
self.c_words = lltype.malloc(sqIntArrayPtr.TO, self.size, flavor='raw')
for i in range(self.size):
self.c_words[i] = rffi.r_int(words[i])

def setword(self, n0, word):
self.c_words[n0] = rffi.r_int(word)

def getword(self, n0):
if n0 >= self.size:
raise IndexError
return r_uint(self.c_words[n0])

def copy_words(self):
return [r_uint(self.c_words[i]) for i in range(self.size)]

def __del__(self):
lltype.free(self.c_words, flavor='raw')
22 changes: 11 additions & 11 deletions rsqueakvm/plugins/squeak_plugin_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,17 +247,17 @@ def firstFixedField(w_object):
# return a list with oops (?) of w_objects instVars
raise ProxyFunctionFailed

@expose_on_virtual_machine_proxy([oop], list)
def firstIndexableField(w_object):
# return a list with values (?) of w_objects variable-parts
if isinstance(w_object, W_WordsObject):
return w_object.convert_to_c_layout()
elif isinstance(w_object, W_BytesObject):
return rffi.cast(sqIntArrayPtr, w_object.convert_to_c_layout())
elif isinstance(w_object, W_DisplayBitmap):
return rffi.cast(sqIntArrayPtr, w_object.convert_to_c_layout())
else:
raise ProxyFunctionFailed
# @expose_on_virtual_machine_proxy([oop], list)
# def firstIndexableField(w_object):
# # return a list with values (?) of w_objects variable-parts
# if isinstance(w_object, W_WordsObject):
# return w_object.convert_to_c_layout()
# elif isinstance(w_object, W_BytesObject):
# return rffi.cast(sqIntArrayPtr, w_object.convert_to_c_layout())
# elif isinstance(w_object, W_DisplayBitmap):
# return rffi.cast(sqIntArrayPtr, w_object.convert_to_c_layout())
# else:
# raise ProxyFunctionFailed

@expose_on_virtual_machine_proxy([int, oop], oop)
def literalofMethod(offset, w_method):
Expand Down
26 changes: 0 additions & 26 deletions rsqueakvm/test/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,19 +71,6 @@ def test_bytes_object():
assert w_bytes.getchar(0) == "\x00"
py.test.raises(IndexError, lambda: w_bytes.getchar(20))

def test_c_bytes_object():
w_class = bootstrap_class(0, format=storage_classes.BYTES)
w_bytes = w_class.as_class_get_shadow(space).new(20)
w_bytes.convert_to_c_layout()
assert w_bytes.getclass(space).is_same_object(w_class)
assert w_bytes.size() == 20
assert w_class.as_class_get_shadow(space).instsize() == 0
assert w_bytes.getchar(3) == "\x00"
w_bytes.setchar(3, "\xAA")
assert w_bytes.getchar(3) == "\xAA"
assert w_bytes.getchar(0) == "\x00"
py.test.raises(IndexError, lambda: w_bytes.getchar(20))

def test_word_object():
w_class = bootstrap_class(0, format=storage_classes.WORDS)
w_bytes = w_class.as_class_get_shadow(space).new(20)
Expand All @@ -96,19 +83,6 @@ def test_word_object():
assert w_bytes.getword(0) == 0
py.test.raises(AssertionError, lambda: w_bytes.getword(20))

def test_c_word_object():
w_class = bootstrap_class(0, format=storage_classes.WORDS)
w_bytes = w_class.as_class_get_shadow(space).new(20)
w_bytes.convert_to_c_layout()
assert w_bytes.getclass(space).is_same_object(w_class)
assert w_bytes.size() == 20
assert w_class.as_class_get_shadow(space).instsize() == 0
assert w_bytes.getword(3) == 0
w_bytes.setword(3, 42)
assert w_bytes.getword(3) == 42
assert w_bytes.getword(0) == 0
py.test.raises(AssertionError, lambda: w_bytes.getword(20))

def test_method_lookup():
class mockmethod(object):
def __init__(self, val):
Expand Down

0 comments on commit 19ec5f9

Please sign in to comment.