Permalink
Browse files

A better fix for OPy determinism: add __hash__ on Block.

It now uses a deterministic integer ID instead of id(), which is based
on the memory address.

Verified that ALL bytecode in _build/oil/bytecode-opy/... is stable
across machines.

With the sorted() fix, it would pass opy-determinism-loop on
core/word_compile.py.  However, there was still nondeterminism across
machines.  This is likely due to the fact that I used sorted(), but
__cmp__ wasn't specified.

Adding __hash__ results in a process that's still deterministic, and
presumably faster than calling sorted() everywhere.
  • Loading branch information...
Andy Chu
Andy Chu committed Mar 17, 2018
1 parent d657c8e commit 3cfc21b8ce451739eaa4d46111e2ddf775e82494
Showing with 22 additions and 8 deletions.
  1. +9 −3 opy/compiler2/pyassem.py
  2. +13 −5 opy/smoke.sh
View
@@ -120,7 +120,7 @@ def order_blocks(start_block, exit_block):
# A block is dominated by another block if that block must be emitted
# before it.
dominators = {}
for b in sorted(remaining): # ANDY FIX: sorted() determinism
for b in remaining:
if __debug__ and b.next:
assert b is b.next[0].prev[0], (b, b.next)
# Make sure every block appears in dominators, even if no
@@ -140,8 +140,8 @@ def order_blocks(start_block, exit_block):
def find_next():
# Find a block that can be emitted next.
for b in sorted(remaining): # ANDY FIX: sorted determinism
for c in sorted(dominators[b]): # ditto
for b in remaining:
for c in dominators[b]:
if c in remaining:
break # can't emit yet, dominated by a remaining block
else:
@@ -175,6 +175,12 @@ def __init__(self, label=''):
self.prev = []
Block._count = Block._count + 1
# BUG FIX: This is needed for deterministic order in sets (and dicts?).
# See order_blocks() below. remaining is set() of blocks. If we rely on
# the default id(), then the output bytecode is NONDETERMINISTIC.
def __hash__(self):
return self.bid
def __repr__(self):
if self.label:
return "<block %s id=%d>" % (self.label, self.bid)
View
@@ -241,8 +241,8 @@ stdlib-compile() { misc/stdlib_compile.py "$@"; }
# FAILS
opy-determinism-loop() {
#local file=../core/lexer.py
#local file=../core/word_compile.py # FIXED
local file=../Python-2.7.13/Lib/genericpath.py
local file=../core/word_compile.py # FIXED
#local file=../Python-2.7.13/Lib/genericpath.py
determinism-loop opyc-compile $file
}
@@ -286,9 +286,17 @@ rebuild-and-md5() {
copy-left-right() {
local src=flanders.local:~/git/oilshell/oil
mkdir -p _tmp/flanders _tmp/lisa
scp $src/_build/oil/bytecode-opy.zip $src/_tmp/flanders.pyc-md5.txt _tmp/flanders
scp $src/_build/oil/bytecode-opy.zip $src/_tmp/pyc-md5.txt _tmp/flanders
src=..
cp -v $src/_build/oil/bytecode-opy.zip $src/_tmp/lisa.pyc-md5.txt _tmp/lisa
cp -v $src/_build/oil/bytecode-opy.zip $src/_tmp/pyc-md5.txt _tmp/lisa
}
diff-left-right() {
if diff _tmp/{lisa,flanders}/pyc-md5.txt; then
echo SAME
else
echo DIFFERENT
fi
}
unzip-left-right() {
@@ -299,7 +307,7 @@ unzip-left-right() {
done
}
diff-left-right() {
diff-one-left-right() {
for host in lisa flanders; do
opyc-dis _tmp/$host/core/word_compile.pyc > _tmp/$host/word_compile.dis
done

0 comments on commit 3cfc21b

Please sign in to comment.