[pypy-commit] pypy default: (fijal, arigo) merge optresult-unroll - this branch improves warmup by about
fijal
noreply at buildbot.pypy.org
Tue Sep 8 15:11:53 CEST 2015
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch:
Changeset: r79543:3c45f447b1e3
Date: 2015-09-08 15:11 +0200
http://bitbucket.org/pypy/pypy/changeset/3c45f447b1e3/
Log: (fijal, arigo) merge optresult-unroll - this branch improves warmup
by about 20% by changing the underlaying structure of the
ResOperations by killing Boxes. It also rewrites unrolling to
something (hopefully) a bit saner
diff too long, truncating to 2000 out of 44326 lines
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -341,8 +341,8 @@
def jitpolicy(self, driver):
from pypy.module.pypyjit.policy import PyPyJitPolicy
- from pypy.module.pypyjit.hooks import pypy_hooks
- return PyPyJitPolicy(pypy_hooks)
+ #from pypy.module.pypyjit.hooks import pypy_hooks
+ return PyPyJitPolicy()#pypy_hooks)
def get_entry_point(self, config):
from pypy.tool.lib_pypy import import_from_lib_pypy
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -111,7 +111,6 @@
'interp_magic.mapdict_cache_counter')
PYC_MAGIC = get_pyc_magic(self.space)
self.extra_interpdef('PYC_MAGIC', 'space.wrap(%d)' % PYC_MAGIC)
- #
try:
from rpython.jit.backend import detect_cpu
model = detect_cpu.autodetect()
@@ -121,7 +120,7 @@
raise
else:
pass # ok fine to ignore in this case
- #
+
if self.space.config.translation.jit:
features = detect_cpu.getcpufeatures(model)
self.extra_interpdef('jit_backend_features',
diff --git a/pypy/module/pypyjit/__init__.py b/pypy/module/pypyjit/__init__.py
--- a/pypy/module/pypyjit/__init__.py
+++ b/pypy/module/pypyjit/__init__.py
@@ -8,16 +8,16 @@
'set_param': 'interp_jit.set_param',
'residual_call': 'interp_jit.residual_call',
'not_from_assembler': 'interp_jit.W_NotFromAssembler',
- 'set_compile_hook': 'interp_resop.set_compile_hook',
- 'set_optimize_hook': 'interp_resop.set_optimize_hook',
- 'set_abort_hook': 'interp_resop.set_abort_hook',
- 'get_stats_snapshot': 'interp_resop.get_stats_snapshot',
- 'enable_debug': 'interp_resop.enable_debug',
- 'disable_debug': 'interp_resop.disable_debug',
- 'ResOperation': 'interp_resop.WrappedOp',
- 'DebugMergePoint': 'interp_resop.DebugMergePoint',
- 'JitLoopInfo': 'interp_resop.W_JitLoopInfo',
- 'Box': 'interp_resop.WrappedBox',
+ #'set_compile_hook': 'interp_resop.set_compile_hook',
+ #'set_optimize_hook': 'interp_resop.set_optimize_hook',
+ #'set_abort_hook': 'interp_resop.set_abort_hook',
+ #'get_stats_snapshot': 'interp_resop.get_stats_snapshot',
+ #'enable_debug': 'interp_resop.enable_debug',
+ #'disable_debug': 'interp_resop.disable_debug',
+ #'ResOperation': 'interp_resop.WrappedOp',
+ #'DebugMergePoint': 'interp_resop.DebugMergePoint',
+ #'JitLoopInfo': 'interp_resop.W_JitLoopInfo',
+ #'Box': 'interp_resop.WrappedBox',
'PARAMETER_DOCS': 'space.wrap(rpython.rlib.jit.PARAMETER_DOCS)',
}
diff --git a/pypy/module/pypyjit/interp_resop.py b/pypy/module/pypyjit/interp_resop.py
--- a/pypy/module/pypyjit/interp_resop.py
+++ b/pypy/module/pypyjit/interp_resop.py
@@ -8,7 +8,7 @@
from rpython.rtyper.lltypesystem import lltype
from rpython.rtyper.annlowlevel import cast_base_ptr_to_instance, hlstr
from rpython.rtyper.rclass import OBJECT
-from rpython.jit.metainterp.resoperation import rop
+#from rpython.jit.metainterp.resoperation import rop
from rpython.rlib.nonconst import NonConstant
from rpython.rlib import jit_hooks
from rpython.rlib.jit import Counters
diff --git a/pypy/tool/pypyjit.py b/pypy/tool/pypyjit.py
--- a/pypy/tool/pypyjit.py
+++ b/pypy/tool/pypyjit.py
@@ -14,6 +14,9 @@
print >> sys.stderr, __doc__
sys.exit(2)
+import sys
+sys.setrecursionlimit(100000000)
+
from pypy.objspace.std import Space
from rpython.config.translationoption import set_opt_level
from pypy.config.pypyoption import get_pypy_config, set_pypy_opt_level
@@ -22,6 +25,7 @@
from rpython.rtyper.lltypesystem import lltype
from pypy.interpreter.pycode import PyCode
from rpython.translator.goal import unixcheckpoint
+import pypy.module.pypyjit.interp_jit
config = get_pypy_config(translating=True)
config.translation.backendopt.inline_threshold = 0.1
@@ -33,6 +37,8 @@
config.objspace.usemodules.pypyjit = True
config.objspace.usemodules.array = False
config.objspace.usemodules._weakref = False
+config.objspace.usemodules.struct = True
+config.objspace.usemodules.time = True
config.objspace.usemodules._sre = False
config.objspace.usemodules._lsprof = False
#
@@ -73,6 +79,7 @@
read_code_ptr = llhelper(FPTR, read_code)
def entry_point():
+ space.startup()
from pypy.module.marshal.interp_marshal import loads
code = loads(space, space.wrap(hlstr(read_code_ptr())))
assert isinstance(code, PyCode)
diff --git a/pypy/tool/pypyjit_demo.py b/pypy/tool/pypyjit_demo.py
--- a/pypy/tool/pypyjit_demo.py
+++ b/pypy/tool/pypyjit_demo.py
@@ -1,8 +1,31 @@
-def f():
- i = 0
- while i < 1303:
- i += 1
- return i
+import time
+l = []
-f()
+for i in range(100):
+ print i
+ t0 = time.time()
+ exec """
+def k(a, b, c):
+ pass
+
+def g(a, b, c):
+ k(a, b + 1, c + 2)
+ k(a, b + 1, c + 2)
+ k(a, b + 1, c + 2)
+ k(a, b + 1, c + 2)
+ k(a, b + 1, c + 2)
+
+def f(i):
+ g(i, i + 1, i + 2)
+ g(i, i + 1, i + 2)
+ g(i, i + 1, i + 2)
+ g(i, i + 1, i + 2)
+ g(i, i + 1, i + 2)
+ g(i, i + 1, i + 2)
+for i in range(1000):
+ f(i)
+"""
+ l.append(time.time() - t0)
+
+print l
diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
--- a/rpython/jit/backend/arm/assembler.py
+++ b/rpython/jit/backend/arm/assembler.py
@@ -708,7 +708,7 @@
self.fixup_target_tokens(rawstart)
self.update_frame_depth(frame_depth)
if logger:
- logger.log_bridge(inputargs, operations, "rewritten",
+ logger.log_bridge(inputargs, operations, "rewritten", faildescr,
ops_offset=ops_offset)
self.teardown()
@@ -935,9 +935,9 @@
op = operations[i]
self.mc.mark_op(op)
opnum = op.getopnum()
- if op.has_no_side_effect() and op.result not in regalloc.longevity:
+ if op.has_no_side_effect() and op not in regalloc.longevity:
regalloc.possibly_free_vars_for_op(op)
- elif not we_are_translated() and op.getopnum() == -124:
+ elif not we_are_translated() and op.getopnum() == -127:
regalloc.prepare_force_spill(op, fcond)
else:
arglocs = regalloc_operations[opnum](regalloc, op, fcond)
@@ -947,8 +947,8 @@
assert fcond is not None
if op.is_guard():
regalloc.possibly_free_vars(op.getfailargs())
- if op.result:
- regalloc.possibly_free_var(op.result)
+ if op.type != 'v':
+ regalloc.possibly_free_var(op)
regalloc.possibly_free_vars_for_op(op)
regalloc.free_temp_vars()
regalloc._check_invariants()
diff --git a/rpython/jit/backend/arm/helper/assembler.py b/rpython/jit/backend/arm/helper/assembler.py
--- a/rpython/jit/backend/arm/helper/assembler.py
+++ b/rpython/jit/backend/arm/helper/assembler.py
@@ -2,7 +2,7 @@
from rpython.jit.backend.arm import conditions as c
from rpython.jit.backend.arm import registers as r
from rpython.jit.backend.arm.codebuilder import InstrBuilder
-from rpython.jit.metainterp.history import ConstInt, BoxInt, FLOAT
+from rpython.jit.metainterp.history import FLOAT
from rpython.rlib.rarithmetic import r_uint, r_longlong, intmask
from rpython.jit.metainterp.resoperation import rop
@@ -50,7 +50,7 @@
helper = getattr(InstrBuilder, opname)
def f(self, op, arglocs, regalloc, fcond):
assert fcond is not None
- if op.result:
+ if op.type != 'v':
regs = r.caller_resp[1:] + [r.ip]
else:
regs = r.caller_resp
diff --git a/rpython/jit/backend/arm/helper/regalloc.py b/rpython/jit/backend/arm/helper/regalloc.py
--- a/rpython/jit/backend/arm/helper/regalloc.py
+++ b/rpython/jit/backend/arm/helper/regalloc.py
@@ -1,14 +1,13 @@
from rpython.jit.backend.arm import conditions as c
from rpython.jit.backend.arm import registers as r
-from rpython.jit.metainterp.history import ConstInt, BoxInt, Box, FLOAT
-from rpython.jit.metainterp.history import ConstInt
+from rpython.jit.metainterp.history import Const, ConstInt, FLOAT
from rpython.rlib.objectmodel import we_are_translated
VMEM_imm_size=0x3FC
default_imm_size=0xFF
def check_imm_arg(arg, size=default_imm_size, allow_zero=True):
- assert not isinstance(arg, ConstInt)
+ assert not isinstance(arg, Const) # because it must be an int :-)
if not we_are_translated():
if not isinstance(arg, int):
import pdb; pdb.set_trace()
@@ -44,7 +43,7 @@
l1 = self.make_sure_var_in_reg(a1, boxes)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg(op.result, boxes)
+ res = self.force_allocate_reg(op, boxes)
return [l0, l1, res]
if name:
f.__name__ = name
@@ -54,7 +53,7 @@
loc1 = self.make_sure_var_in_reg(op.getarg(0))
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg(op.result)
+ res = self.force_allocate_reg(op)
return [loc1, res]
def prepare_two_regs_op(self, op, fcond):
@@ -62,7 +61,7 @@
loc2 = self.make_sure_var_in_reg(op.getarg(1))
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg(op.result)
+ res = self.force_allocate_reg(op)
return [loc1, loc2, res]
def prepare_float_cmp(self, op, fcond):
@@ -70,7 +69,7 @@
loc2 = self.make_sure_var_in_reg(op.getarg(1))
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg_or_cc(op.result)
+ res = self.force_allocate_reg_or_cc(op)
return [loc1, loc2, res]
def prepare_op_by_helper_call(name):
@@ -82,12 +81,12 @@
arg2 = self.rm.make_sure_var_in_reg(a1, selected_reg=r.r1)
assert arg1 == r.r0
assert arg2 == r.r1
- if isinstance(a0, Box) and self.stays_alive(a0):
+ if not isinstance(a0, Const) and self.stays_alive(a0):
self.force_spill_var(a0)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- self.after_call(op.result)
- self.possibly_free_var(op.result)
+ self.after_call(op)
+ self.possibly_free_var(op)
return []
f.__name__ = name
return f
@@ -106,14 +105,14 @@
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg_or_cc(op.result)
+ res = self.force_allocate_reg_or_cc(op)
return [l0, l1, res]
def prepare_unary_cmp(self, op, fcond):
assert fcond is not None
a0 = op.getarg(0)
- assert isinstance(a0, Box)
+ assert not isinstance(a0, Const)
reg = self.make_sure_var_in_reg(a0)
self.possibly_free_vars_for_op(op)
- res = self.force_allocate_reg_or_cc(op.result)
+ res = self.force_allocate_reg_or_cc(op)
return [reg, res]
diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -15,20 +15,21 @@
from rpython.jit.backend.arm.helper.regalloc import VMEM_imm_size
from rpython.jit.backend.arm.codebuilder import InstrBuilder, OverwritingBuilder
from rpython.jit.backend.arm.jump import remap_frame_layout
-from rpython.jit.backend.arm.regalloc import TempBox
+from rpython.jit.backend.arm.regalloc import TempVar
from rpython.jit.backend.arm.locations import imm, RawSPStackLocation
from rpython.jit.backend.llsupport import symbolic
from rpython.jit.backend.llsupport.gcmap import allocate_gcmap
from rpython.jit.backend.llsupport.descr import InteriorFieldDescr
from rpython.jit.backend.llsupport.assembler import GuardToken, BaseAssembler
from rpython.jit.backend.llsupport.regalloc import get_scale
-from rpython.jit.metainterp.history import (Box, AbstractFailDescr, ConstInt,
+from rpython.jit.metainterp.history import (AbstractFailDescr, ConstInt,
INT, FLOAT, REF)
from rpython.jit.metainterp.history import TargetToken
from rpython.jit.metainterp.resoperation import rop
from rpython.rlib.objectmodel import we_are_translated
from rpython.rtyper.lltypesystem import rstr, rffi, lltype
from rpython.rtyper.annlowlevel import cast_instance_to_gcref
+from rpython.rtyper import rclass
from rpython.jit.backend.arm import callbuilder
from rpython.rlib.rarithmetic import r_uint
@@ -49,6 +50,8 @@
def emit_op_int_add(self, op, arglocs, regalloc, fcond):
return self.int_add_impl(op, arglocs, regalloc, fcond)
+ emit_op_nursery_ptr_increment = emit_op_int_add
+
def int_add_impl(self, op, arglocs, regalloc, fcond, flags=False):
l0, l1, res = arglocs
if flags:
@@ -253,28 +256,105 @@
def emit_op_guard_class(self, op, arglocs, regalloc, fcond):
self._cmp_guard_class(op, arglocs, regalloc, fcond)
self.guard_success_cc = c.EQ
- self._emit_guard(op, arglocs[3:], save_exc=False)
+ self._emit_guard(op, arglocs[2:], save_exc=False)
return fcond
def emit_op_guard_nonnull_class(self, op, arglocs, regalloc, fcond):
self.mc.CMP_ri(arglocs[0].value, 1)
self._cmp_guard_class(op, arglocs, regalloc, c.HS)
self.guard_success_cc = c.EQ
- self._emit_guard(op, arglocs[3:], save_exc=False)
+ self._emit_guard(op, arglocs[2:], save_exc=False)
return fcond
def _cmp_guard_class(self, op, locs, regalloc, fcond):
- offset = locs[2]
+ offset = self.cpu.vtable_offset
if offset is not None:
- self.mc.LDR_ri(r.ip.value, locs[0].value, offset.value, cond=fcond)
- self.mc.CMP_rr(r.ip.value, locs[1].value, cond=fcond)
+ self.mc.LDR_ri(r.ip.value, locs[0].value, offset, cond=fcond)
+ self.mc.gen_load_int(r.lr.value, locs[1].value, cond=fcond)
+ self.mc.CMP_rr(r.ip.value, r.lr.value, cond=fcond)
else:
- typeid = locs[1]
- self.mc.LDRH_ri(r.ip.value, locs[0].value, cond=fcond)
- if typeid.is_imm():
- self.mc.CMP_ri(r.ip.value, typeid.value, cond=fcond)
- else:
- self.mc.CMP_rr(r.ip.value, typeid.value, cond=fcond)
+ expected_typeid = (self.cpu.gc_ll_descr
+ .get_typeid_from_classptr_if_gcremovetypeptr(locs[1].value))
+ self._cmp_guard_gc_type(locs[0], expected_typeid, fcond)
+
+ def _cmp_guard_gc_type(self, loc_ptr, expected_typeid, fcond=c.AL):
+ # Note that the typeid half-word is at offset 0 on a little-endian
+ # machine; it would be at offset 2 or 4 on a big-endian machine.
+ assert self.cpu.supports_guard_gc_type
+ self.mc.LDRH_ri(r.ip.value, loc_ptr.value, cond=fcond)
+ self.mc.gen_load_int(r.lr.value, expected_typeid, cond=fcond)
+ self.mc.CMP_rr(r.ip.value, r.lr.value, cond=fcond)
+
+ def emit_op_guard_gc_type(self, op, arglocs, regalloc, fcond):
+ self._cmp_guard_gc_type(arglocs[0], arglocs[1].value, fcond)
+ self.guard_success_cc = c.EQ
+ self._emit_guard(op, arglocs[2:], save_exc=False)
+ return fcond
+
+ def emit_op_guard_is_object(self, op, arglocs, regalloc, fcond):
+ assert self.cpu.supports_guard_gc_type
+ loc_object = arglocs[0]
+ # idea: read the typeid, fetch one byte of the field 'infobits' from
+ # the big typeinfo table, and check the flag 'T_IS_RPYTHON_INSTANCE'.
+ self.mc.LDRH_ri(r.ip.value, loc_object.value)
+ #
+ base_type_info, shift_by, sizeof_ti = (
+ self.cpu.gc_ll_descr.get_translated_info_for_typeinfo())
+ infobits_offset, IS_OBJECT_FLAG = (
+ self.cpu.gc_ll_descr.get_translated_info_for_guard_is_object())
+
+ self.mc.gen_load_int(r.lr.value, base_type_info + infobits_offset)
+ if shift_by > 0:
+ self.mc.LSL_ri(r.ip.value, r.ip.value, shift_by)
+ self.mc.LDRB_rr(r.ip.value, r.ip.value, r.lr.value)
+ self.mc.TST_ri(r.ip.value, imm=(IS_OBJECT_FLAG & 0xff))
+ self.guard_success_cc = c.NE
+ self._emit_guard(op, arglocs[1:], save_exc=False)
+ return fcond
+
+ def emit_op_guard_subclass(self, op, arglocs, regalloc, fcond):
+ assert self.cpu.supports_guard_gc_type
+ loc_object = arglocs[0]
+ loc_check_against_class = arglocs[1]
+ offset = self.cpu.vtable_offset
+ offset2 = self.cpu.subclassrange_min_offset
+ if offset is not None:
+ # read this field to get the vtable pointer
+ self.mc.LDR_ri(r.ip.value, loc_object.value, offset)
+ # read the vtable's subclassrange_min field
+ self.mc.LDR_ri(r.ip.value, r.ip.value, offset2)
+ else:
+ # read the typeid
+ self.mc.LDRH_ri(r.ip.value, loc_object.value)
+ # read the vtable's subclassrange_min field, as a single
+ # step with the correct offset
+ base_type_info, shift_by, sizeof_ti = (
+ self.cpu.gc_ll_descr.get_translated_info_for_typeinfo())
+
+ self.mc.gen_load_int(r.lr.value,
+ base_type_info + sizeof_ti + offset2)
+ if shift_by > 0:
+ self.mc.LSL_ri(r.ip.value, r.ip.value, shift_by)
+ self.mc.LDR_rr(r.ip.value, r.ip.value, r.lr.value)
+ # get the two bounds to check against
+ vtable_ptr = loc_check_against_class.getint()
+ vtable_ptr = rffi.cast(rclass.CLASSTYPE, vtable_ptr)
+ check_min = vtable_ptr.subclassrange_min
+ check_max = vtable_ptr.subclassrange_max
+ assert check_max > check_min
+ check_diff = check_max - check_min - 1
+ # check by doing the unsigned comparison (tmp - min) < (max - min)
+ self.mc.gen_load_int(r.lr.value, check_min)
+ self.mc.SUB_rr(r.ip.value, r.ip.value, r.lr.value)
+ if check_diff <= 0xff:
+ self.mc.CMP_ri(r.ip.value, check_diff)
+ else:
+ self.mc.gen_load_int(r.lr.value, check_diff)
+ self.mc.CMP_rr(r.ip.value, r.lr.value)
+ # the guard passes if we get a result of "below or equal"
+ self.guard_success_cc = c.LS
+ self._emit_guard(op, arglocs[2:], save_exc=False)
+ return fcond
def emit_op_guard_not_invalidated(self, op, locs, regalloc, fcond):
return self._emit_guard(op, locs, save_exc=False,
@@ -365,8 +445,12 @@
self.gen_func_epilog()
return fcond
- def emit_op_call(self, op, arglocs, regalloc, fcond):
+ def _genop_call(self, op, arglocs, regalloc, fcond):
return self._emit_call(op, arglocs, fcond=fcond)
+ emit_op_call_i = _genop_call
+ emit_op_call_r = _genop_call
+ emit_op_call_f = _genop_call
+ emit_op_call_n = _genop_call
def _emit_call(self, op, arglocs, is_call_release_gil=False, fcond=c.AL):
# args = [resloc, size, sign, args...]
@@ -396,14 +480,17 @@
cb.emit()
return fcond
- def emit_op_same_as(self, op, arglocs, regalloc, fcond):
+ def _genop_same_as(self, op, arglocs, regalloc, fcond):
argloc, resloc = arglocs
if argloc is not resloc:
self.mov_loc_loc(argloc, resloc)
return fcond
- emit_op_cast_ptr_to_int = emit_op_same_as
- emit_op_cast_int_to_ptr = emit_op_same_as
+ emit_op_same_as_i = _genop_same_as
+ emit_op_same_as_r = _genop_same_as
+ emit_op_same_as_f = _genop_same_as
+ emit_op_cast_ptr_to_int = _genop_same_as
+ emit_op_cast_int_to_ptr = _genop_same_as
def emit_op_guard_no_exception(self, op, arglocs, regalloc, fcond):
loc = arglocs[0]
@@ -574,16 +661,23 @@
emit_op_setfield_raw = emit_op_setfield_gc
emit_op_zero_ptr_field = emit_op_setfield_gc
- def emit_op_getfield_gc(self, op, arglocs, regalloc, fcond):
+ def _genop_getfield(self, op, arglocs, regalloc, fcond):
base_loc, ofs, res, size = arglocs
signed = op.getdescr().is_field_signed()
scale = get_scale(size.value)
self._load_from_mem(res, base_loc, ofs, imm(scale), signed, fcond)
return fcond
- emit_op_getfield_raw = emit_op_getfield_gc
- emit_op_getfield_raw_pure = emit_op_getfield_gc
- emit_op_getfield_gc_pure = emit_op_getfield_gc
+ emit_op_getfield_gc_i = _genop_getfield
+ emit_op_getfield_gc_r = _genop_getfield
+ emit_op_getfield_gc_f = _genop_getfield
+ emit_op_getfield_gc_pure_i = _genop_getfield
+ emit_op_getfield_gc_pure_r = _genop_getfield
+ emit_op_getfield_gc_pure_f = _genop_getfield
+ emit_op_getfield_raw_i = _genop_getfield
+ emit_op_getfield_raw_f = _genop_getfield
+ emit_op_getfield_raw_pure_i = _genop_getfield
+ emit_op_getfield_raw_pure_f = _genop_getfield
def emit_op_increment_debug_counter(self, op, arglocs, regalloc, fcond):
base_loc, value_loc = arglocs
@@ -592,7 +686,7 @@
self.mc.STR_ri(value_loc.value, base_loc.value, 0, cond=fcond)
return fcond
- def emit_op_getinteriorfield_gc(self, op, arglocs, regalloc, fcond):
+ def _genop_getinteriorfield(self, op, arglocs, regalloc, fcond):
(base_loc, index_loc, res_loc,
ofs_loc, ofs, itemsize, fieldsize) = arglocs
scale = get_scale(fieldsize.value)
@@ -613,6 +707,10 @@
imm(scale), signed, fcond)
return fcond
+ emit_op_getinteriorfield_gc_i = _genop_getinteriorfield
+ emit_op_getinteriorfield_gc_r = _genop_getinteriorfield
+ emit_op_getinteriorfield_gc_f = _genop_getinteriorfield
+
def emit_op_setinteriorfield_gc(self, op, arglocs, regalloc, fcond):
(base_loc, index_loc, value_loc,
ofs_loc, ofs, itemsize, fieldsize) = arglocs
@@ -697,12 +795,13 @@
self._write_to_mem(value_loc, base_loc, ofs_loc, scale, fcond)
return fcond
- def emit_op_getarrayitem_gc(self, op, arglocs, regalloc, fcond):
+ def _genop_getarrayitem(self, op, arglocs, regalloc, fcond):
res_loc, base_loc, ofs_loc, scale, ofs = arglocs
assert ofs_loc.is_core_reg()
signed = op.getdescr().is_item_signed()
# scale the offset as required
+ # XXX we should try to encode the scale inside the "shift" part of LDR
if scale.value > 0:
self.mc.LSL_ri(r.ip.value, ofs_loc.value, scale.value)
ofs_loc = r.ip
@@ -714,6 +813,17 @@
self._load_from_mem(res_loc, base_loc, ofs_loc, scale, signed, fcond)
return fcond
+ emit_op_getarrayitem_gc_i = _genop_getarrayitem
+ emit_op_getarrayitem_gc_r = _genop_getarrayitem
+ emit_op_getarrayitem_gc_f = _genop_getarrayitem
+ emit_op_getarrayitem_gc_pure_i = _genop_getarrayitem
+ emit_op_getarrayitem_gc_pure_r = _genop_getarrayitem
+ emit_op_getarrayitem_gc_pure_f = _genop_getarrayitem
+ emit_op_getarrayitem_raw_i = _genop_getarrayitem
+ emit_op_getarrayitem_raw_f = _genop_getarrayitem
+ emit_op_getarrayitem_raw_pure_i = _genop_getarrayitem
+ emit_op_getarrayitem_raw_pure_f = _genop_getarrayitem
+
def _load_from_mem(self, res_loc, base_loc, ofs_loc, scale,
signed=False, fcond=c.AL):
if scale.value == 3:
@@ -771,10 +881,7 @@
else:
assert 0
- emit_op_getarrayitem_raw = emit_op_getarrayitem_gc
- emit_op_getarrayitem_gc_pure = emit_op_getarrayitem_gc
-
- def emit_op_raw_load(self, op, arglocs, regalloc, fcond):
+ def _genop_raw_load(self, op, arglocs, regalloc, fcond):
res_loc, base_loc, ofs_loc, scale, ofs = arglocs
assert ofs_loc.is_core_reg()
# no base offset
@@ -783,6 +890,9 @@
self._load_from_mem(res_loc, base_loc, ofs_loc, scale, signed, fcond)
return fcond
+ emit_op_raw_load_i = _genop_raw_load
+ emit_op_raw_load_f = _genop_raw_load
+
def emit_op_strlen(self, op, arglocs, regalloc, fcond):
l0, l1, res = arglocs
if l1.is_imm():
@@ -833,7 +943,7 @@
base_loc = regalloc.rm.make_sure_var_in_reg(args[0], args)
ofs_loc = regalloc.rm.make_sure_var_in_reg(args[2], args)
assert args[0] is not args[1] # forbidden case of aliasing
- srcaddr_box = TempBox()
+ srcaddr_box = TempVar()
forbidden_vars = [args[1], args[3], args[4], srcaddr_box]
srcaddr_loc = regalloc.rm.force_allocate_reg(srcaddr_box, forbidden_vars)
self._gen_address_inside_string(base_loc, ofs_loc, srcaddr_loc,
@@ -842,7 +952,7 @@
base_loc = regalloc.rm.make_sure_var_in_reg(args[1], forbidden_vars)
ofs_loc = regalloc.rm.make_sure_var_in_reg(args[3], forbidden_vars)
forbidden_vars = [args[4], srcaddr_box]
- dstaddr_box = TempBox()
+ dstaddr_box = TempVar()
dstaddr_loc = regalloc.rm.force_allocate_reg(dstaddr_box, forbidden_vars)
self._gen_address_inside_string(base_loc, ofs_loc, dstaddr_loc,
is_unicode=is_unicode)
@@ -851,7 +961,7 @@
length_loc = regalloc.loc(length_box)
if is_unicode:
forbidden_vars = [srcaddr_box, dstaddr_box]
- bytes_box = TempBox()
+ bytes_box = TempVar()
bytes_loc = regalloc.rm.force_allocate_reg(bytes_box, forbidden_vars)
scale = self._get_unicode_item_scale()
if not length_loc.is_core_reg():
@@ -952,7 +1062,7 @@
def imm(self, v):
return imm(v)
- def emit_op_call_assembler(self, op, arglocs, regalloc, fcond):
+ def _genop_call_assembler(self, op, arglocs, regalloc, fcond):
if len(arglocs) == 4:
[argloc, vloc, result_loc, tmploc] = arglocs
else:
@@ -961,6 +1071,10 @@
self._store_force_index(self._find_nearby_operation(+1))
self.call_assembler(op, argloc, vloc, result_loc, tmploc)
return fcond
+ emit_op_call_assembler_i = _genop_call_assembler
+ emit_op_call_assembler_r = _genop_call_assembler
+ emit_op_call_assembler_f = _genop_call_assembler
+ emit_op_call_assembler_n = _genop_call_assembler
def _call_assembler_emit_call(self, addr, argloc, resloc):
ofs = self.saved_threadlocal_addr
@@ -991,9 +1105,9 @@
return pos
def _call_assembler_load_result(self, op, result_loc):
- if op.result is not None:
+ if op.type != 'v':
# load the return value from (tmploc, 0)
- kind = op.result.type
+ kind = op.type
descr = self.cpu.getarraydescr_for_frame(kind)
if kind == FLOAT:
ofs = self.cpu.unpack_arraydescr(descr)
@@ -1041,15 +1155,23 @@
self._emit_guard(op, arglocs, save_exc=True, is_guard_not_forced=True)
return fcond
- def emit_op_call_may_force(self, op, arglocs, regalloc, fcond):
+ def _genop_call_may_force(self, op, arglocs, regalloc, fcond):
self._store_force_index(self._find_nearby_operation(+1))
self._emit_call(op, arglocs, fcond=fcond)
return fcond
+ emit_op_call_may_force_i = _genop_call_may_force
+ emit_op_call_may_force_r = _genop_call_may_force
+ emit_op_call_may_force_f = _genop_call_may_force
+ emit_op_call_may_force_n = _genop_call_may_force
- def emit_op_call_release_gil(self, op, arglocs, regalloc, fcond):
+ def _genop_call_release_gil(self, op, arglocs, regalloc, fcond):
self._store_force_index(self._find_nearby_operation(+1))
self._emit_call(op, arglocs, is_call_release_gil=True)
return fcond
+ emit_op_call_release_gil_i = _genop_call_release_gil
+ emit_op_call_release_gil_r = _genop_call_release_gil
+ emit_op_call_release_gil_f = _genop_call_release_gil
+ emit_op_call_release_gil_n = _genop_call_release_gil
def _store_force_index(self, guard_op):
assert (guard_op.getopnum() == rop.GUARD_NOT_FORCED or
@@ -1065,7 +1187,7 @@
return regalloc.operations[regalloc.rm.position + delta]
def emit_op_call_malloc_gc(self, op, arglocs, regalloc, fcond):
- self.emit_op_call(op, arglocs, regalloc, fcond)
+ self._emit_call(op, arglocs, fcond=fcond)
self.propagate_memoryerror_if_r0_is_null()
self._alignment_check()
return fcond
@@ -1183,7 +1305,7 @@
# address that we will pass as first argument to memset().
# It can be in the same register as either one, but not in
# args[2], because we're still needing the latter.
- dstaddr_box = TempBox()
+ dstaddr_box = TempVar()
dstaddr_loc = regalloc.rm.force_allocate_reg(dstaddr_box, [args[2]])
if startindex >= 0: # a constant
ofs = baseofs + startindex * itemsize
@@ -1239,7 +1361,7 @@
# we need a register that is different from dstaddr_loc,
# but which can be identical to length_loc (as usual,
# only if the length_box is not used by future operations)
- bytes_box = TempBox()
+ bytes_box = TempVar()
bytes_loc = regalloc.rm.force_allocate_reg(bytes_box,
[dstaddr_box])
self.mc.gen_load_int(r.ip.value, itemsize)
diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py
--- a/rpython/jit/backend/arm/regalloc.py
+++ b/rpython/jit/backend/arm/regalloc.py
@@ -2,7 +2,7 @@
from rpython.rlib import rgc
from rpython.rlib.debug import debug_print, debug_start, debug_stop
from rpython.jit.backend.llsupport.regalloc import FrameManager, \
- RegisterManager, TempBox, compute_vars_longevity, BaseRegalloc, \
+ RegisterManager, TempVar, compute_vars_longevity, BaseRegalloc, \
get_scale
from rpython.jit.backend.arm import registers as r
from rpython.jit.backend.arm import conditions as c
@@ -24,8 +24,7 @@
from rpython.jit.backend.arm.arch import WORD, JITFRAME_FIXED_SIZE
from rpython.jit.codewriter import longlong
from rpython.jit.metainterp.history import (Const, ConstInt, ConstFloat,
- ConstPtr, BoxInt,
- Box, BoxPtr,
+ ConstPtr,
INT, REF, FLOAT)
from rpython.jit.metainterp.history import TargetToken
from rpython.jit.metainterp.resoperation import rop
@@ -46,21 +45,21 @@
# that it is a LABEL that was not compiled yet.
TargetToken._ll_loop_code = 0
-class TempInt(TempBox):
+class TempInt(TempVar):
type = INT
def __repr__(self):
return "<TempInt at %s>" % (id(self),)
-class TempPtr(TempBox):
+class TempPtr(TempVar):
type = REF
def __repr__(self):
return "<TempPtr at %s>" % (id(self),)
-class TempFloat(TempBox):
+class TempFloat(TempVar):
type = FLOAT
def __repr__(self):
@@ -225,6 +224,8 @@
return self.rm.call_result_location(v)
def after_call(self, v):
+ if v.type == 'v':
+ return
if v.type == FLOAT:
return self.vfprm.after_call(v)
else:
@@ -434,9 +435,11 @@
locs = self._prepare_op_int_add(op, fcond)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg(op.result)
+ res = self.force_allocate_reg(op)
return locs + [res]
+ prepare_op_nursery_ptr_increment = prepare_op_int_add
+
def _prepare_op_int_sub(self, op, fcond):
a0, a1 = boxes = op.getarglist()
imm_a0 = check_imm_box(a0)
@@ -456,7 +459,7 @@
locs = self._prepare_op_int_sub(op, fcond)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg(op.result)
+ res = self.force_allocate_reg(op)
return locs + [res]
def prepare_op_int_mul(self, op, fcond):
@@ -468,19 +471,19 @@
self.possibly_free_vars(boxes)
self.possibly_free_vars_for_op(op)
- res = self.force_allocate_reg(op.result)
- self.possibly_free_var(op.result)
+ res = self.force_allocate_reg(op)
+ self.possibly_free_var(op)
return [reg1, reg2, res]
def prepare_op_int_force_ge_zero(self, op, fcond):
argloc = self.make_sure_var_in_reg(op.getarg(0))
- resloc = self.force_allocate_reg(op.result, [op.getarg(0)])
+ resloc = self.force_allocate_reg(op, [op.getarg(0)])
return [argloc, resloc]
def prepare_op_int_signext(self, op, fcond):
argloc = self.make_sure_var_in_reg(op.getarg(0))
numbytes = op.getarg(1).getint()
- resloc = self.force_allocate_reg(op.result)
+ resloc = self.force_allocate_reg(op)
return [argloc, imm(numbytes), resloc]
prepare_op_int_floordiv = prepare_op_by_helper_call('int_floordiv')
@@ -523,7 +526,7 @@
prepare_op_int_neg = prepare_unary_op
prepare_op_int_invert = prepare_unary_op
- def prepare_op_call(self, op, fcond):
+ def _prepare_op_call(self, op, fcond):
calldescr = op.getdescr()
assert calldescr is not None
effectinfo = calldescr.get_extra_info()
@@ -554,6 +557,11 @@
# ...
return self._prepare_call(op)
+ prepare_op_call_i = _prepare_op_call
+ prepare_op_call_r = _prepare_op_call
+ prepare_op_call_f = _prepare_op_call
+ prepare_op_call_n = _prepare_op_call
+
def _prepare_call(self, op, force_store=[], save_all_regs=False,
first_arg_index=1):
args = [None] * (op.numargs() + 3)
@@ -584,9 +592,7 @@
if gcrootmap and gcrootmap.is_shadow_stack:
save_all_regs = 2
self.rm.before_call(force_store, save_all_regs=save_all_regs)
- resloc = None
- if op.result:
- resloc = self.after_call(op.result)
+ resloc = self.after_call(op)
return resloc
def prepare_op_call_malloc_gc(self, op, fcond):
@@ -598,12 +604,12 @@
loc1 = self.make_sure_var_in_reg(op.getarg(2))
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.vfprm.force_allocate_reg(op.result)
+ res = self.vfprm.force_allocate_reg(op)
return [loc0, loc1, res]
def _prepare_llong_to_int(self, op, fcond):
loc0 = self.make_sure_var_in_reg(op.getarg(1))
- res = self.force_allocate_reg(op.result)
+ res = self.force_allocate_reg(op)
return [loc0, res]
def _prepare_threadlocalref_get(self, op, fcond):
@@ -611,7 +617,7 @@
calldescr = op.getdescr()
size_loc = imm(calldescr.get_result_size())
sign_loc = imm(calldescr.is_result_signed())
- res_loc = self.force_allocate_reg(op.result)
+ res_loc = self.force_allocate_reg(op)
return [ofs_loc, size_loc, sign_loc, res_loc]
def _prepare_guard(self, op, args=None):
@@ -669,7 +675,6 @@
l1 = self.make_sure_var_in_reg(a1, boxes)
else:
l1 = self.convert_to_imm(a1)
- assert op.result is None
arglocs = self._prepare_guard(op, [l0, l1])
self.possibly_free_vars(op.getarglist())
self.possibly_free_vars(op.getfailargs())
@@ -689,9 +694,9 @@
arg0 = ConstInt(rffi.cast(lltype.Signed, op.getarg(0).getint()))
loc = self.make_sure_var_in_reg(arg0)
loc1 = self.get_scratch_reg(INT, boxes)
- if op.result in self.longevity:
- resloc = self.force_allocate_reg(op.result, boxes)
- self.possibly_free_var(op.result)
+ if op in self.longevity:
+ resloc = self.force_allocate_reg(op, boxes)
+ self.possibly_free_var(op)
else:
resloc = None
pos_exc_value = imm(self.cpu.pos_exc_value())
@@ -706,55 +711,20 @@
return arglocs
def prepare_op_guard_class(self, op, fcond):
- return self._prepare_guard_class(op, fcond)
-
- prepare_op_guard_nonnull_class = prepare_op_guard_class
-
- def _prepare_guard_class(self, op, fcond):
- assert isinstance(op.getarg(0), Box)
+ assert not isinstance(op.getarg(0), Const)
boxes = op.getarglist()
x = self.make_sure_var_in_reg(boxes[0], boxes)
- y_val = rffi.cast(lltype.Signed, op.getarg(1).getint())
+ y_val = rffi.cast(lltype.Signed, boxes[1].getint())
+ return self._prepare_guard(op, [x, imm(y_val)])
- arglocs = [x, None, None]
+ prepare_op_guard_nonnull_class = prepare_op_guard_class
+ prepare_op_guard_gc_type = prepare_op_guard_class
+ prepare_op_guard_subclass = prepare_op_guard_class
- offset = self.cpu.vtable_offset
- if offset is not None:
- y = self.get_scratch_reg(INT, forbidden_vars=boxes)
- self.assembler.load(y, imm(y_val))
-
- assert check_imm_arg(offset)
- offset_loc = imm(offset)
-
- arglocs[1] = y
- arglocs[2] = offset_loc
- else:
- # XXX hard-coded assumption: to go from an object to its class
- # we use the following algorithm:
- # - read the typeid from mem(locs[0]), i.e. at offset 0
- # - keep the lower 16 bits read there
- # - multiply by 4 and use it as an offset in type_info_group
- # - add 16 bytes, to go past the TYPE_INFO structure
- classptr = y_val
- # here, we have to go back from 'classptr' to the value expected
- # from reading the 16 bits in the object header
- from rpython.memory.gctypelayout import GCData
- sizeof_ti = rffi.sizeof(GCData.TYPE_INFO)
- type_info_group = llop.gc_get_type_info_group(llmemory.Address)
- type_info_group = rffi.cast(lltype.Signed, type_info_group)
- expected_typeid = classptr - sizeof_ti - type_info_group
- expected_typeid >>= 2
- if check_imm_arg(expected_typeid):
- arglocs[1] = imm(expected_typeid)
- else:
- y = self.get_scratch_reg(INT, forbidden_vars=boxes)
- self.assembler.load(y, imm(expected_typeid))
- arglocs[1] = y
-
- return self._prepare_guard(op, arglocs)
-
- return arglocs
+ def prepare_op_guard_is_object(self, op, fcond):
+ loc_object = self.make_sure_var_in_reg(op.getarg(0))
+ return self._prepare_guard(op, [loc_object])
def compute_hint_frame_locations(self, operations):
# optimization only: fill in the 'hint_frame_locations' dictionary
@@ -782,7 +752,7 @@
assert len(arglocs) == jump_op.numargs()
for i in range(jump_op.numargs()):
box = jump_op.getarg(i)
- if isinstance(box, Box):
+ if not isinstance(box, Const):
loc = arglocs[i]
if loc is not None and loc.is_stack():
self.frame_manager.hint_frame_pos[box] = (
@@ -847,7 +817,7 @@
ofs = op.getarg(1).getint()
return self._prepare_op_setfield([a0, ConstInt(0)], ofs, WORD)
- def prepare_op_getfield_gc(self, op, fcond):
+ def _prepare_op_getfield(self, op, fcond):
a0 = op.getarg(0)
ofs, size, sign = unpack_fielddescr(op.getdescr())
base_loc = self.make_sure_var_in_reg(a0)
@@ -860,12 +830,19 @@
self.assembler.load(ofs_loc, immofs)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg(op.result)
+ res = self.force_allocate_reg(op)
return [base_loc, ofs_loc, res, imm(size)]
- prepare_op_getfield_raw = prepare_op_getfield_gc
- prepare_op_getfield_raw_pure = prepare_op_getfield_gc
- prepare_op_getfield_gc_pure = prepare_op_getfield_gc
+ prepare_op_getfield_gc_i = _prepare_op_getfield
+ prepare_op_getfield_gc_r = _prepare_op_getfield
+ prepare_op_getfield_gc_f = _prepare_op_getfield
+ prepare_op_getfield_raw_i = _prepare_op_getfield
+ prepare_op_getfield_raw_f = _prepare_op_getfield
+ prepare_op_getfield_raw_pure_i = _prepare_op_getfield
+ prepare_op_getfield_raw_pure_f = _prepare_op_getfield
+ prepare_op_getfield_gc_pure_i = _prepare_op_getfield
+ prepare_op_getfield_gc_pure_r = _prepare_op_getfield
+ prepare_op_getfield_gc_pure_f = _prepare_op_getfield
def prepare_op_increment_debug_counter(self, op, fcond):
boxes = op.getarglist()
@@ -875,7 +852,7 @@
self.free_temp_vars()
return [base_loc, value_loc]
- def prepare_op_getinteriorfield_gc(self, op, fcond):
+ def _prepare_op_getinteriorfield(self, op, fcond):
t = unpack_interiorfielddescr(op.getdescr())
ofs, itemsize, fieldsize, sign = t
args = op.getarglist()
@@ -890,10 +867,14 @@
self.assembler.load(ofs_loc, immofs)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- result_loc = self.force_allocate_reg(op.result)
+ result_loc = self.force_allocate_reg(op)
return [base_loc, index_loc, result_loc, ofs_loc, imm(ofs),
imm(itemsize), imm(fieldsize)]
+ prepare_op_getinteriorfield_gc_i = _prepare_op_getinteriorfield
+ prepare_op_getinteriorfield_gc_r = _prepare_op_getinteriorfield
+ prepare_op_getinteriorfield_gc_f = _prepare_op_getinteriorfield
+
def prepare_op_setinteriorfield_gc(self, op, fcond):
t = unpack_interiorfielddescr(op.getdescr())
ofs, itemsize, fieldsize, sign = t
@@ -920,7 +901,7 @@
base_loc = self.make_sure_var_in_reg(arg)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg(op.result)
+ res = self.force_allocate_reg(op)
return [res, base_loc, imm(ofs)]
def prepare_op_setarrayitem_gc(self, op, fcond):
@@ -935,7 +916,7 @@
prepare_op_setarrayitem_raw = prepare_op_setarrayitem_gc
prepare_op_raw_store = prepare_op_setarrayitem_gc
- def prepare_op_getarrayitem_gc(self, op, fcond):
+ def _prepare_op_getarrayitem(self, op, fcond):
boxes = op.getarglist()
size, ofs, _ = unpack_arraydescr(op.getdescr())
scale = get_scale(size)
@@ -943,14 +924,22 @@
ofs_loc = self.make_sure_var_in_reg(boxes[1], boxes)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg(op.result)
+ res = self.force_allocate_reg(op)
assert check_imm_arg(ofs)
return [res, base_loc, ofs_loc, imm(scale), imm(ofs)]
- prepare_op_getarrayitem_raw = prepare_op_getarrayitem_gc
- prepare_op_getarrayitem_raw_pure = prepare_op_getarrayitem_gc
- prepare_op_getarrayitem_gc_pure = prepare_op_getarrayitem_gc
- prepare_op_raw_load = prepare_op_getarrayitem_gc
+ prepare_op_getarrayitem_gc_i = _prepare_op_getarrayitem
+ prepare_op_getarrayitem_gc_r = _prepare_op_getarrayitem
+ prepare_op_getarrayitem_gc_f = _prepare_op_getarrayitem
+ prepare_op_getarrayitem_raw_i = _prepare_op_getarrayitem
+ prepare_op_getarrayitem_raw_f = _prepare_op_getarrayitem
+ prepare_op_getarrayitem_raw_pure_i = _prepare_op_getarrayitem
+ prepare_op_getarrayitem_raw_pure_f = _prepare_op_getarrayitem
+ prepare_op_getarrayitem_gc_pure_i = _prepare_op_getarrayitem
+ prepare_op_getarrayitem_gc_pure_r = _prepare_op_getarrayitem
+ prepare_op_getarrayitem_gc_pure_f = _prepare_op_getarrayitem
+ prepare_op_raw_load_i = _prepare_op_getarrayitem
+ prepare_op_raw_load_f = _prepare_op_getarrayitem
def prepare_op_strlen(self, op, fcond):
args = op.getarglist()
@@ -967,8 +956,8 @@
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg(op.result)
- self.possibly_free_var(op.result)
+ res = self.force_allocate_reg(op)
+ self.possibly_free_var(op)
return [l0, l1, res]
def prepare_op_strgetitem(self, op, fcond):
@@ -984,7 +973,7 @@
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg(op.result)
+ res = self.force_allocate_reg(op)
basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR,
self.cpu.translate_support_code)
@@ -1018,7 +1007,7 @@
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg(op.result)
+ res = self.force_allocate_reg(op)
return [l0, l1, res]
def prepare_op_unicodegetitem(self, op, fcond):
@@ -1028,7 +1017,7 @@
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.force_allocate_reg(op.result)
+ res = self.force_allocate_reg(op)
basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE,
self.cpu.translate_support_code)
@@ -1047,7 +1036,7 @@
return [value_loc, base_loc, ofs_loc,
imm(scale), imm(basesize), imm(itemsize)]
- def prepare_op_same_as(self, op, fcond):
+ def _prepare_op_same_as(self, op, fcond):
arg = op.getarg(0)
imm_arg = check_imm_box(arg)
if imm_arg:
@@ -1056,18 +1045,21 @@
argloc = self.make_sure_var_in_reg(arg)
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- resloc = self.force_allocate_reg(op.result)
+ resloc = self.force_allocate_reg(op)
return [argloc, resloc]
- prepare_op_cast_ptr_to_int = prepare_op_same_as
- prepare_op_cast_int_to_ptr = prepare_op_same_as
+ prepare_op_cast_ptr_to_int = _prepare_op_same_as
+ prepare_op_cast_int_to_ptr = _prepare_op_same_as
+ prepare_op_same_as_i = _prepare_op_same_as
+ prepare_op_same_as_r = _prepare_op_same_as
+ prepare_op_same_as_f = _prepare_op_same_as
def prepare_op_call_malloc_nursery(self, op, fcond):
size_box = op.getarg(0)
assert isinstance(size_box, ConstInt)
size = size_box.getint()
- self.rm.force_allocate_reg(op.result, selected_reg=r.r0)
+ self.rm.force_allocate_reg(op, selected_reg=r.r0)
t = TempInt()
self.rm.force_allocate_reg(t, selected_reg=r.r1)
@@ -1085,13 +1077,13 @@
def prepare_op_call_malloc_nursery_varsize_frame(self, op, fcond):
size_box = op.getarg(0)
- assert isinstance(size_box, BoxInt) # we cannot have a const here!
+ assert not isinstance(size_box, ConstInt) # we cannot have a const here!
# sizeloc must be in a register, but we can free it now
# (we take care explicitly of conflicts with r0 or r1)
sizeloc = self.rm.make_sure_var_in_reg(size_box)
self.rm.possibly_free_var(size_box)
#
- self.rm.force_allocate_reg(op.result, selected_reg=r.r0)
+ self.rm.force_allocate_reg(op, selected_reg=r.r0)
#
t = TempInt()
self.rm.force_allocate_reg(t, selected_reg=r.r1)
@@ -1115,11 +1107,11 @@
# for boehm, this function should never be called
arraydescr = op.getdescr()
length_box = op.getarg(2)
- assert isinstance(length_box, BoxInt) # we cannot have a const here!
+ assert not isinstance(length_box, Const) # we cannot have a const here!
# the result will be in r0
- self.rm.force_allocate_reg(op.result, selected_reg=r.r0)
+ self.rm.force_allocate_reg(op, selected_reg=r.r0)
# we need r1 as a temporary
- tmp_box = TempBox()
+ tmp_box = TempVar()
self.rm.force_allocate_reg(tmp_box, selected_reg=r.r1)
gcmap = self.get_gcmap([r.r0, r.r1]) # allocate the gcmap *before*
self.rm.possibly_free_var(tmp_box)
@@ -1144,7 +1136,6 @@
prepare_op_leave_portal_frame = void
def prepare_op_cond_call_gc_wb(self, op, fcond):
- assert op.result is None
# we force all arguments in a reg because it will be needed anyway by
# the following setfield_gc or setarrayitem_gc. It avoids loading it
# twice from the memory.
@@ -1160,7 +1151,6 @@
prepare_op_cond_call_gc_wb_array = prepare_op_cond_call_gc_wb
def prepare_op_cond_call(self, op, fcond):
- assert op.result is None
assert 2 <= op.numargs() <= 4 + 2
tmpreg = self.get_scratch_reg(INT, selected_reg=r.r4)
v = op.getarg(1)
@@ -1178,8 +1168,7 @@
def prepare_op_force_token(self, op, fcond):
# XXX for now we return a regular reg
- res_loc = self.force_allocate_reg(op.result)
- self.possibly_free_var(op.result)
+ res_loc = self.force_allocate_reg(op)
return [res_loc]
def prepare_op_label(self, op, fcond):
@@ -1194,14 +1183,14 @@
# of some guard
position = self.rm.position
for arg in inputargs:
- assert isinstance(arg, Box)
+ assert not isinstance(arg, Const)
if self.last_real_usage.get(arg, -1) <= position:
self.force_spill_var(arg)
#
for i in range(len(inputargs)):
arg = inputargs[i]
- assert isinstance(arg, Box)
+ assert not isinstance(arg, Const)
loc = self.loc(arg)
arglocs[i] = loc
if loc.is_core_reg() or loc.is_vfp_reg():
@@ -1228,18 +1217,33 @@
self.assembler.store_force_descr(op, fail_locs[1:], fail_locs[0].value)
self.possibly_free_vars(op.getfailargs())
- def prepare_op_call_may_force(self, op, fcond):
+ def _prepare_op_call_may_force(self, op, fcond):
return self._prepare_call(op, save_all_regs=True)
- def prepare_op_call_release_gil(self, op, fcond):
+ prepare_op_call_may_force_i = _prepare_op_call_may_force
+ prepare_op_call_may_force_r = _prepare_op_call_may_force
+ prepare_op_call_may_force_f = _prepare_op_call_may_force
+ prepare_op_call_may_force_n = _prepare_op_call_may_force
+
+ def _prepare_op_call_release_gil(self, op, fcond):
return self._prepare_call(op, save_all_regs=True, first_arg_index=2)
- def prepare_op_call_assembler(self, op, fcond):
+ prepare_op_call_release_gil_i = _prepare_op_call_release_gil
+ prepare_op_call_release_gil_r = _prepare_op_call_release_gil
+ prepare_op_call_release_gil_f = _prepare_op_call_release_gil
+ prepare_op_call_release_gil_n = _prepare_op_call_release_gil
+
+ def _prepare_op_call_assembler(self, op, fcond):
locs = self.locs_for_call_assembler(op)
tmploc = self.get_scratch_reg(INT, selected_reg=r.r0)
resloc = self._call(op, locs + [tmploc], save_all_regs=True)
return locs + [resloc, tmploc]
+ prepare_op_call_assembler_i = _prepare_op_call_assembler
+ prepare_op_call_assembler_r = _prepare_op_call_assembler
+ prepare_op_call_assembler_f = _prepare_op_call_assembler
+ prepare_op_call_assembler_n = _prepare_op_call_assembler
+
def _prepare_args_for_new_op(self, new_args):
gc_ll_descr = self.cpu.gc_ll_descr
args = gc_ll_descr.args_for_new(new_args)
@@ -1269,18 +1273,17 @@
loc = self.make_sure_var_in_reg(op.getarg(1))
self.possibly_free_vars_for_op(op)
self.free_temp_vars()
- res = self.vfprm.force_allocate_reg(op.result)
- self.possibly_free_var(op.result)
+ res = self.vfprm.force_allocate_reg(op)
return [loc, res]
def prepare_op_cast_float_to_int(self, op, fcond):
loc1 = self.make_sure_var_in_reg(op.getarg(0))
- res = self.rm.force_allocate_reg(op.result)
+ res = self.rm.force_allocate_reg(op)
return [loc1, res]
def prepare_op_cast_int_to_float(self, op, fcond):
loc1 = self.make_sure_var_in_reg(op.getarg(0))
- res = self.vfprm.force_allocate_reg(op.result)
+ res = self.vfprm.force_allocate_reg(op)
return [loc1, res]
def prepare_force_spill(self, op, fcond):
@@ -1292,17 +1295,17 @@
#def prepare_op_read_timestamp(self, op, fcond):
# loc = self.get_scratch_reg(INT)
- # res = self.vfprm.force_allocate_reg(op.result)
+ # res = self.vfprm.force_allocate_reg(op)
# return [loc, res]
def prepare_op_cast_float_to_singlefloat(self, op, fcond):
loc1 = self.make_sure_var_in_reg(op.getarg(0))
- res = self.force_allocate_reg(op.result)
+ res = self.force_allocate_reg(op)
return [loc1, res]
def prepare_op_cast_singlefloat_to_float(self, op, fcond):
loc1 = self.make_sure_var_in_reg(op.getarg(0))
- res = self.force_allocate_reg(op.result)
+ res = self.force_allocate_reg(op)
return [loc1, res]
diff --git a/rpython/jit/backend/arm/test/test_runner.py b/rpython/jit/backend/arm/test/test_runner.py
--- a/rpython/jit/backend/arm/test/test_runner.py
+++ b/rpython/jit/backend/arm/test/test_runner.py
@@ -2,9 +2,9 @@
from rpython.jit.backend.detect_cpu import getcpuclass
from rpython.jit.backend.test.runner_test import LLtypeBackendTest,\
boxfloat, constfloat
-from rpython.jit.metainterp.history import (BasicFailDescr, BasicFinalDescr,
- BoxInt)
-from rpython.jit.metainterp.resoperation import ResOperation, rop
+from rpython.jit.metainterp.history import BasicFailDescr, BasicFinalDescr
+from rpython.jit.metainterp.resoperation import (ResOperation, rop,
+ InputArgInt)
from rpython.jit.tool.oparser import parse
from rpython.rtyper.lltypesystem import lltype, llmemory
from rpython.rtyper import rclass
@@ -52,30 +52,29 @@
def test_result_is_spilled(self):
cpu = self.cpu
- inp = [BoxInt(i) for i in range(1, 15)]
- out = [BoxInt(i) for i in range(1, 15)]
+ inp = [InputArgInt(i) for i in range(1, 15)]
looptoken = JitCellToken()
targettoken = TargetToken()
operations = [
- ResOperation(rop.LABEL, inp, None, descr=targettoken),
- ResOperation(rop.INT_ADD, [inp[0], inp[1]], out[0]),
- ResOperation(rop.INT_ADD, [inp[2], inp[3]], out[1]),
- ResOperation(rop.INT_ADD, [inp[4], inp[5]], out[2]),
- ResOperation(rop.INT_ADD, [inp[6], inp[7]], out[3]),
- ResOperation(rop.INT_ADD, [inp[8], inp[9]], out[4]),
- ResOperation(rop.INT_ADD, [inp[10], inp[11]], out[5]),
- ResOperation(rop.INT_ADD, [inp[12], inp[13]], out[6]),
- ResOperation(rop.INT_ADD, [inp[0], inp[1]], out[7]),
- ResOperation(rop.INT_ADD, [inp[2], inp[3]], out[8]),
- ResOperation(rop.INT_ADD, [inp[4], inp[5]], out[9]),
- ResOperation(rop.INT_ADD, [inp[6], inp[7]], out[10]),
- ResOperation(rop.INT_ADD, [inp[8], inp[9]], out[11]),
- ResOperation(rop.INT_ADD, [inp[10], inp[11]], out[12]),
- ResOperation(rop.INT_ADD, [inp[12], inp[13]], out[13]),
- ResOperation(rop.GUARD_FALSE, [inp[1]], None, descr=BasicFailDescr(1)),
- ResOperation(rop.FINISH, [inp[1]], None, descr=BasicFinalDescr(1)),
+ ResOperation(rop.LABEL, inp, descr=targettoken),
+ ResOperation(rop.INT_ADD, [inp[0], inp[1]]),
+ ResOperation(rop.INT_ADD, [inp[2], inp[3]]),
+ ResOperation(rop.INT_ADD, [inp[4], inp[5]]),
+ ResOperation(rop.INT_ADD, [inp[6], inp[7]]),
+ ResOperation(rop.INT_ADD, [inp[8], inp[9]]),
+ ResOperation(rop.INT_ADD, [inp[10], inp[11]]),
+ ResOperation(rop.INT_ADD, [inp[12], inp[13]]),
+ ResOperation(rop.INT_ADD, [inp[0], inp[1]]),
+ ResOperation(rop.INT_ADD, [inp[2], inp[3]]),
+ ResOperation(rop.INT_ADD, [inp[4], inp[5]]),
+ ResOperation(rop.INT_ADD, [inp[6], inp[7]]),
+ ResOperation(rop.INT_ADD, [inp[8], inp[9]]),
+ ResOperation(rop.INT_ADD, [inp[10], inp[11]]),
+ ResOperation(rop.INT_ADD, [inp[12], inp[13]]),
+ ResOperation(rop.GUARD_FALSE, [inp[1]], descr=BasicFailDescr(1)),
+ ResOperation(rop.FINISH, [inp[1]], descr=BasicFinalDescr(1)),
]
- operations[-2].setfailargs(out)
+ operations[-2].setfailargs(operations[1:15])
cpu.compile_loop(inp, operations, looptoken)
args = [i for i in range(1, 15)]
deadframe = self.cpu.execute_token(looptoken, *args)
@@ -104,7 +103,7 @@
lt2.outermost_jitdriver_sd = FakeJitDriverSD()
loop1 = parse('''
[i0]
- i1 = call_assembler(i0, descr=lt2)
+ i1 = call_assembler_i(i0, descr=lt2)
guard_not_forced()[]
finish(i1)
''', namespace=locals())
@@ -181,19 +180,19 @@
def test_float_field(self):
if not self.cpu.supports_floats:
py.test.skip('requires floats')
+ t_box, T_box, _ = self.alloc_instance(self.TFloat)
floatdescr = self.cpu.fielddescrof(self.SFloat, 'float')
- t_box, T_box = self.alloc_instance(self.TFloat)
self.execute_operation(rop.SETFIELD_GC, [t_box, boxfloat(3.4)],
'void', descr=floatdescr)
- res = self.execute_operation(rop.GETFIELD_GC, [t_box],
+ res = self.execute_operation(rop.GETFIELD_GC_F, [t_box],
'float', descr=floatdescr)
- assert res.getfloat() == 3.4
+ assert longlong.getrealfloat(res) == 3.4
#
self.execute_operation(rop.SETFIELD_GC, [t_box, constfloat(-3.6)],
'void', descr=floatdescr)
- res = self.execute_operation(rop.GETFIELD_GC, [t_box],
+ res = self.execute_operation(rop.GETFIELD_GC_F, [t_box],
'float', descr=floatdescr)
- assert res.getfloat() == -3.6
+ assert longlong.getrealfloat(res) == -3.6
def test_compile_loop_many_int_args(self):
for numargs in range(2, 30):
@@ -269,13 +268,13 @@
targettoken = TargetToken()
ops = """
[i0, f3]
- i2 = same_as(i0) # but forced to be in a register
+ i2 = same_as_i(i0) # but forced to be in a register
force_spill(i2)
force_spill(f3)
f4 = float_add(f3, 5.0)
label(f3, f4, descr=targettoken)
force_spill(f3)
- f5 = same_as(f3) # but forced to be in a register
+ f5 = same_as_f(f3) # but forced to be in a register
finish(f5)
"""
faildescr = BasicFailDescr(2)
@@ -284,8 +283,8 @@
info = self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
ops2 = """
[i0, f1]
- i1 = same_as(i0)
- f2 = same_as(f1)
+ i1 = same_as_i(i0)
+ f2 = same_as_f(f1)
f3 = float_add(f1, 10.0)
force_spill(f3)
force_spill(i1)
diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py
--- a/rpython/jit/backend/detect_cpu.py
+++ b/rpython/jit/backend/detect_cpu.py
@@ -122,11 +122,15 @@
def getcpufeatures(backend_name="auto"):
- """NOT_RPYTHON"""
- cpucls = getcpuclass(backend_name)
- return [attr[len('supports_'):] for attr in dir(cpucls)
- if attr.startswith('supports_')
- and getattr(cpucls, attr)]
+ if backend_name == "auto":
+ backend_name = autodetect()
+ return {
+ MODEL_X86: ['floats', 'singlefloats', 'longlong'],
+ MODEL_X86_NO_SSE2: ['longlong'],
+ MODEL_X86_64: ['floats', 'singlefloats'],
+ MODEL_ARM: ['floats', 'singlefloats', 'longlong'],
+ MODEL_PPC_64: [], # we don't even have PPC directory, so no
+ }[backend_name]
if __name__ == '__main__':
if len(sys.argv) > 1:
diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -16,6 +16,7 @@
from rpython.rlib.clibffi import FFI_DEFAULT_ABI
from rpython.rlib.rarithmetic import ovfcheck, r_uint, r_ulonglong
+from rpython.rlib.objectmodel import Symbolic
class LLTrace(object):
has_been_freed = False
@@ -25,7 +26,9 @@
# We need to clone the list of operations because the
# front-end will mutate them under our feet again. We also
# need to make sure things get freed.
- def mapping(box, _cache={}):
+ _cache={}
+
+ def mapping(box):
if isinstance(box, Const) or box is None:
return box
try:
@@ -46,8 +49,8 @@
newdescr = None
newop = op.copy_and_change(op.getopnum(),
map(mapping, op.getarglist()),
- mapping(op.result),
newdescr)
+ _cache[op] = newop
if op.getfailargs() is not None:
newop.setfailargs(map(mapping, op.getfailargs()))
self.operations.append(newop)
@@ -86,15 +89,45 @@
def get_result_type(self):
return getkind(self.RESULT)[0]
+ get_normalized_result_type = get_result_type
+
+class TypeIDSymbolic(Symbolic):
+ def __init__(self, STRUCT_OR_ARRAY):
+ self.STRUCT_OR_ARRAY = STRUCT_OR_ARRAY
+
+ def __eq__(self, other):
+ return self.STRUCT_OR_ARRAY is other.STRUCT_OR_ARRAY
+
+ def __ne__(self, other):
+ return not self == other
+
class SizeDescr(AbstractDescr):
- def __init__(self, S):
+ def __init__(self, S, vtable, runner):
+ assert not isinstance(vtable, bool)
self.S = S
+ self._vtable = vtable
+ self._is_object = bool(vtable)
+ self._runner = runner
- def as_vtable_size_descr(self):
- return self
+ def get_all_fielddescrs(self):
+ return self.all_fielddescrs
- def count_fields_if_immutable(self):
- return heaptracker.count_fields_if_immutable(self.S)
+ def is_object(self):
+ return self._is_object
+
+ def get_vtable(self):
+ assert self._vtable is not None
+ if self._vtable is Ellipsis:
+ self._vtable = heaptracker.get_vtable_for_gcstruct(self._runner,
+ self.S)
+ return heaptracker.adr2int(llmemory.cast_ptr_to_adr(self._vtable))
+
+ def is_immutable(self):
+ return heaptracker.is_immutable_struct(self.S)
+
+ def get_type_id(self):
+ assert isinstance(self.S, lltype.GcStruct)
+ return TypeIDSymbolic(self.S) # integer-like symbolic
def __repr__(self):
return 'SizeDescr(%r)' % (self.S,)
@@ -104,10 +137,21 @@
self.S = S
self.fieldname = fieldname
self.FIELD = getattr(S, fieldname)
+ self.index = heaptracker.get_fielddescr_index_in(S, fieldname)
+ self._is_pure = S._immutable_field(fieldname)
+
+ def is_always_pure(self):
+ return self._is_pure
+
+ def get_parent_descr(self):
+ return self.parent_descr
def get_vinfo(self):
return self.vinfo
+ def get_index(self):
+ return self.index
+
def __repr__(self):
return 'FieldDescr(%r, %r)' % (self.S, self.fieldname)
@@ -146,11 +190,20 @@
rffi.cast(TYPE, -1) == -1)
class ArrayDescr(AbstractDescr):
- def __init__(self, A):
+ all_interiorfielddescrs = None
+
+ def __init__(self, A, runner):
self.A = self.OUTERA = A
+ self._is_pure = A._immutable_field(None)
if isinstance(A, lltype.Struct):
self.A = A._flds[A._arrayfld]
+ def is_always_pure(self):
+ return self._is_pure
+
+ def get_all_fielddescrs(self):
+ return self.all_interiorfielddescrs
+
def __repr__(self):
return 'ArrayDescr(%r)' % (self.OUTERA,)
@@ -184,12 +237,27 @@
return intbounds.get_integer_max(
not _is_signed_kind(self.A.OF), rffi.sizeof(self.A.OF))
+ def get_type_id(self):
+ assert isinstance(self.A, lltype.GcArray)
+ return TypeIDSymbolic(self.A) # integer-like symbolic
+
class InteriorFieldDescr(AbstractDescr):
- def __init__(self, A, fieldname):
+ def __init__(self, A, fieldname, runner):
self.A = A
self.fieldname = fieldname
self.FIELD = getattr(A.OF, fieldname)
+ self.arraydescr = runner.arraydescrof(A)
+ self.fielddescr = runner.fielddescrof(A.OF, fieldname)
+
+ def get_index(self):
+ return self.fielddescr.get_index()
+
+ def get_arraydescr(self):
+ return self.arraydescr
+
+ def get_field_descr(self):
+ return self.fielddescr
def __repr__(self):
return 'InteriorFieldDescr(%r, %r)' % (self.A, self.fieldname)
@@ -232,6 +300,7 @@
supports_floats = True
supports_longlong = r_uint is not r_ulonglong
supports_singlefloats = True
+ supports_guard_gc_type = True
translate_support_code = False
is_llgraph = True
@@ -336,10 +405,10 @@
values = []
for box in frame.force_guard_op.getfailargs():
if box is not None:
- if box is not frame.current_op.result:
+ if box is not frame.current_op:
value = frame.env[box]
else:
- value = box.value # 0 or 0.0 or NULL
+ value = box.getvalue() # 0 or 0.0 or NULL
else:
value = None
values.append(value)
@@ -367,14 +436,19 @@
self.descrs[key] = descr
return descr
- def sizeof(self, S):
+ def sizeof(self, S, vtable=lltype.nullptr(rclass.OBJECT_VTABLE)):
key = ('size', S)
try:
- return self.descrs[key]
+ descr = self.descrs[key]
except KeyError:
- descr = SizeDescr(S)
+ descr = SizeDescr(S, vtable, self)
self.descrs[key] = descr
- return descr
+ descr.all_fielddescrs = heaptracker.all_fielddescrs(self, S,
+ get_field_descr=LLGraphCPU.fielddescrof)
+ if descr._is_object and vtable is not Ellipsis:
+ assert vtable
+ heaptracker.testing_gcstruct2vtable.setdefault(S, vtable)
+ return descr
def fielddescrof(self, S, fieldname):
key = ('field', S, fieldname)
@@ -383,6 +457,12 @@
except KeyError:
descr = FieldDescr(S, fieldname)
self.descrs[key] = descr
+ if (isinstance(S, lltype.GcStruct) and
+ heaptracker.has_gcstruct_a_vtable(S)):
+ vtable = Ellipsis
+ else:
+ vtable = None
+ descr.parent_descr = self.sizeof(S, vtable)
if self.vinfo_for_tests is not None:
descr.vinfo = self.vinfo_for_tests
return descr
@@ -392,8 +472,12 @@
try:
return self.descrs[key]
except KeyError:
- descr = ArrayDescr(A)
+ descr = ArrayDescr(A, self)
self.descrs[key] = descr
+ if isinstance(A, lltype.Array) and isinstance(A.OF, lltype.Struct):
+ descrs = heaptracker.all_interiorfielddescrs(self,
+ A, get_field_descr=LLGraphCPU.interiorfielddescrof)
+ descr.all_interiorfielddescrs = descrs
return descr
def interiorfielddescrof(self, A, fieldname):
@@ -401,7 +485,7 @@
try:
return self.descrs[key]
except KeyError:
- descr = InteriorFieldDescr(A, fieldname)
+ descr = InteriorFieldDescr(A, fieldname, self)
self.descrs[key] = descr
return descr
@@ -435,6 +519,22 @@
self.descrs[key] = descr
return descr
+ def check_is_object(self, gcptr):
+ """Check if the given, non-null gcptr refers to an rclass.OBJECT
+ or not at all (an unrelated GcStruct or a GcArray). Only usable
+ in the llgraph backend, or after translation of a real backend."""
+ ptr = lltype.normalizeptr(gcptr._obj.container._as_ptr())
+ T = lltype.typeOf(ptr).TO
+ return heaptracker.has_gcstruct_a_vtable(T) or T is rclass.OBJECT
+
+ def get_actual_typeid(self, gcptr):
+ """Fetch the actual typeid of the given gcptr, as an integer.
+ Only usable in the llgraph backend, or after translation of a
+ real backend. (Here in the llgraph backend, returns a
+ TypeIDSymbolic instead of a real integer.)"""
+ ptr = lltype.normalizeptr(gcptr._obj.container._as_ptr())
+ return TypeIDSymbolic(lltype.typeOf(ptr).TO)
+
# ------------------------------------------------------------
def maybe_on_top_of_llinterp(self, func, args, RESULT):
@@ -461,13 +561,17 @@
p = support.cast_arg(lltype.Ptr(descr.S), p)
return support.cast_result(descr.FIELD, getattr(p, descr.fieldname))
- bh_getfield_gc_pure = bh_getfield_gc
+ bh_getfield_gc_pure_i = bh_getfield_gc
+ bh_getfield_gc_pure_r = bh_getfield_gc
+ bh_getfield_gc_pure_f = bh_getfield_gc
bh_getfield_gc_i = bh_getfield_gc
bh_getfield_gc_r = bh_getfield_gc
bh_getfield_gc_f = bh_getfield_gc
bh_getfield_raw = bh_getfield_gc
- bh_getfield_raw_pure = bh_getfield_raw
+ bh_getfield_raw_pure_i = bh_getfield_raw
+ bh_getfield_raw_pure_r = bh_getfield_raw
+ bh_getfield_raw_pure_f = bh_getfield_raw
bh_getfield_raw_i = bh_getfield_raw
bh_getfield_raw_r = bh_getfield_raw
bh_getfield_raw_f = bh_getfield_raw
@@ -495,13 +599,17 @@
array = a._obj
return support.cast_result(descr.A.OF, array.getitem(index))
- bh_getarrayitem_gc_pure = bh_getarrayitem_gc
+ bh_getarrayitem_gc_pure_i = bh_getarrayitem_gc
+ bh_getarrayitem_gc_pure_r = bh_getarrayitem_gc
+ bh_getarrayitem_gc_pure_f = bh_getarrayitem_gc
bh_getarrayitem_gc_i = bh_getarrayitem_gc
bh_getarrayitem_gc_r = bh_getarrayitem_gc
bh_getarrayitem_gc_f = bh_getarrayitem_gc
bh_getarrayitem_raw = bh_getarrayitem_gc
- bh_getarrayitem_raw_pure = bh_getarrayitem_raw
+ bh_getarrayitem_raw_pure_i = bh_getarrayitem_raw
+ bh_getarrayitem_raw_pure_r = bh_getarrayitem_raw
+ bh_getarrayitem_raw_pure_f = bh_getarrayitem_raw
bh_getarrayitem_raw_i = bh_getarrayitem_raw
bh_getarrayitem_raw_r = bh_getarrayitem_raw
bh_getarrayitem_raw_f = bh_getarrayitem_raw
@@ -634,11 +742,11 @@
return lltype.cast_opaque_ptr(llmemory.GCREF,
lltype.malloc(sizedescr.S, zero=True))
- def bh_new_with_vtable(self, vtable, descr):
+ def bh_new_with_vtable(self, descr):
result = lltype.malloc(descr.S, zero=True)
result_as_objptr = lltype.cast_pointer(rclass.OBJECTPTR, result)
result_as_objptr.typeptr = support.cast_from_int(rclass.CLASSTYPE,
- vtable)
+ descr.get_vtable())
return lltype.cast_opaque_ptr(llmemory.GCREF, result)
def bh_new_array(self, length, arraydescr):
@@ -749,8 +857,8 @@
i = 0
self.do_renaming(targetargs, j.args)
continue
- if op.result is not None:
- self.setenv(op.result, resval)
+ if op.type != 'v':
+ self.setenv(op, resval)
else:
assert resval is None
i += 1
@@ -823,6 +931,32 @@
self.execute_guard_nonnull(descr, arg)
self.execute_guard_class(descr, arg, klass)
+ def execute_guard_gc_type(self, descr, arg, typeid):
+ assert isinstance(typeid, TypeIDSymbolic)
+ TYPE = arg._obj.container._TYPE
+ if TYPE != typeid.STRUCT_OR_ARRAY:
+ self.fail_guard(descr)
+
+ def execute_guard_is_object(self, descr, arg):
+ TYPE = arg._obj.container._TYPE
+ while TYPE is not rclass.OBJECT:
+ if not isinstance(TYPE, lltype.GcStruct): # or TYPE is None
+ self.fail_guard(descr)
+ return
+ _, TYPE = TYPE._first_struct()
+
+ def execute_guard_subclass(self, descr, arg, klass):
+ value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, arg)
+ expected_class = llmemory.cast_adr_to_ptr(
+ llmemory.cast_int_to_adr(klass),
+ rclass.CLASSTYPE)
+ if (expected_class.subclassrange_min
+ <= value.typeptr.subclassrange_min
+ <= expected_class.subclassrange_max):
+ pass
+ else:
+ self.fail_guard(descr)
+
def execute_guard_no_exception(self, descr):
if self.last_exception is not None:
self.fail_guard(descr)
@@ -894,6 +1028,7 @@
def execute_guard_overflow(self, descr):
if not self.overflow_flag:
self.fail_guard(descr)
+ return lltype.nullptr(llmemory.GCREF.TO) # I think it's fine....
def execute_jump(self, descr, *args):
raise Jump(descr._llgraph_target, args)
@@ -908,9 +1043,9 @@
if not cond:
return
# cond_call can't have a return value
- self.execute_call(calldescr, func, *args)
+ self.execute_call_n(calldescr, func, *args)
- def execute_call(self, calldescr, func, *args):
+ def _execute_call(self, calldescr, func, *args):
effectinfo = calldescr.get_extra_info()
if effectinfo is not None and hasattr(effectinfo, 'oopspecindex'):
oopspecindex = effectinfo.oopspecindex
@@ -926,16 +1061,25 @@
res = _example_res[getkind(TP.RESULT)[0]]
return res
- def execute_call_may_force(self, calldescr, func, *args):
- call_op = self.lltrace.operations[self.current_index]
+ execute_call_i = _execute_call
+ execute_call_r = _execute_call
+ execute_call_f = _execute_call
+ execute_call_n = _execute_call
+
+ def _execute_call_may_force(self, calldescr, func, *args):
guard_op = self.lltrace.operations[self.current_index + 1]
assert guard_op.getopnum() == rop.GUARD_NOT_FORCED
self.force_guard_op = guard_op
- res = self.execute_call(calldescr, func, *args)
+ res = self._execute_call(calldescr, func, *args)
del self.force_guard_op
return res
- def execute_call_release_gil(self, descr, saveerr, func, *args):
+ execute_call_may_force_n = _execute_call_may_force
+ execute_call_may_force_r = _execute_call_may_force
+ execute_call_may_force_f = _execute_call_may_force
+ execute_call_may_force_i = _execute_call_may_force
+
+ def _execute_call_release_gil(self, descr, saveerr, func, *args):
if hasattr(descr, '_original_func_'):
func = descr._original_func_ # see pyjitpl.py
# we want to call the function that does the aroundstate
@@ -960,61 +1104,74 @@
del self.force_guard_op
return support.cast_result(descr.RESULT, result)
- def execute_call_assembler(self, descr, *args):
- # XXX simplify the following a bit
- #
- # pframe = CALL_ASSEMBLER(args..., descr=looptoken)
- # ==>
- # pframe = CALL looptoken.loopaddr(*args)
- # JUMP_IF_FAST_PATH @fastpath
- # res = CALL assembler_call_helper(pframe)
- # jmp @done
- # @fastpath:
- # res = GETFIELD(pframe, 'result')
- # @done:
- #
- call_op = self.lltrace.operations[self.current_index]
- guard_op = self.lltrace.operations[self.current_index + 1]
- assert guard_op.getopnum() == rop.GUARD_NOT_FORCED
- self.force_guard_op = guard_op
- pframe = self.cpu._execute_token(descr, *args)
- del self.force_guard_op
- #
- jd = descr.outermost_jitdriver_sd
- assert jd is not None, ("call_assembler(): the loop_token needs "
- "to have 'outermost_jitdriver_sd'")
- if jd.index_of_virtualizable != -1:
- vable = args[jd.index_of_virtualizable]
- else:
- vable = lltype.nullptr(llmemory.GCREF.TO)
- #
- # Emulate the fast path
- #
- faildescr = self.cpu.get_latest_descr(pframe)
- if faildescr == self.cpu.done_with_this_frame_descr_int:
- return self.cpu.get_int_value(pframe, 0)
- elif faildescr == self.cpu.done_with_this_frame_descr_ref:
- return self.cpu.get_ref_value(pframe, 0)
- elif faildescr == self.cpu.done_with_this_frame_descr_float:
- return self.cpu.get_float_value(pframe, 0)
- elif faildescr == self.cpu.done_with_this_frame_descr_void:
- return None
+ execute_call_release_gil_n = _execute_call_release_gil
+ execute_call_release_gil_i = _execute_call_release_gil
+ execute_call_release_gil_r = _execute_call_release_gil
+ execute_call_release_gil_f = _execute_call_release_gil
- assembler_helper_ptr = jd.assembler_helper_adr.ptr # fish
- try:
- result = assembler_helper_ptr(pframe, vable)
- except LLException, lle:
- assert self.last_exception is None, "exception left behind"
- self.last_exception = lle
- # fish op
- op = self.current_op
- return op.result and op.result.value
- if isinstance(result, float):
- result = support.cast_to_floatstorage(result)
- return result
+ def _new_execute_call_assembler(def_val):
+ def _execute_call_assembler(self, descr, *args):
+ # XXX simplify the following a bit
+ #
+ # pframe = CALL_ASSEMBLER(args..., descr=looptoken)
+ # ==>
+ # pframe = CALL looptoken.loopaddr(*args)
+ # JUMP_IF_FAST_PATH @fastpath
+ # res = CALL assembler_call_helper(pframe)
+ # jmp @done
+ # @fastpath:
+ # res = GETFIELD(pframe, 'result')
+ # @done:
+ #
+ call_op = self.lltrace.operations[self.current_index]
+ guard_op = self.lltrace.operations[self.current_index + 1]
+ assert guard_op.getopnum() == rop.GUARD_NOT_FORCED
+ self.force_guard_op = guard_op
+ pframe = self.cpu._execute_token(descr, *args)
+ del self.force_guard_op
+ #
+ jd = descr.outermost_jitdriver_sd
+ assert jd is not None, ("call_assembler(): the loop_token needs "
+ "to have 'outermost_jitdriver_sd'")
+ if jd.index_of_virtualizable != -1:
+ vable = args[jd.index_of_virtualizable]
+ else:
+ vable = lltype.nullptr(llmemory.GCREF.TO)
+ #
+ # Emulate the fast path
+ #
+ faildescr = self.cpu.get_latest_descr(pframe)
+ if faildescr == self.cpu.done_with_this_frame_descr_int:
+ return self.cpu.get_int_value(pframe, 0)
+ elif faildescr == self.cpu.done_with_this_frame_descr_ref:
+ return self.cpu.get_ref_value(pframe, 0)
+ elif faildescr == self.cpu.done_with_this_frame_descr_float:
+ return self.cpu.get_float_value(pframe, 0)
+ elif faildescr == self.cpu.done_with_this_frame_descr_void:
+ return None
- def execute_same_as(self, _, x):
+ assembler_helper_ptr = jd.assembler_helper_adr.ptr # fish
+ try:
+ result = assembler_helper_ptr(pframe, vable)
+ except LLException, lle:
+ assert self.last_exception is None, "exception left behind"
+ self.last_exception = lle
+ # fish op
+ result = def_val
+ if isinstance(result, float):
+ result = support.cast_to_floatstorage(result)
+ return result
+ return _execute_call_assembler
+
+ execute_call_assembler_i = _new_execute_call_assembler(0)
+ execute_call_assembler_r = _new_execute_call_assembler(lltype.nullptr(llmemory.GCREF.TO))
+ execute_call_assembler_f = _new_execute_call_assembler(0.0)
+ execute_call_assembler_n = _new_execute_call_assembler(None)
+
+ def execute_same_as_i(self, _, x):
return x
+ execute_same_as_f = execute_same_as_i
+ execute_same_as_r = execute_same_as_i
def execute_debug_merge_point(self, descr, *args):
from rpython.jit.metainterp.warmspot import get_stats
@@ -1031,9 +1188,8 @@
def execute_leave_portal_frame(self, descr, *args):
pass
- def execute_new_with_vtable(self, _, vtable):
- descr = heaptracker.vtable2descr(self.cpu, vtable)
- return self.cpu.bh_new_with_vtable(vtable, descr)
+ def execute_new_with_vtable(self, descr):
+ return self.cpu.bh_new_with_vtable(descr)
def execute_force_token(self, _):
return self
diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py
--- a/rpython/jit/backend/llsupport/assembler.py
+++ b/rpython/jit/backend/llsupport/assembler.py
@@ -3,7 +3,7 @@
from rpython.jit.backend.llsupport.symbolic import WORD
from rpython.jit.backend.llsupport.codemap import CodemapBuilder
from rpython.jit.metainterp.history import (INT, REF, FLOAT, JitCellToken,
- ConstInt, BoxInt, AbstractFailDescr)
+ ConstInt, AbstractFailDescr)
from rpython.jit.metainterp.resoperation import ResOperation, rop
from rpython.rlib import rgc
from rpython.rlib.debug import (debug_start, debug_stop, have_debug_prints_for,
@@ -223,11 +223,11 @@
self._call_assembler_emit_call(self.imm(descr._ll_function_addr),
More information about the pypy-commit
mailing list