Permalink
Browse files

Hacky workaround for generator_exception.py bug.

Might come up with something better later.

This fixes one Oil unit test failure, still have 3.

Move the speed test into test.sh.  That's relevant to the bug fix.
  • Loading branch information...
Andy Chu
Andy Chu committed Apr 7, 2018
1 parent 7d8f668 commit 04d9f6ccb4528beb82cd1d6721673268ca2f1901
Showing with 91 additions and 73 deletions.
  1. +14 −9 opy/byterun/pyobj.py
  2. +19 −1 opy/byterun/pyvm2.py
  3. +7 −0 opy/common.sh
  4. +0 −63 opy/smoke.sh
  5. +35 −0 opy/test.sh
  6. +11 −0 opy/testdata/speed.py
  7. +5 −0 opy/testdata/speed_main.py
View
@@ -294,10 +294,8 @@ def decode_next(self):
"""
byteCode = ord(self.f_code.co_code[self.f_lasti])
self.f_lasti += 1
byteName = dis.opname[byteCode]
arg = None
arguments = []
arguments = []
if byteCode >= dis.HAVE_ARGUMENT:
arg = self.f_code.co_code[self.f_lasti : self.f_lasti+2]
self.f_lasti += 2
@@ -322,9 +320,9 @@ def decode_next(self):
arg = intArg
arguments = [arg]
byteName = dis.opname[byteCode]
return byteName, arguments
def line_number(self):
"""Get the current line number the frame is executing."""
# We don't keep f_lineno up to date, so calculate it based on the
@@ -350,25 +348,32 @@ def line_number(self):
class Generator(object):
def __init__(self, g_frame, vm):
self.gi_frame = g_frame
self.g_frame = g_frame
self._vm = vm
self.started = False
self.finished = False
# Part of the iterator protocol.
def __iter__(self):
"""DO_NOT_INTERPRET"""
return self
# Part of the iterator protocol.
def next(self):
"""DO_NOT_INTERPRET"""
# Docstring is a hack for pyvm2 ! Is there a better way?
# This is a THIRD path for a function.
return self.send(None)
# Part of the iterator protocol.
def send(self, value=None):
"""DO_NOT_INTERPRET"""
if not self.started and value is not None:
raise TypeError("Can't send non-None value to a just-started generator")
self.gi_frame.stack.append(value)
self.g_frame.stack.append(value)
self.started = True
val = self._vm.resume_frame(self.gi_frame)
val = self._vm.resume_frame(self.g_frame)
if self.finished:
raise StopIteration(val)
return val
__next__ = next
View
@@ -874,9 +874,27 @@ def call_function(self, arg, args, kwargs):
# MAKE_FUNCTION, which properly turns them into pyobj.Function.
# 3. User-defined function from another module. These are created with
# __import__, which yields a native function.
# 4. pyobj.Generator is on the stack, and you get its next() value.
# We should do something smarter.
# This check is broken!
# next() and send() that is a native python function. We dO NOt need
# to wrap it.
interpret_bytecode = False
if isinstance(func, types.FunctionType):
debug1('*** WRAPPING %s', func)
interpret_bytecode = True
# Hack for case #4.
if getattr(func, '__doc__', None) == 'DO_NOT_INTERPRET':
interpret_bytecode = False
#raise AssertionError
if interpret_bytecode:
#debug1('*** WRAPPING %s', func)
#debug1('%s', dir(func))
#debug1('__doc__ %s', func.__doc__)
defaults = func.func_defaults or ()
byterun_func = Function(
func.func_name, func.func_code, func.func_globals,
View
@@ -69,3 +69,10 @@ oil-python-sources() {
-name '*.py' -a -printf "$fmt"
}
opyc-run() {
../bin/opyc run "$@"
}
opyc-compile() {
../bin/opyc compile "$@"
}
View
@@ -39,69 +39,6 @@ zip-oil-tree() {
popd
}
write-speed() {
cat >_tmp/speed.py <<EOF
def do_sum(n):
sum = 0
for i in xrange(n):
sum += i
print(sum)
if __name__ == '__main__':
import sys
n = int(sys.argv[1])
do_sum(n)
EOF
cat >_tmp/speed_main.py <<EOF
import sys
import speed
n = int(sys.argv[1])
speed.do_sum(n)
EOF
}
opyc-run() {
../bin/opyc run "$@"
}
opyc-compile() {
../bin/opyc compile "$@"
}
opy-speed-test() {
write-speed
opyc-compile _tmp/speed.py _tmp/speed.pyc
opyc-compile _tmp/speed_main.py _tmp/speed_main.pyc
cp _tmp/speed.pyc _tmp/speed.opyc
# For logging
local n=10000
#local n=10
# 7 ms
echo PYTHON
time python _tmp/speed.opyc $n
# 205 ms. So it's 30x slower. Makes sense.
echo OPY
time opyc-run _tmp/speed.opyc $n
#
# byterun Import bug regression test!
#
# 7 ms
echo PYTHON
time python _tmp/speed_main.pyc $n
# 205 ms. So it's 30x slower. Makes sense.
echo OPY
time opyc-run _tmp/speed_main.pyc $n
}
_byterun() {
# Wow this is SO confusing.
# Not executable on master branch
View
@@ -10,6 +10,7 @@ set -o errexit
readonly THIS_DIR=$(cd $(dirname $0) && pwd)
readonly OPYC=$THIS_DIR/../bin/opyc
source $THIS_DIR/common.sh
osh-opy() {
_tmp/oil-opy/bin/osh "$@"
@@ -199,4 +200,38 @@ spec() {
popd
}
# The way to tickle the 'import' bug. We need to wrap SOME functions in
# pyobj.Function. Otherwise it will run too fast!
opy-speed-test() {
opyc-compile testdata/speed.py _tmp/speed.pyc
opyc-compile testdata/speed_main.py _tmp/speed_main.pyc
cp _tmp/speed.pyc _tmp/speed.opyc
# For logging
local n=10000
#local n=10
# 7 ms
echo PYTHON
time python _tmp/speed.opyc $n
# 205 ms. So it's 30x slower. Makes sense.
echo OPY
time opyc-run _tmp/speed.opyc $n
#
# byterun Import bug regression test!
#
# 7 ms
echo PYTHON
time python _tmp/speed_main.pyc $n
# 205 ms. So it's 30x slower. Makes sense.
echo OPY
time opyc-run _tmp/speed_main.pyc $n
}
"$@"
View
@@ -0,0 +1,11 @@
def do_sum(n):
sum = 0
for i in xrange(n):
sum += i
print(sum)
if __name__ == '__main__':
import sys
n = int(sys.argv[1])
do_sum(n)
@@ -0,0 +1,5 @@
import sys
import speed
n = int(sys.argv[1])
speed.do_sum(n)

0 comments on commit 04d9f6c

Please sign in to comment.