def normalize_simple_slice(space, length, w_start, w_stop): """Helper for the {get,set,del}slice implementations.""" # this returns a pair (start, stop) which is usable for slicing # a sequence of the given length in the most friendly way, i.e. # guaranteeing that 0 <= start <= stop <= length. start = space.int_w(w_start) stop = space.int_w(w_stop) assert length >= 0 if start < 0: start = 0 # hack for the JIT, for slices with no end specified: # this avoids the two comparisons that follow if jit.isconstant(stop) and stop == sys.maxint: pass else: if stop < start: stop = start if stop <= length: return start, stop # here is the case where 'stop' is larger than the list stop = length if jit.isconstant(start) and start == 0: pass # no need to do the following check here elif start > stop: start = stop return start, stop
def read(self, obj, selector): attr = self.find_map_attr(selector) if attr is None: return self.terminator._read_terminator(obj, selector) if jit.isconstant(attr.storageindex) and jit.isconstant(obj) and not attr.ever_mutated: return self._pure_mapdict_read_storage(obj, attr.storageindex) else: return obj._mapdict_read_storage(attr.storageindex)
def eq(self, other): # slightly evil if jit.isconstant(self): jit.promote(other) elif jit.isconstant(other): jit.promote(self) return self is other or (self.numargs == other.numargs and self.name == other.name)
def eq(self, other): # slightly evil if jit.isconstant(self): jit.promote(other) elif jit.isconstant(other): jit.promote(self) return self is other or ( self.numargs == other.numargs and self.name == other.name)
def read(self, obj, name, index): attr = self.find_map_attr(name, index) if attr is None: return self.terminator._read_terminator(obj, name, index) if (jit.isconstant(attr.storageindex) and jit.isconstant(obj) and not attr.ever_mutated): return self._pure_mapdict_read_storage(obj, attr.storageindex) else: return obj._mapdict_read_storage(attr.storageindex)
def read(self, obj, name, attrkind): attr = self.find_map_attr(name, attrkind) if attr is None: return self.terminator._read_terminator(obj, name, attrkind) if (jit.isconstant(attr) and jit.isconstant(obj) and not attr.ever_mutated): return attr._pure_direct_read(obj) else: return attr._direct_read(obj)
def _ll_list_resize_le(l, newsize): """This is called with 'newsize' smaller than the current length of the list. If 'newsize' falls lower than half the allocated size, proceed with the realloc() to shrink the list. """ cond = newsize < (len(l.items) >> 1) - 5 if jit.isconstant(len(l.items)) and jit.isconstant(newsize): if cond: _ll_list_resize_hint_really(l, newsize, False) else: jit.conditional_call(cond, _ll_list_resize_hint_really, l, newsize, False) l.length = newsize
def _ll_list_resize_ge(l, newsize): """This is called with 'newsize' larger than the current length of the list. If the list storage doesn't have enough space, then really perform a realloc(). In the common case where we already overallocated enough, then this is a very fast operation. """ cond = len(l.items) < newsize if jit.isconstant(len(l.items)) and jit.isconstant(newsize): if cond: _ll_list_resize_hint_really(l, newsize, True) else: jit.conditional_call(cond, _ll_list_resize_hint_really, l, newsize, True) l.length = newsize
def _ll_list_resize_le(l, newsize): """This is called with 'newsize' smaller than the current length of the list. If 'newsize' falls lower than half the allocated size, proceed with the realloc() to shrink the list. """ cond = newsize < (len(l.items) >> 1) - 5 # note: overallocate=False should be safe here if jit.isconstant(len(l.items)) and jit.isconstant(newsize): if cond: _ll_list_resize_hint_really(l, newsize, False) else: jit.conditional_call(cond, _ll_list_resize_hint_really, l, newsize, False) l.length = newsize
def __init__(self, space, args_w, keywords=None, keywords_w=None, w_stararg=None, w_starstararg=None, keyword_names_w=None): self.space = space assert isinstance(args_w, list) self.arguments_w = args_w self.keywords = keywords self.keywords_w = keywords_w self.keyword_names_w = keyword_names_w # matches the tail of .keywords if keywords is not None: assert keywords_w is not None assert len(keywords_w) == len(keywords) assert (keyword_names_w is None or len(keyword_names_w) <= len(keywords)) make_sure_not_resized(self.keywords) make_sure_not_resized(self.keywords_w) make_sure_not_resized(self.arguments_w) self._combine_wrapped(w_stararg, w_starstararg) # a flag that specifies whether the JIT can unroll loops that operate # on the keywords self._jit_few_keywords = self.keywords is None or jit.isconstant( len(self.keywords))
def __init__(self, space, args_w, keywords=None, keywords_w=None, w_stararg=None, w_starstararg=None, keyword_names_w=None, methodcall=False): self.space = space assert isinstance(args_w, list) self.arguments_w = args_w self.keywords = keywords self.keywords_w = keywords_w self.keyword_names_w = keyword_names_w # matches the tail of .keywords if keywords is not None: assert keywords_w is not None assert len(keywords_w) == len(keywords) assert (keyword_names_w is None or len(keyword_names_w) <= len(keywords)) make_sure_not_resized(self.keywords) make_sure_not_resized(self.keywords_w) make_sure_not_resized(self.arguments_w) self._combine_wrapped(w_stararg, w_starstararg) # a flag that specifies whether the JIT can unroll loops that operate # on the keywords self._jit_few_keywords = self.keywords is None or jit.isconstant(len(self.keywords)) # a flag whether this is likely a method call, which doesn't change the # behaviour but produces better error messages self.methodcall = methodcall
def __init__(self, space, args_w, keywords=None, keywords_w=None, w_stararg=None, w_starstararg=None, keyword_names_w=None, methodcall=False, fnname_parens=None): self.space = space assert isinstance(args_w, list) self.arguments_w = args_w self.keywords = keywords self.keywords_w = keywords_w self.keyword_names_w = keyword_names_w # matches the tail of .keywords if keywords is not None: assert keywords_w is not None assert len(keywords_w) == len(keywords) assert (keyword_names_w is None or len(keyword_names_w) <= len(keywords)) make_sure_not_resized(self.keywords) make_sure_not_resized(self.keywords_w) make_sure_not_resized(self.arguments_w) self._combine_wrapped(w_stararg, w_starstararg, fnname_parens) # a flag that specifies whether the JIT can unroll loops that operate # on the keywords self._jit_few_keywords = self.keywords is None or jit.isconstant( len(self.keywords)) # a flag whether this is likely a method call, which doesn't change the # behaviour but produces better error messages self.methodcall = methodcall
def size(self): sz = jit.conditional_call_elidable(self._exposed_size, calculate_exposed_size_for_big_int, self.value) if not jit.isconstant(self): self._exposed_size = sz return sz
def ffi_type(self, w_x, accept): space = self.space if (accept & ACCEPT_STRING) and (space.isinstance_w( w_x, space.w_basestring)): string = space.text_w(w_x) consider_fn_as_fnptr = (accept & CONSIDER_FN_AS_FNPTR) != 0 if jit.isconstant(string): try: return self.get_string_to_type(string, consider_fn_as_fnptr) except KeyError: pass return self.parse_string_to_type(string, consider_fn_as_fnptr) if (accept & ACCEPT_CTYPE) and isinstance(w_x, W_CType): return w_x if (accept & ACCEPT_CDATA) and isinstance(w_x, W_CData): return w_x.ctype # m1 = "string" if accept & ACCEPT_STRING else "" m2 = "ctype object" if accept & ACCEPT_CTYPE else "" m3 = "cdata object" if accept & ACCEPT_CDATA else "" s12 = " or " if m1 and (m2 or m3) else "" s23 = " or " if m2 and m3 else "" raise oefmt(space.w_TypeError, "expected a %s%s%s%s%s, got '%T'", m1, s12, m2, s23, m3, w_x)
def pow_small_int(self, n): if n >= 0: if jit.isconstant(n) and n == 2: return self.mul(self) return self.pow_positive_int(n) else: return w_one.div(self.pow_positive_int(-n))
def w_dict_unrolling_heuristic(w_dct): """In which cases iterating over dict items can be unrolled. Note that w_dct is an instance of W_DictMultiObject, not necesarilly an actual dict """ return jit.isvirtual(w_dct) or (jit.isconstant(w_dct) and w_dct.length() <= UNROLL_CUTOFF)
def string_append(args): if jit.isconstant(len(args)): return string_append_fastpath(args) if not args: return W_String.fromascii("") builder = StringBuilder(len(args)) unibuilder = None ascii_idx = 0 try: for ascii_idx in range(len(args)): arg = args[ascii_idx] if not isinstance(arg, W_String): raise SchemeException("string-append: expected a string") builder.append(arg.as_str_ascii()) except ValueError: unibuilder = UnicodeBuilder(len(args)) unibuilder.append(unicode(builder.build())) builder = None for i in range(ascii_idx, len(args)): arg = args[i] if not isinstance(arg, W_String): raise SchemeException("string-append: expected a string") unibuilder.append(arg.as_unicode()) if unibuilder is None: assert builder is not None return W_String.fromascii(builder.build()) else: assert unibuilder is not None return W_String.fromunicode(unibuilder.build())
def descr_new(space, w_stringtype, w_source=None, encoding=None, errors=None): if (w_source and space.is_w(w_stringtype, space.w_bytes) and encoding is None and errors is None): # special-case 'bytes(byte_object)' w_srctype = space.type(w_source) if w_srctype is space.w_bytes: return w_source # special-case 'bytes([single_integer])' or 'bytes((single_int,))' # for JITted performance only, when we clearly see the # length of the list/tuple being constant and equal to 1 if w_srctype is space.w_list or w_srctype is space.w_tuple: length = space.len_w(w_source) if jit.isconstant(length) and length == 1: w_item = space.getitem(w_source, space.newint(0)) value = space.byte_w(w_item) return W_BytesObject(value) else: # special-case 'bytes(X)' if X has a __bytes__() method: # we must return the result unmodified even if it is a # subclass of bytes w_result = invoke_bytes_method(space, w_source) if w_result is not None: return w_result value = newbytesdata_w_tail(space, w_source) else: value = newbytesdata_w(space, w_source, encoding, errors) w_obj = space.allocate_instance(W_BytesObject, w_stringtype) W_BytesObject.__init__(w_obj, value) return w_obj
def convert_string_to_number(s, can_be_octal=False): """Returns (wrapped number, flag: number-fully-processed).""" length = len(s) if jit.isconstant(length) and length == 1: # 's' is actually a char. return _convert_char_to_number(s[0]) else: return _convert_string_to_number(s, can_be_octal)
def size(self): sz = jit.conditional_call_elidable( self._exposed_size, calculate_exposed_size_for_big_int, self.value) if not jit.isconstant(self): self._exposed_size = sz return sz
def getitem_unicode(self, w_dict, w_key): storage_w = self.unerase(w_dict.dstorage) if jit.isconstant(w_key): jit.promote(self) index = self.jsonmap.get_index(w_key) if index == -1: return None return storage_w[index]
def _raw_memcopy(source, dest, size): if jit.isconstant(size): # for the JIT: first handle the case where 'size' is known to be # a constant equal to 1, 2, 4, 8 for TP, TPP in _prim_unsigned_types: if size == rffi.sizeof(TP): _raw_memcopy_tp(TPP, source, dest) return _raw_memcopy_opaque(source, dest, size)
def decrement_ticker(self, by): value = self._ticker if self.has_bytecode_counter: # this 'if' is constant-folded if jit.isconstant(by) and by == 0: pass # normally constant-folded too else: value -= by self._ticker = value return value
def decrement_ticker(self, by): p = pypysig_getaddr_occurred() value = p.c_value if self.has_bytecode_counter: # this 'if' is constant-folded if jit.isconstant(by) and by == 0: pass # normally constant-folded too else: value -= by p.c_value = value return value
def _pack(space, format, args_w): if jit.isconstant(format): size = _calcsize(space, format) else: size = 8 fmtiter = PackFormatIterator(space, args_w, size) try: fmtiter.interpret(format) except StructOverflowError, e: raise OperationError(space.w_OverflowError, space.wrap(e.msg))
def pack(space, format, args_w): if jit.isconstant(format): size = _calcsize(space, format) else: size = 8 fmtiter = PackFormatIterator(space, args_w, size) try: fmtiter.interpret(format) except StructOverflowError, e: raise OperationError(space.w_OverflowError, space.wrap(e.msg))
class StringFormatter(object): """ From https://github.com/topazproject/topaz""" def __init__(self, fmt, items_w): assert isinstance(fmt, unicode) self.fmt = fmt self.items_w = items_w self.item_index = 0 @jit.look_inside_iff(lambda self: jit.isconstant(self.fmt)) def format(self): i = 0 result_w = [] while True: start = i while i < len(self.fmt): if self.fmt[i] == "%": break i += 1 else: result_w.append(self.fmt[start:i]) break result_w.append(self.fmt[start:i]) i += 1 if self.fmt[i] == '.': # ignore dots TODO i += 1 width = 0 while self.fmt[i] in [unicode(str(s)) for s in range(0, 9)]: width = width * 10 + (ord(self.fmt[i]) - ord("0")) i += 1 format_char = self.fmt[i] w_item = self.items_w[self.item_index] self.item_index += 1 i += 1 for c in FORMAT_CHARS: if c == format_char: w_res = getattr(self, "fmt_" + c)(w_item, width) result_w.append(w_res) break else: raise NotImplementedError(format_char) return u''.join(result_w) def _fmt_num(self, num, width): return (width - len(num)) * u"0" + num def fmt_s(self, w_item, width): return w_item.str() def fmt_d(self, w_item, width): num = w_item.str() return self._fmt_num(num, width) def fmt_f(self, w_item, width): num = w_item.to_number() return self._fmt_num(unicode(formatd(num, "f", width)), width)
def pushNewArrayBytecode(self, interp, current_bytecode, descriptor): arraySize, popIntoArray = splitter[7, 1](descriptor) newArray = None if popIntoArray == 1: if jit.we_are_jitted() and jit.isconstant(arraySize) and arraySize < vmconstants.LITERAL_LIST_UNROLL_SIZE: newArray = interp.space.wrap_list_unroll_safe(self.pop_and_return_n(arraySize)) else: newArray = interp.space.wrap_list(self.pop_and_return_n(arraySize)) else: newArray = interp.space.w_Array.as_class_get_shadow(interp.space).new(arraySize) self.push(newArray)
class W_SRE_Match(W_Root): flatten_cache = None def __init__(self, srepat, ctx): self.space = srepat.space self.srepat = srepat self.ctx = ctx def cannot_copy_w(self): space = self.space raise OperationError(space.w_TypeError, space.wrap("cannot copy this match object")) @jit.look_inside_iff(lambda self, args_w: jit.isconstant(len(args_w))) def group_w(self, args_w): space = self.space ctx = self.ctx if len(args_w) <= 1: if len(args_w) == 0: start, end = ctx.match_start, ctx.match_end else: start, end = self.do_span(args_w[0]) return slice_w(space, ctx, start, end, space.w_None) else: results = [None] * len(args_w) for i in range(len(args_w)): start, end = self.do_span(args_w[i]) results[i] = slice_w(space, ctx, start, end, space.w_None) return space.newtuple(results) @unwrap_spec(w_default=WrappedDefault(None)) def groups_w(self, w_default=None): fmarks = self.flatten_marks() num_groups = self.srepat.num_groups return allgroups_w(self.space, self.ctx, fmarks, num_groups, w_default) @unwrap_spec(w_default=WrappedDefault(None)) def groupdict_w(self, w_default=None): space = self.space w_dict = space.newdict() w_groupindex = self.srepat.w_groupindex w_iterator = space.iter(w_groupindex) while True: try: w_key = space.next(w_iterator) except OperationError, e: if not e.match(space, space.w_StopIteration): raise break # done w_value = space.getitem(w_groupindex, w_key) start, end = self.do_span(w_value) w_grp = slice_w(space, self.ctx, start, end, w_default) space.setitem(w_dict, w_key, w_grp) return w_dict
def _pack(space, format, args_w): if jit.isconstant(format): size = _calcsize(space, format) else: size = 8 fmtiter = PackFormatIterator(space, args_w, size) try: fmtiter.interpret(format) except StructOverflowError as e: raise OperationError(space.w_OverflowError, space.wrap(e.msg)) except StructError as e: raise OperationError(get_error(space), space.wrap(e.msg)) return fmtiter.result.build()
def _pack(space, format, args_w): if jit.isconstant(format): size = _calcsize(space, format) else: size = 8 fmtiter = PackFormatIterator(space, args_w, size) try: fmtiter.interpret(format) except StructOverflowError as e: raise OperationError(space.w_OverflowError, space.newtext(e.msg)) except StructError as e: raise OperationError(get_error(space), space.newtext(e.msg)) return fmtiter.result.build()
class StringFormatter(object): def __init__(self, fmt, items_w): self.fmt = fmt self.items_w = items_w self.item_index = 0 @jit.look_inside_iff(lambda self, space: jit.isconstant(self.fmt)) def format(self, space): i = 0 result_w = [] while True: start = i while i < len(self.fmt): if self.fmt[i] == "%": break i += 1 else: result_w.append(space.newstr_fromstr(self.fmt[start:i])) break result_w.append(space.newstr_fromstr(self.fmt[start:i])) i += 1 width = 0 while self.fmt[i].isdigit(): width = width * 10 + (ord(self.fmt[i]) - ord("0")) i += 1 format_char = self.fmt[i] w_item = self.items_w[self.item_index] self.item_index += 1 i += 1 for c in FORMAT_CHARS: if c == format_char: w_res = getattr(self, "fmt_" + c)(space, w_item, width) result_w.append(w_res) break else: raise NotImplementedError(format_char) return result_w def _fmt_num(self, space, num, width): return space.newstr_fromstr((width - len(num)) * "0" + num) def fmt_s(self, space, w_item, width): return space.send(w_item, space.newsymbol("to_s")) def fmt_d(self, space, w_item, width): num = space.int_w(w_item) return self._fmt_num(space, str(num), width) def fmt_f(self, space, w_item, width): num = space.float_w(w_item) return self._fmt_num(space, formatd(num, "f", 6), width)
def ll_jit_try_append_multiple_char(ll_builder, char, size): if jit.isconstant(size): if size == 0: return True # a special case: if the builder's pos and end are still contants # (typically if the builder is still virtual), and if 'size' fits, # then we don't need any reallocation and can just set the # characters in the buffer, in a way that won't force anything. if (jit.isconstant(ll_builder.current_pos) and jit.isconstant(ll_builder.current_end) and size <= (ll_builder.current_end - ll_builder.current_pos) and size <= 16): pos = ll_builder.current_pos buf = ll_builder.current_buf stop = pos + size ll_builder.current_pos = stop while pos < stop: buf.chars[pos] = char pos += 1 return True if size == 1: ll_append_char(ll_builder, char) return True return False # use the fall-back path
class UnwrappedVectorStrategyMixin(object): # the concrete class needs to implement: # erase, unerase, is_correct_type, wrap, unwrap def _copy_storage(self, w_vector, immutable=False): strategy = self if not immutable else self.immutable_variant() l = self.unerase(w_vector.get_storage())[:] return W_Vector(strategy, self.erase(l), w_vector.len) def _storage(self, w_vector): l = self.unerase(w_vector.get_storage()) debug.make_sure_not_resized(l) return l def _ref(self, w_vector, i): assert i >= 0 return self.wrap(self._storage(w_vector)[i]) def _set(self, w_vector, i, w_val): assert i >= 0 self._storage(w_vector)[i] = self.unwrap(w_val) @jit.look_inside_iff(lambda strategy, w_vector: jit.isconstant( w_vector.length()) and w_vector.length() < UNROLLING_CUTOFF) def ref_all(self, w_vector): unwrapped = self._storage(w_vector) return [self.wrap(i) for i in unwrapped] def create_storage_for_element(self, element, times): e = self.unwrap(element) return self.erase([e] * times) @jit.look_inside_iff(lambda self, elements_w: jit.loop_unrolling_heuristic( elements_w, len(elements_w), UNROLLING_CUTOFF)) def create_storage_for_elements(self, elements_w): if not elements_w: return self.erase([]) l = [self.unwrap(e) for e in elements_w] return self.erase(l) def wrap(self, obj): return obj def unwrap(self, w_obj): return w_obj def unrolling_heuristic(self, w_vector): storage = self._storage(w_vector) return jit.loop_unrolling_heuristic(storage, w_vector.len, UNROLLING_CUTOFF)
def _pack(space, format, args_w): """Return string containing values v1, v2, ... packed according to fmt.""" if jit.isconstant(format): size = _calcsize(space, format) else: size = 8 fmtiter = PackFormatIterator(space, args_w, size) try: fmtiter.interpret(format) except StructOverflowError as e: raise OperationError(space.w_OverflowError, space.newtext(e.msg)) except StructError as e: raise OperationError(get_error(space), space.newtext(e.msg)) return fmtiter.result.build()
def get(self): if jit.isconstant(self): # ever_mutated is False if we never see a transition from not-None to # not-None. That means _elidable_get might return an out-of-date # None, and by now the cell was to, with a not-None. So if we see a # None, we don't return that and instead read self.w_value in the # code below. if not self.family.ever_mutated: w_res = self._elidable_get() if w_res is not None: return w_res if self.w_value is None: raise ValueError("get() from an empty cell") return self.w_value
def ll_jit_try_append_slice(ll_builder, ll_str, start, size): if jit.isconstant(size): if size == 0: return True # a special case: if the builder's pos and end are still contants # (typically if the builder is still virtual), and if 'size' fits, # then we don't need any reallocation and can just set the # characters in the buffer, in a way that won't force anything. if (jit.isconstant(ll_builder.current_pos) and jit.isconstant(ll_builder.current_end) and size <= (ll_builder.current_end - ll_builder.current_pos) and size <= 16): pos = ll_builder.current_pos buf = ll_builder.current_buf stop = pos + size ll_builder.current_pos = stop while pos < stop: buf.chars[pos] = ll_str.chars[start] pos += 1 start += 1 return True # turn appends of length 1 into ll_append_char(). if size == 1: ll_append_char(ll_builder, ll_str.chars[start]) return True # turn appends of length 2 to 10 into residual calls to # specialized functions, for the lengths 2 to 10, where # gcc will optimize the known-length copy_string_contents() # as much as possible. for func0, funcstart, for_size in unroll_func_for_size: if size == for_size: if jit.isconstant(start) and start == 0: func0(ll_builder, ll_str) else: funcstart(ll_builder, ll_str, start) return True return False # use the fall-back path
def pushNewArrayBytecode(self, interp, current_bytecode, descriptor): arraySize, popIntoArray = splitter[7, 1](descriptor) newArray = None if popIntoArray == 1: if jit.we_are_jitted() and jit.isconstant( arraySize ) and arraySize < vmconstants.LITERAL_LIST_UNROLL_SIZE: newArray = interp.space.wrap_list_unroll_safe( self.pop_and_return_n(arraySize)) else: newArray = interp.space.wrap_list( self.pop_and_return_n(arraySize)) else: newArray = interp.space.w_Array.as_class_get_shadow( interp.space).new(arraySize) self.push(newArray)
def text_w(self, space): try: identifier = jit.conditional_call_elidable(self._utf8, g_encode_utf8, self._value) except SurrogateError as e: raise OperationError( space.w_UnicodeEncodeError, space.newtuple([ space.newtext('utf-8'), self, space.newint(e.index - 1), space.newint(e.index), space.newtext("surrogates not allowed") ])) if not jit.isconstant(self): self._utf8 = identifier return identifier
def __init__(self, space, args_w, keywords=None, keywords_w=None, w_stararg=None, w_starstararg=None, keyword_names_w=None): self.space = space assert isinstance(args_w, list) self.arguments_w = args_w self.keywords = keywords self.keywords_w = keywords_w self.keyword_names_w = keyword_names_w # matches the tail of .keywords if keywords is not None: assert keywords_w is not None assert len(keywords_w) == len(keywords) assert (keyword_names_w is None or len(keyword_names_w) <= len(keywords)) make_sure_not_resized(self.keywords) make_sure_not_resized(self.keywords_w) make_sure_not_resized(self.arguments_w) self._combine_wrapped(w_stararg, w_starstararg) # a flag that specifies whether the JIT can unroll loops that operate # on the keywords self._jit_few_keywords = self.keywords is None or jit.isconstant(len(self.keywords))
def ffi_type(self, w_x, accept): space = self.space if (accept & ACCEPT_STRING) and (space.isinstance_w(w_x, space.w_unicode)): string = space.str_w(w_x) consider_fn_as_fnptr = (accept & CONSIDER_FN_AS_FNPTR) != 0 if jit.isconstant(string): try: return self.get_string_to_type(string, consider_fn_as_fnptr) except KeyError: pass return self.parse_string_to_type(string, consider_fn_as_fnptr) if (accept & ACCEPT_CTYPE) and isinstance(w_x, W_CType): return w_x if (accept & ACCEPT_CDATA) and isinstance(w_x, W_CData): return w_x.ctype # m1 = "string" if accept & ACCEPT_STRING else "" m2 = "ctype object" if accept & ACCEPT_CTYPE else "" m3 = "cdata object" if accept & ACCEPT_CDATA else "" s12 = " or " if m1 and (m2 or m3) else "" s23 = " or " if m2 and m3 else "" raise oefmt(space.w_TypeError, "expected a %s%s%s%s%s, got '%T'", m1, s12, m2, s23, m3, w_x)
def _rshift(space, a, b): if r_uint(b) >= LONG_BIT: # not (0 <= b < LONG_BIT) if b < 0: raise oefmt(space.w_ValueError, "negative shift count") # b >= LONG_BIT if a == 0: return wrapint(space, a) a = -1 if a < 0 else 0 else: a = a >> b return wrapint(space, a) @jit.look_inside_iff(lambda space, iv, iw, iz: jit.isconstant(iw) and jit.isconstant(iz)) def _pow(space, iv, iw, iz): """Helper for pow""" if iw < 0: if iz != 0: raise oefmt(space.w_TypeError, "pow() 2nd argument cannot be negative when 3rd " "argument specified") # bounce it, since it always returns float raise ValueError temp = iv ix = 1 while iw > 0: if iw & 1: ix = ovfcheck(ix * temp) iw >>= 1 # Shift exponent down by 1 bit
class FormatIterator(object): """ An iterator-like object that follows format strings step by step. It provides input to the packer/unpacker and accumulates their output. The subclasses are specialized for either packing, unpacking, or just computing the size. """ _mixin_ = True _operate_is_specialized_ = False @jit.look_inside_iff(lambda self, fmt: jit.isconstant(fmt)) def interpret(self, fmt): # decode the byte order, size and alignment based on the 1st char table = unroll_native_fmtdescs self.bigendian = native_is_bigendian index = 0 if len(fmt) > 0: c = fmt[0] index = 1 if c == '@': pass elif c == '=': table = unroll_standard_fmtdescs elif c == '<': table = unroll_standard_fmtdescs self.bigendian = False elif c == '>' or c == '!': table = unroll_standard_fmtdescs self.bigendian = True else: index = 0 # interpret the format string, # calling self.operate() for each format unit while index < len(fmt): c = fmt[index] index += 1 if c.isspace(): continue if c.isdigit(): repetitions = ord(c) - ord('0') while True: if index == len(fmt): raise StructError("incomplete struct format") c = fmt[index] index += 1 if not c.isdigit(): break try: repetitions = ovfcheck(repetitions * 10) repetitions = ovfcheck(repetitions + (ord(c) - ord('0'))) except OverflowError: raise StructError("overflow in item count") assert repetitions >= 0 else: repetitions = 1 for fmtdesc in table: if c == fmtdesc.fmtchar: if self._operate_is_specialized_: if fmtdesc.alignment > 1: self.align(fmtdesc.mask) self.operate(fmtdesc, repetitions) break else: if c == '\0': raise StructError("embedded null character") raise StructError("bad char in struct format") if not self._operate_is_specialized_: if fmtdesc.alignment > 1: self.align(fmtdesc.mask) self.operate(fmtdesc, repetitions) self.finished() def finished(self): pass
class BaseTransform(object): pass class ViewTransform(BaseTransform): def __init__(self, chunks): # 4-tuple specifying slicing self.chunks = chunks class BroadcastTransform(BaseTransform): def __init__(self, res_shape): self.res_shape = res_shape @jit.look_inside_iff(lambda chunks: jit.isconstant(len(chunks))) def enumerate_chunks(chunks): result = [] i = -1 for chunk in chunks: i += chunk.axis_step result.append((i, chunk)) return result @jit.look_inside_iff(lambda shape, start, strides, backstrides, chunks: jit.isconstant(len(chunks))) def calculate_slice_strides(shape, start, strides, backstrides, chunks): size = 0 for chunk in chunks: if chunk.step != 0:
# The maximal length of RPython lists is bounded by the assumption that # we can never allocate arrays more than sys.maxint bytes in size. # Our arrays have a length and some GC headers, so a list of characters # could come near sys.maxint in length (but not reach it). A list of # pointers could only come near sys.maxint/sizeof(void*) elements. There # is the list of Voids that could reach exactly sys.maxint elements, # but for now let's ignore this case -- the reasoning is that even if # the length of a Void list overflows, nothing bad memory-wise can be # done with it. So in the sequel we don't bother checking for overflow # when we compute "ll_length() + 1". # jit note: this is normally special-cased by the oopspec, # but if item != const(0), then the special-casing fails and # we fall back to the look_inside_iff. @jit.look_inside_iff(lambda LIST, count, item: jit.isconstant(count) and count < 137) @jit.oopspec("newlist(count, item)") def ll_alloc_and_set(LIST, count, item): if count < 0: count = 0 l = LIST.ll_newlist(count) T = typeOf(item) if T is Char or T is UniChar: check = ord(item) elif isinstance(T, Number): check = widen(item) else: check = item # as long as malloc is known to zero the allocated memory avoid zeroing # twice if jit.we_are_jitted() or (not malloc_zero_filled) or check:
def slice_w(space, ctx, start, end, w_default): if 0 <= start <= end: if isinstance(ctx, rsre_core.BufMatchContext): return space.newbytes(ctx._buffer.getslice(start, end, 1, end-start)) if isinstance(ctx, rsre_core.StrMatchContext): return space.newbytes(ctx._string[start:end]) elif isinstance(ctx, rsre_core.UnicodeMatchContext): return space.newunicode(ctx._unicodestr[start:end]) else: # unreachable raise SystemError return w_default @jit.look_inside_iff(lambda ctx, num_groups: jit.isconstant(num_groups)) def do_flatten_marks(ctx, num_groups): # Returns a list of RPython-level integers. # Unlike the app-level groups() method, groups are numbered from 0 # and the returned list does not start with the whole match range. if num_groups == 0: return None result = [-1] * (2 * num_groups) mark = ctx.match_marks while mark is not None: index = jit.promote(mark.gid) if result[index] == -1: result[index] = mark.position mark = mark.prev return result
return 'FixedSizeListR %s' % (self.item_repr.compact_repr(),) def prepare_const(self, n): result = malloc(self.LIST, n, immortal=True) return result # ____________________________________________________________ # # Low-level methods. These can be run for testing, but are meant to # be direct_call'ed from rtyped flow graphs, which means that they will # get flowed and annotated, mostly with SomePtr. # adapted C code @jit.look_inside_iff(lambda l, newsize, overallocate: jit.isconstant(len(l.items)) and jit.isconstant(newsize)) @signature(types.any(), types.int(), types.bool(), returns=types.none()) def _ll_list_resize_hint_really(l, newsize, overallocate): """ Ensure l.items has room for at least newsize elements. Note that l.items may change, and even if newsize is less than l.length on entry. """ # This over-allocates proportional to the list size, making room # for additional growth. The over-allocation is mild, but is # enough to give linear-time amortized behavior over a long # sequence of appends() in the presence of a poorly-performing # system malloc(). # The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... if newsize <= 0: ll_assert(newsize == 0, "negative list length")
def f(n): assert isconstant(n) is False l = [] l.append(n) return len(l)
@unwrap_spec(depth=int) def _getframe(space, depth=0): """Return a frame object from the call stack. If optional integer depth is given, return the frame object that many calls below the top of the stack. If that is deeper than the call stack, ValueError is raised. The default for depth is zero, returning the frame at the top of the call stack. This function should be used for internal and specialized purposes only.""" if depth < 0: raise OperationError(space.w_ValueError, space.wrap("frame index must not be negative")) return getframe(space, depth) @jit.look_inside_iff(lambda space, depth: jit.isconstant(depth)) def getframe(space, depth): ec = space.getexecutioncontext() f = ec.gettopframe_nohidden() while True: if f is None: raise OperationError(space.w_ValueError, space.wrap("call stack is not deep enough")) if depth == 0: f.mark_as_escaped() return space.wrap(f) depth -= 1 f = ec.getnextframe_nohidden(f) @unwrap_spec(new_limit="c_int")
def _compare(self, w_left, w_right, strict=False, ignore_order=False): w_left = w_left.deref() w_right = w_right.deref() left_tp = w_left.tp right_tp = w_right.tp if strict: if left_tp != right_tp: return 1 if(left_tp == self.tp_float and right_tp == self.tp_float): return my_cmp(self.float_w(w_left), self.float_w(w_right), ignore_order) if(left_tp == self.tp_int and right_tp == self.tp_float): return my_cmp(self.float_w(w_left), self.float_w(w_right), ignore_order) if(left_tp == self.tp_float and right_tp == self.tp_int): return my_cmp(self.float_w(w_left), self.float_w(w_right), ignore_order) elif(left_tp == self.tp_int and right_tp == self.tp_int): return my_cmp(self.int_w(w_left), self.int_w(w_right), ignore_order) elif(left_tp == self.tp_array and right_tp == self.tp_array): return self._compare_array(w_left, w_right, strict) elif(left_tp == self.tp_null and right_tp == self.tp_null): return 0 elif(left_tp == self.tp_null and right_tp == self.tp_bool): if self.is_true(w_right): return -1 return 0 elif(left_tp == self.tp_bool and right_tp == self.tp_null): if self.is_true(w_left): return 1 return 0 elif(left_tp == self.tp_bool and right_tp == self.tp_bool): return my_cmp(self.is_true(w_left), self.is_true(w_right), ignore_order) elif(left_tp == self.tp_str and right_tp == self.tp_str): left = self.str_w(w_left) right = self.str_w(w_right) if not strict: # a small optimimization first, if both are single-char left_length = len(left) right_length = len(right) if (jit.isconstant(left_length) and left_length == 1 and jit.isconstant(right_length) and right_length == 1): return my_cmp(ord(left[0]), ord(right[0]), ignore_order) # w_right_num, right_valid = convert_string_to_number(right) if right_valid: w_left_num, left_valid = convert_string_to_number(left) if left_valid: return self._compare(w_left_num, w_right_num, ignore_order=ignore_order) return my_cmp(left, right, ignore_order) elif(left_tp == self.tp_null and right_tp == self.tp_str): return my_cmp("", self.str_w(w_right), ignore_order) elif(left_tp == self.tp_str and right_tp == self.tp_null): return my_cmp(self.str_w(w_left), "", ignore_order) elif(left_tp == self.tp_object and right_tp == self.tp_null): return 1 elif(left_tp == self.tp_null and right_tp == self.tp_object): return -1 elif(left_tp == self.tp_object and right_tp == self.tp_object): return w_left.compare(w_right, self, strict) else: if(left_tp == self.tp_null): if self.is_true(w_right): return -1 return 0 elif(right_tp == self.tp_null): if self.is_true(w_left): return 1 return 0 elif(left_tp == self.tp_bool or right_tp == self.tp_bool): return my_cmp(self.is_true(w_left), self.is_true(w_right), ignore_order) elif(left_tp == self.tp_array): return 1 elif(right_tp == self.tp_array): return -1 elif(left_tp == self.tp_object): return 1 elif(right_tp == self.tp_object): return -1 else: return self._compare(self.as_number(w_left), self.as_number(w_right), ignore_order=ignore_order) raise NotImplementedError()
fmt = args[0] if not isinstance(fmt, values_string.W_String): raise SchemeException("printf: expected a format string, got something else") return do_print(format(fmt, args[1:], "printf"), None, env, cont) @expose("eprintf", simple=False) def eprintf(args, env, cont): if not args: raise SchemeException("eprintf: expected at least one argument, got 0") fmt = args[0] if not isinstance(fmt, values_string.W_String): raise SchemeException("eprintf: expected a format string, got something else") return do_print(format(fmt, args[1:], "eprintf"), current_error_param.get(cont), env, cont) @expose("format") @jit.look_inside_iff(lambda args: jit.isconstant(args[0])) def do_format(args): if len(args) == 0: raise SchemeException("format: expects format string") fmt = args[0] if not isinstance(fmt, values_string.W_String): raise SchemeException("format: expected a format string, got something else") vals = args[1:] return values_string.W_String.fromstr_utf8(format(fmt, vals, "format")) @expose("fprintf", simple=False) def do_fprintf(args, env, cont): out, form, v = args[0], args[1], args[2:] assert isinstance(out, values.W_OutputPort) assert isinstance(form, values_string.W_String) out.write(format(form, v, "fprintf"))