[pypy-svn] r43477 - in pypy/branch/prolog-jit-experiments/pypy/lang/prolog: builtin interpreter interpreter/test
cfbolz at codespeak.net
cfbolz at codespeak.net
Fri May 18 14:35:13 CEST 2007
Author: cfbolz
Date: Fri May 18 14:35:12 2007
New Revision: 43477
Modified:
pypy/branch/prolog-jit-experiments/pypy/lang/prolog/builtin/__init__.py
pypy/branch/prolog-jit-experiments/pypy/lang/prolog/builtin/register.py
pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/engine.py
pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/portal.py
pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/term.py
pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/test/test_jit.py
Log:
assorted hints and hacks to make pyrolog-jit better. gives a speedup of around
2.
Modified: pypy/branch/prolog-jit-experiments/pypy/lang/prolog/builtin/__init__.py
==============================================================================
--- pypy/branch/prolog-jit-experiments/pypy/lang/prolog/builtin/__init__.py (original)
+++ pypy/branch/prolog-jit-experiments/pypy/lang/prolog/builtin/__init__.py Fri May 18 14:35:12 2007
@@ -1,5 +1,6 @@
# all builtins
builtins = {}
+builtins_list = []
# imports to register builtins
import pypy.lang.prolog.builtin.allsolution
Modified: pypy/branch/prolog-jit-experiments/pypy/lang/prolog/builtin/register.py
==============================================================================
--- pypy/branch/prolog-jit-experiments/pypy/lang/prolog/builtin/register.py (original)
+++ pypy/branch/prolog-jit-experiments/pypy/lang/prolog/builtin/register.py Fri May 18 14:35:12 2007
@@ -2,17 +2,20 @@
from pypy.lang.prolog.interpreter import arithmetic
from pypy.lang.prolog.interpreter.parsing import parse_file, TermBuilder
from pypy.lang.prolog.interpreter import engine, helper, term, error
-from pypy.lang.prolog.builtin import builtins
+from pypy.lang.prolog.builtin import builtins, builtins_list
from pypy.rlib.objectmodel import we_are_translated
class Builtin(object):
+ _immutable_ = True
def __init__(self, function):
self.function = function
def call(self, engine, query, continuation):
return self.function(engine, query, continuation)
+ def _freeze_(self):
+ return True
def expose_builtin(func, name, unwrap_spec=None, handles_continuation=False,
translatable=True):
@@ -80,5 +83,6 @@
exec py.code.Source("\n".join(code)).compile() in miniglobals
for name in expose_as:
signature = "%s/%s" % (name, len(unwrap_spec))
- builtins[signature] = Builtin(miniglobals[funcname])
-
+ b = Builtin(miniglobals[funcname])
+ builtins[signature] = b
+ builtins_list.append((signature, b))
Modified: pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/engine.py
==============================================================================
--- pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/engine.py (original)
+++ pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/engine.py Fri May 18 14:35:12 2007
@@ -3,7 +3,8 @@
from pypy.lang.prolog.interpreter.error import UnificationFailed, FunctionNotFound, \
CutException
from pypy.lang.prolog.interpreter import error
-from pypy.rlib.objectmodel import hint, specialize
+from pypy.rlib.objectmodel import hint, specialize, _is_early_constant
+from pypy.rlib.unroll import unrolling_iterable
DEBUG = False
@@ -95,6 +96,7 @@
return result
class LinkedRules(object):
+ _immutable_ = True
def __init__(self, rule, next=None):
self.rule = rule
self.next = next
@@ -114,13 +116,19 @@
#import pdb;pdb.set_trace()
while self:
uh = self.rule.unify_hash
- for j in range(len(uh)):
+ hint(uh, concrete=True)
+ uh = hint(uh, deepfreeze=True)
+ j = 0
+ while j < len(uh):
+ hint(j, concrete=True)
hash1 = uh[j]
hash2 = query.unify_hash_of_child(j)
if hash1 != 0 and hash2 != 0 and hash1 != hash2:
break
+ j += 1
else:
- return self
+ #XXX otherwise the result is green which seems wrong
+ return hint(self, variable=True)
self = self.next
return None
@@ -128,14 +136,19 @@
return "LinkedRules(%r, %r)" % (self.rule, self.next)
+
class Function(object):
- def __init__(self, firstrule):
- self.rulechain = LinkedRules(firstrule)
- self.last = self.rulechain
+ def __init__(self, firstrule=None):
+ if firstrule is None:
+ self.rulechain = self.last = None
+ else:
+ self.rulechain = LinkedRules(firstrule)
+ self.last = self.rulechain
def add_rule(self, rule, end):
- #import pdb; pdb.set_trace()
- if end:
+ if self.rulechain is None:
+ self.rulechain = self.last = LinkedRules(rule)
+ elif end:
self.rulechain, last = self.rulechain.copy()
self.last = LinkedRules(rule)
last.next = self.last
@@ -146,13 +159,17 @@
self.rulechain, last = self.rulechain.copy(rulechain)
last.next = rulechain.next
+
class Engine(object):
def __init__(self):
self.heap = Heap()
self.signature2function = {}
self.parser = None
self.operations = None
-
+ #XXX circular imports hack
+ from pypy.lang.prolog.builtin import builtins_list
+ globals()['unrolling_builtins'] = unrolling_iterable(builtins_list)
+
def add_rule(self, rule, end=True):
from pypy.lang.prolog import builtin
if DEBUG:
@@ -204,29 +221,57 @@
def call(self, query, continuation=DONOTHING):
assert isinstance(query, Callable)
- from pypy.lang.prolog.builtin import builtins
if DEBUG:
debug_print("calling", query)
signature = query.signature
# check for builtins
- builtins = hint(builtins, deepfreeze=True)
+ if _is_early_constant(signature):
+ for bsig, builtin in unrolling_builtins:
+ if signature == bsig:
+ #XXX should be:
+ #return builtin.call(self, query, continuation)
+ # but then the JIT explodes sometimes for funny reasons
+ return builtin.function(self, query, continuation)
+ # do a real call
+ return self.user_call(query, continuation)
+ else:
+ return self._opaque_call(signature, query, continuation)
+
+ def _opaque_call(self, signature, query, continuation):
+ from pypy.lang.prolog.builtin import builtins
+ #builtins = hint(builtins, deepfreeze=True)
builtin = builtins.get(signature, None)
if builtin is not None:
- return builtin.call(self, query, continuation)
+ #XXX should be:
+ #return builtin.call(self, query, continuation)
+ # but then the JIT explodes sometimes for funny reasons
+ return builtin.function(self, query, continuation)
# do a real call
return self.user_call(query, continuation)
+ def _jit_lookup(self, signature):
+ signature2function = self.signature2function
+ function = signature2function.get(signature, None)
+ if function is None:
+ signature2function[signature] = function = Function()
+ return function
+ _jit_lookup._pure_function_ = True
+
def user_call(self, query, continuation):
#import pdb; pdb.set_trace()
- signature = query.signature
- function = self.signature2function.get(signature, None)
- if function is None:
+ signature = hint(query.signature, promote=True)
+ function = self._jit_lookup(signature)
+ startrulechain = function.rulechain
+ startrulechain = hint(startrulechain, promote=True)
+ if startrulechain is None:
error.throw_existence_error(
"procedure", query.get_prolog_signature())
- rulechain = function.rulechain.find_applicable_rule(query)
+
+ rulechain = startrulechain.find_applicable_rule(query)
if rulechain is None:
# none of the rules apply
raise UnificationFailed()
+ rulechain = hint(rulechain, promote=True)
rule = rulechain.rule
rulechain = rulechain.next
oldstate = self.heap.branch()
@@ -235,6 +280,8 @@
if rulechain is None:
self.heap.discard(oldstate)
break
+ rulechain = hint(rulechain, promote=True)
+ hint(rule, concrete=True)
if rule.contains_cut:
continuation = LimitedScopeContinuation(continuation)
try:
@@ -257,6 +304,7 @@
self.heap.revert(oldstate)
rule = rulechain.rule
rulechain = rulechain.next
+ hint(rule, concrete=True)
if rule.contains_cut:
continuation = LimitedScopeContinuation(continuation)
try:
@@ -268,9 +316,12 @@
return self.try_rule(rule, query, continuation)
def try_rule(self, rule, query, continuation=DONOTHING):
+ return self._portal_try_rule(rule, query, continuation)
+
+ def _portal_try_rule(self, rule, query, continuation=DONOTHING):
hint(None, global_merge_point=True)
- rule = hint(rule, promote=True)
rule = hint(rule, deepfreeze=True)
+ hint(self, concrete=True)
if DEBUG:
debug_print("trying rule", rule, query, self.heap.vars[:self.heap.needed_vars])
# standardizing apart
@@ -284,7 +335,6 @@
continuation.call(self)
return "yes"
-
def continue_after_cut(self, continuation, lsc=None):
while 1:
try:
@@ -306,3 +356,7 @@
if self.operations is None:
return default_operations
return self.operations
+
+
+
+
Modified: pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/portal.py
==============================================================================
--- pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/portal.py (original)
+++ pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/portal.py Fri May 18 14:35:12 2007
@@ -11,7 +11,7 @@
'pypy.lang.prolog.builtin.register': True
}
-PORTAL = engine.Engine.try_rule
+PORTAL = engine.Engine._portal_try_rule.im_func
class PyrologHintAnnotatorPolicy(HintAnnotatorPolicy):
novirtualcontainer = True
@@ -126,13 +126,21 @@
seegraph(cls.copy)
seegraph(cls.__init__)
seegraph(cls.copy_and_unify)
+ seegraph(cls.unify_hash_of_child)
for cls in [term.Term, term.Number, term.Atom]:
seegraph(cls.copy_and_basic_unify)
+ seegraph(cls.dereference)
seegraph(cls.copy_and_basic_unify)
+ for cls in [term.Var, term.Term, term.Number, term.Atom]:
+ seegraph(cls.get_unify_hash)
+ for cls in [term.Callable, term.Atom, term.Term]:
+ seegraph(cls.get_prolog_signature)
+ seegraph(PORTAL)
seegraph(pypy.lang.prolog.interpreter.engine.Heap.newvar)
- seegraph(pypy.lang.prolog.interpreter.engine.Engine.try_rule)
seegraph(pypy.lang.prolog.interpreter.term.Rule.clone_and_unify_head)
seegraph(pypy.lang.prolog.interpreter.engine.Engine.call)
+ seegraph(pypy.lang.prolog.interpreter.engine.Engine.user_call)
+ seegraph(pypy.lang.prolog.interpreter.engine.LinkedRules.find_applicable_rule)
return result_graphs
def get_portal(drv):
Modified: pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/term.py
==============================================================================
--- pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/term.py (original)
+++ pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/term.py Fri May 18 14:35:12 2007
@@ -18,6 +18,10 @@
if DEBUG and not we_are_translated():
print " ".join([str(a) for a in args])
+def pure_hash_function(s):
+ return h(s)
+pure_hash_function._pure_function_ = True
+
class PrologObject(object):
__slots__ = ()
_immutable_ = True
@@ -49,7 +53,7 @@
# they must not be unifiable
raise NotImplementedError("abstract base class")
- def unify_hash_of_child(self, i, heap=None):
+ def unify_hash_of_child(self, i):
raise KeyError
@specialize.arg(3)
@@ -79,6 +83,7 @@
__slots__ = ('index', )
cache = {}
+ _immutable_ = True
def __init__(self, index):
self.index = index
@@ -223,6 +228,7 @@
STANDARD_ORDER = 1
cache = {}
+ _immutable_ = True
def __init__(self, name):
self.name = name
@@ -253,10 +259,11 @@
raise UnificationFailed
def get_unify_hash(self):
- return intmask(hash(self.name) << TAGBITS | self.TAG)
+ name = hint(self.name, promote=True)
+ return intmask(pure_hash_function(name) << TAGBITS | self.TAG)
def get_prolog_signature(self):
- return Term("/", [self, Number(0)])
+ return Term("/", [self, NUMBER_0])
def newatom(name):
result = Atom.cache.get(name, None)
@@ -270,6 +277,7 @@
class Number(NonVar):
TAG = tag()
STANDARD_ORDER = 2
+ _immutable_ = True
def __init__(self, num):
self.num = num
@@ -298,10 +306,12 @@
def get_unify_hash(self):
return intmask(self.num << TAGBITS | self.TAG)
+NUMBER_0 = Number(0)
class Float(NonVar):
TAG = tag()
STANDARD_ORDER = 2
+ _immutable_ = True
def __init__(self, num):
self.num = num
@@ -374,6 +384,7 @@
class Term(Callable):
TAG = tag()
STANDARD_ORDER = 3
+ _immutable_ = True
def __init__(self, name, args, signature=None):
self.name = name
self.args = args
@@ -453,7 +464,8 @@
return self
def get_unify_hash(self):
- return intmask(hash(self.signature) << TAGBITS | self.TAG)
+ signature = hint(self.signature, promote=True)
+ return intmask(pure_hash_function(signature) << TAGBITS | self.TAG)
def unify_hash_of_child(self, i):
return self.args[i].get_unify_hash()
@@ -506,6 +518,7 @@
def clone_and_unify_head(self, heap, head):
memo = {}
h2 = self.head
+ hint(h2, concrete=True)
if isinstance(h2, Term):
assert isinstance(head, Term)
i = 0
@@ -516,6 +529,7 @@
arg2.copy_and_unify(arg1, heap, memo)
i += 1
body = self.body
+ hint(body, concrete=True)
if body is None:
return None
return body.copy(heap, memo)
Modified: pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/test/test_jit.py
==============================================================================
--- pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/test/test_jit.py (original)
+++ pypy/branch/prolog-jit-experiments/pypy/lang/prolog/interpreter/test/test_jit.py Fri May 18 14:35:12 2007
@@ -1,5 +1,5 @@
import py
-from pypy.jit.timeshifter.test.test_portal import PortalTest
+from pypy.jit.timeshifter.test.test_portal import PortalTest, P_NOVIRTUAL
from pypy.lang.prolog.interpreter import portal
from pypy.lang.prolog.interpreter import engine, term
from pypy.lang.prolog.interpreter.parsing import parse_query_term, get_engine
@@ -37,11 +37,59 @@
assert res == True
- res = self.timeshift_from_portal(main, engine.Engine.try_rule.im_func,
+ res = self.timeshift_from_portal(main, portal.PORTAL,
[1], policy=POLICY)
assert res == True
- res = self.timeshift_from_portal(main, engine.Engine.try_rule.im_func,
+ res = self.timeshift_from_portal(main, portal.PORTAL,
+ [0], policy=POLICY)
+ assert res == True
+
+ def test_and(self):
+ e = get_engine("""
+ b(a).
+ a(a).
+ f(X) :- b(X), a(X).
+ """)
+ X = e.heap.newvar()
+
+ def main(n):
+ e.heap.reset()
+ if n == 0:
+ e.call(term.Term("f", [X]))
+ return isinstance(X.dereference(e.heap), term.Atom)
+ else:
+ return False
+
+ res = main(0)
+ assert res == True
+
+ res = self.timeshift_from_portal(main, portal.PORTAL,
+ [0], policy=POLICY)
+ assert res == True
+
+ def test_user_call(self):
+ e = get_engine("""
+ h(X) :- f(X, b).
+ f(a, a).
+ f(X, b) :- g(X).
+ g(b).
+ """)
+ X = e.heap.newvar()
+
+ def main(n):
+ e.heap.reset()
+ if n == 0:
+ e.call(term.Term("h", [X]))
+ return isinstance(X.dereference(e.heap), term.Atom)
+ else:
+ return False
+
+ res = main(0)
+ assert res == True
+
+
+ res = self.timeshift_from_portal(main, portal.PORTAL,
[0], policy=POLICY)
assert res == True
More information about the Pypy-commit
mailing list