• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

A categorical programming language


Commit MetaInfo

Revisiónbe55e727840cd7ed53fc8a9d8a92802aedf578f8 (tree)
Tiempo2022-04-13 13:52:38
AutorCorbin <cds@corb...>
CommiterCorbin

Log Message

Start optimizing emitted bytecode.

Cambiar Resumen

Diferencia incremental

--- a/cammy-rpy/cammylib/arrows.py
+++ b/cammy-rpy/cammylib/arrows.py
@@ -277,7 +277,7 @@ FZero = makeConstantF(0.0)
277277 FOne = makeConstantF(1.0)
278278 FPi = makeConstantF(math.pi)
279279
280-def sign(f): return math.copysign(1.0, f) > 0.0
280+def sign(f): return abs(f) == f
281281 class FSign(Arrow):
282282 _immutable_ = True
283283 def compile(self, compiler): compiler.sign()
--- a/cammy-rpy/cammylib/cam.py
+++ b/cammy-rpy/cammylib/cam.py
@@ -69,11 +69,11 @@ class CAM(object):
6969 return runCAM(self.code, self.constants, term)
7070
7171
72-def location(pc, code):
72+def location(pc, code, constants):
7373 return "%d: %s" % (pc, decode(code[pc]))
7474
7575 CAMDriver = JitDriver(name="cam",
76- greens=["pc", "code"], reds="auto",
76+ greens=["pc", "code", "constants"], reds=["term", "stack"],
7777 get_printable_location=location,
7878 is_recursive=True)
7979
@@ -82,7 +82,8 @@ def runCAM(code, constants, term):
8282 stack = T()
8383
8484 while pc < len(code):
85- CAMDriver.jit_merge_point(code=code, pc=pc)
85+ CAMDriver.jit_merge_point(pc=pc, code=code, constants=constants,
86+ term=term, stack=stack)
8687 op = code[pc]; pc += 1
8788
8889 # print "pc", self.pc, "op", decode(op)
@@ -116,13 +117,19 @@ def runCAM(code, constants, term):
116117 stack = P(N(pc), stack.second())
117118 term = P(v1, v2)
118119 pc = l
120+ CAMDriver.can_enter_jit(pc=pc, code=code, constants=constants,
121+ term=term, stack=stack)
119122 elif op == BRANCH:
120123 term = L(T()) if term.b() else R(T())
121124 elif op == RET:
122125 pc = stack.first().n()
123126 stack = stack.second()
127+ CAMDriver.can_enter_jit(pc=pc, code=code, constants=constants,
128+ term=term, stack=stack)
124129 elif op == GOTO:
125130 pc = code[pc]
131+ CAMDriver.can_enter_jit(pc=pc, code=code, constants=constants,
132+ term=term, stack=stack)
126133 elif op == HALT:
127134 return term
128135 elif op == LEFT:
@@ -194,6 +201,14 @@ class Compiler(object):
194201 Compile an arrow to CAM bytecode.
195202 """
196203
204+ # The location behind which we will not erase any instructions during
205+ # peephole optimization. Labels behind the barrier will not shift.
206+ barrier = 0
207+
208+ # The last location that was written, to make it easy to erase bytecodes
209+ # with parameters.
210+ lastLocation = 0
211+
197212 def __init__(self):
198213 self.constants = []
199214 self.insts = []
@@ -204,6 +219,19 @@ class Compiler(object):
204219 # Queue of curried arrows to compile.
205220 self.curryQueue = []
206221
222+ def emit(self, inst):
223+ self.insts.append(inst)
224+
225+ def emitParam(self, inst, param):
226+ self.lastLocation = len(self.insts)
227+ self.insts.append(inst)
228+ self.insts.append(param)
229+
230+ def peek(self, inst):
231+ # if self.lastLocation < len(self.insts):
232+ # return self.insts[self.lastLocation] == inst
233+ return False
234+
207235 def quote(self, constant):
208236 # Don't repeat constants.
209237 for i, const in enumerate(self.constants):
@@ -213,18 +241,26 @@ class Compiler(object):
213241 else:
214242 c = len(self.constants)
215243 self.constants.append(constant)
216- self.insts.append(QUOTE)
217- self.insts.append(c)
244+ if self.peek(QUOTE):
245+ # Peephole: QUOTE c; QUOTE d -> QUOTE d
246+ # XXX icky patch
247+ # XXX respect the barrier!!
248+ self.insts[-1] = c
249+ else:
250+ self.emitParam(QUOTE, c)
218251
219252 # A label is a location where execution can go. A (forward) jump is a
220253 # location that needs to be patched with a label. Backward jumps are
221- # emitted immediately without a patch site.
254+ # emitted immediately without a patch site. To protect labels from
255+ # shifting during peephole optimization, a barrier is shifted forward to
256+ # commit to each label as it is taken.
222257
223258 def here(self):
224- return len(self.insts)
259+ rv = self.barrier = len(self.insts)
260+ return rv
225261
226262 def jumpForward(self):
227- rv = len(self.insts)
263+ rv = self.barrier = len(self.insts)
228264 self.insts.append(-1)
229265 return rv
230266
@@ -232,7 +268,7 @@ class Compiler(object):
232268 self.insts.append(label)
233269
234270 def jumpHere(self, jump):
235- self.insts[jump] = len(self.insts)
271+ self.insts[jump] = self.barrier = len(self.insts)
236272
237273 def curry(self, arrow):
238274 self.insts.append(CUR)
@@ -244,6 +280,7 @@ class Compiler(object):
244280 self.halt()
245281 while self.curryQueue:
246282 jump, arrow = self.curryQueue.pop()
283+ # XXX if already seen this arrow, then jump to it instead
247284 self.jumpHere(jump)
248285 arrow.compile(self)
249286 self.ret()
@@ -251,38 +288,38 @@ class Compiler(object):
251288 def makeMachine(self):
252289 return CAM(self.insts[:], self.constants[:])
253290
254- def fst(self): self.insts.append(FST)
255- def snd(self): self.insts.append(SND)
256- def push(self): self.insts.append(PUSH)
257- def pop(self): self.insts.append(POP)
258- def swap(self): self.insts.append(SWAP)
259- def cons(self): self.insts.append(CONS)
260- def app(self): self.insts.append(APP)
261- def branch(self): self.insts.append(BRANCH)
262- def ret(self): self.insts.append(RET)
263- def goto(self): self.insts.append(GOTO)
264- def halt(self): self.insts.append(HALT)
265- def left(self): self.insts.append(LEFT)
266- def right(self): self.insts.append(RIGHT)
267- def gotoRight(self): self.insts.append(GOTORIGHT)
268- def notOp(self): self.insts.append(NOTOP)
269- def andOp(self): self.insts.append(ANDOP)
270- def orOp(self): self.insts.append(OROP)
271- def pred(self): self.insts.append(PRED)
272- def succ(self): self.insts.append(SUCC)
273- def isNil(self): self.insts.append(ISNIL)
274- def assoc(self): self.insts.append(ASSOC)
275- def sign(self): self.insts.append(SIGN)
276- def floor(self): self.insts.append(FLOOR)
277- def negate(self): self.insts.append(NEGATE)
278- def recip(self): self.insts.append(RECIP)
279- def lessThan(self): self.insts.append(LESSTHAN)
280- def add(self): self.insts.append(ADD)
281- def mul(self): self.insts.append(MUL)
282- def sqrt(self): self.insts.append(SQRT)
283- def sin(self): self.insts.append(SIN)
284- def cos(self): self.insts.append(COS)
285- def atan2(self): self.insts.append(ATAN2)
291+ def fst(self): self.emit(FST)
292+ def snd(self): self.emit(SND)
293+ def push(self): self.emit(PUSH)
294+ def pop(self): self.emit(POP)
295+ def swap(self): self.emit(SWAP)
296+ def cons(self): self.emit(CONS)
297+ def app(self): self.emit(APP)
298+ def branch(self): self.emit(BRANCH)
299+ def ret(self): self.emit(RET)
300+ def goto(self): self.emit(GOTO)
301+ def halt(self): self.emit(HALT)
302+ def left(self): self.emit(LEFT)
303+ def right(self): self.emit(RIGHT)
304+ def gotoRight(self): self.emit(GOTORIGHT)
305+ def notOp(self): self.emit(NOTOP)
306+ def andOp(self): self.emit(ANDOP)
307+ def orOp(self): self.emit(OROP)
308+ def pred(self): self.emit(PRED)
309+ def succ(self): self.emit(SUCC)
310+ def isNil(self): self.emit(ISNIL)
311+ def assoc(self): self.emit(ASSOC)
312+ def sign(self): self.emit(SIGN)
313+ def floor(self): self.emit(FLOOR)
314+ def negate(self): self.emit(NEGATE)
315+ def recip(self): self.emit(RECIP)
316+ def lessThan(self): self.emit(LESSTHAN)
317+ def add(self): self.emit(ADD)
318+ def mul(self): self.emit(MUL)
319+ def sqrt(self): self.emit(SQRT)
320+ def sin(self): self.emit(SIN)
321+ def cos(self): self.emit(COS)
322+ def atan2(self): self.emit(ATAN2)
286323
287324 # Generate most of the emission methods.
288325 # insts = ("fst", "snd", "push", "pop", "swap", "cons", "app", "branch", "ret",
--- a/cammy-rpy/cammylib/elements.py
+++ b/cammy-rpy/cammylib/elements.py
@@ -1,6 +1,6 @@
11 import math
22
3-from rpython.rlib.jit import promote, we_are_jitted
3+from rpython.rlib.jit import we_are_jitted
44 # from rpython.rlib.rbigint import rbigint
55
66
@@ -109,30 +109,10 @@ class R(Element):
109109 def asStr(self):
110110 return "R(%s)" % self._x.asStr()
111111
112-class H(Element):
113- _immutable_ = True
114- def __init__(self, f, x):
115- self._f = f
116- self._x = x
117- def apply(self, y):
118- # Defunctionalize by assuming that f can only take on finitely many
119- # values. This trick was suggested by cfbolz; they do a similar trick
120- # in Pycket for similar ends.
121- return promote(self._f).run(P(self._x, y))
122- def asStr(self):
123- return "%s @ %s" % (self._f, self._x.asStr())
124-
125-class Xs(Element):
126- _immutable_ = True
127- _immutable_fields_ = "xs[*]",
128- def __init__(self, xs):
129- self.xs = xs
130- def l(self): return self.xs
131- def asStr(self):
132- return "[%s]" % ", ".join([x.asStr() for x in self.xs])
133-
134112
135113 def equal(e1, e2):
114+ if e1 is e2:
115+ return True
136116 return False
137117 # if isinstance(e1, T) and isinstance(e2, T):
138118 # return True
@@ -150,12 +130,3 @@ def equal(e1, e2):
150130 # return equal(e1._x, e2._x)
151131 # elif isinstance(e1, R) and isinstance(e2, R):
152132 # return equal(e1._x, e2._x)
153- # elif isinstance(e1, Xs) and isinstance(e2, Xs):
154- # if len(e1.xs) != len(e2.xs):
155- # return False
156- # for i, x in enumerate(e1.xs):
157- # if not equal(x, e2.xs[i]):
158- # return False
159- # return True
160- # else:
161- # return False
--- a/todo.txt
+++ b/todo.txt
@@ -97,6 +97,17 @@
9797 recompute jumps
9898 * TCO, or really any call optimizations
9999 * snoc and other backwards versions of ops
100+ * term ops can be applied to quoted elements, creating new quotes with
101+ pre-computed elements
102+ * needs equality for elements
103+ * curried arrows sometimes repeat, or at least they compile down to the same
104+ code
105+ * needs equality for arrows
106+ * sometimes we end up with two quotes in a row, should only use the second
107+ * requires code barrier
108+ * Currying everything really does look like it might generate better
109+ bytecode
110+ * Or at least let binary term ops be stack ops?
100111 * fun/precomp is an ingredient of CPS transformation
101112 * https://okmij.org/ftp/continuations/undelimited.html
102113 * A serious cost model