The following invocation
pike -e 'foo: for(;;) { catch { catch { break foo; }; }; }'
makes Pike bomb out on POWER with machine code optimizations. The stack is a little too messed up for me to figure out where it went wrong just from the post mortem though. What sequence of bytecodes will be generated by this code?
Ah. Replacing the implementation of F_ESCAPE_CATCH fixed the problem. *committing*
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2002-09-22 23:15: Subject: catch { catch { break foo; }; };
The following invocation
pike -e 'foo: for(;;) { catch { catch { break foo; }; }; }'
makes Pike bomb out on POWER with machine code optimizations. The stack is a little too messed up for me to figure out where it went wrong just from the post mortem though. What sequence of bytecodes will be generated by this code?
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Hmm... That implementation uses the toc. Does that work on MacOS X and Linux?
/ Henrik Grubbström (Lysator)
Previous text:
2002-09-23 00:04: Subject: catch { catch { break foo; }; };
Ah. Replacing the implementation of F_ESCAPE_CATCH fixed the problem. *committing*
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Should hope so. MacOS X uses PowerOpen ABI which is based on AIX, so it also has toc in r2. Linux is SVR4, where r2 is just "reserved for system", but I'm pretty sure GCC will use it for toc anyway. It would be a pain in the a$$ for a compiler to generate code without a toc.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2002-09-23 11:32: Subject: catch { catch { break foo; }; };
Hmm... That implementation uses the toc. Does that work on MacOS X and Linux?
/ Henrik Grubbström (Lysator)
Make verify on Linux/PPC succeeded apart from the following:
Doing tests in tlib/modules/Tools.pmod/testsuite (1 tests) Error: ({ /* 3 elements */ "a=2.0;", "2,000000", "2.000000" }) Error: ({ /* 3 elements */ "i;", "Image.Image( 0 x 0 /* 0,0Kb */)", "Image.Image( 0 x 0 /* 0.0Kb */)" })
Failed tests: 2.
which I'm unsure how to interpret, but it's probably not related to F_ESCAPE_CATCH at all.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2002-09-23 12:37: Subject: catch { catch { break foo; }; };
Should hope so. MacOS X uses PowerOpen ABI which is based on AIX, so it also has toc in r2. Linux is SVR4, where r2 is just "reserved for system", but I'm pretty sure GCC will use it for toc anyway. It would be a pain in the a$$ for a compiler to generate code without a toc.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
That means that sprintf("%O") and possily sprintf("%f") outputs "," instead of "." as decimal separator. Are there no real sprintf tests elsewhere?
/ Martin Nilsson (Fake Build Master)
Previous text:
2002-09-23 17:09: Subject: catch { catch { break foo; }; };
Make verify on Linux/PPC succeeded apart from the following:
Doing tests in tlib/modules/Tools.pmod/testsuite (1 tests) Error: ({ /* 3 elements */ "a=2.0;", "2,000000", "2.000000" }) Error: ({ /* 3 elements */ "i;", "Image.Image( 0 x 0 /* 0,0Kb */)", "Image.Image( 0 x 0 /* 0.0Kb */)" })
Failed tests: 2.
which I'm unsure how to interpret, but it's probably not related to F_ESCAPE_CATCH at all.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Yes. In src/modules/sprintf/testsuite.in. The test for %f only checks that the result is a string, since the actual contents is locale dependant.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2002-09-23 17:11: Subject: catch { catch { break foo; }; };
That means that sprintf("%O") and possily sprintf("%f") outputs "," instead of "." as decimal separator. Are there no real sprintf tests elsewhere?
/ Martin Nilsson (Fake Build Master)
Ouch. I detect a sudden lack of sprintf documentation. What formats are locale dependent apart from %f? %F, %g, %G, %e, %E (and none of the rest)?
/ Johan Sundström (nu även i Gottfridsberg!)
Previous text:
2002-09-23 17:16: Subject: catch { catch { break foo; }; };
Yes. In src/modules/sprintf/testsuite.in. The test for %f only checks that the result is a string, since the actual contents is locale dependant.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
%F is locale independant. It's always binary IEEE. %g, %G, %e and %E are locale dependant, yes.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2002-09-23 17:21: Subject: catch { catch { break foo; }; };
Ouch. I detect a sudden lack of sprintf documentation. What formats are locale dependent apart from %f? %F, %g, %G, %e, %E (and none of the rest)?
/ Johan Sundström (nu även i Gottfridsberg!)
%O is obviously locale dependent.
/ Martin Nilsson (Fake Build Master)
Previous text:
2002-09-23 17:21: Subject: catch { catch { break foo; }; };
Ouch. I detect a sudden lack of sprintf documentation. What formats are locale dependent apart from %f? %F, %g, %G, %e, %E (and none of the rest)?
/ Johan Sundström (nu även i Gottfridsberg!)
No, %O is dependant on whatever _sprintf is dependant on. Which may be locale, time, phase of the moon, or whatever the person coding the object felt like.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2002-09-23 17:33: Subject: catch { catch { break foo; }; };
%O is obviously locale dependent.
/ Martin Nilsson (Fake Build Master)
The "object" in this case is a float. Is _sprintf still involved?
/ Martin Nilsson (Fake Build Master)
Previous text:
2002-09-23 17:37: Subject: catch { catch { break foo; }; };
No, %O is dependant on whatever _sprintf is dependant on. Which may be locale, time, phase of the moon, or whatever the person coding the object felt like.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Using %O for anything but "debug style" (quote from the current docs) printouts isn't supported, which is about to be elaborated better now.
/ Johan Sundström (nu även i Gottfridsberg!)
Previous text:
2002-09-23 17:39: Subject: catch { catch { break foo; }; };
The "object" in this case is a float. Is _sprintf still involved?
/ Martin Nilsson (Fake Build Master)
I don't thing the dependancy on the locale is intended.
/ Henrik Grubbström (Lysator)
Previous text:
2002-09-23 17:16: Subject: catch { catch { break foo; }; };
Yes. In src/modules/sprintf/testsuite.in. The test for %f only checks that the result is a string, since the actual contents is locale dependant.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
The test uses the number 255.0. To represent this number exactly, 7 bits of mantissa is sufficient. Are we really concerned about systems with less precision than that?
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2002-09-23 17:42: Subject: catch { catch { break foo; }; };
Probably because they don't trust the precision of the decimals.
/ Henrik Grubbström (Lysator)
I'd be happy to see the dependency go away, possibly with some Locale.sprintf method for the old behaviour. Either way, I'll have the docs reflect current reality, and let the next benefactor revert move them to the compat function. :-)
/ Johan Sundström (nu även i Gottfridsberg!)
Previous text:
2002-09-23 17:40: Subject: catch { catch { break foo; }; };
I don't thing the dependancy on the locale is intended.
/ Henrik Grubbström (Lysator)
Actually, it's not, I distincly remember that we tried to work around the locale dependency back in '97 or so.
/ Per Hedbor ()
Previous text:
2002-09-23 17:40: Subject: catch { catch { break foo; }; };
I don't thing the dependancy on the locale is intended.
/ Henrik Grubbström (Lysator)
--assembler-debug=2 or more ought to give it to you. This is what I get after peephole optimization:
=== 1 0 byte(3) === 1 1 byte(3) === 1 2 entry === 1 2 function start === 1 2 label(4) === 1 11 catch(5) === 1 1e catch(7) === 1 27 escape catch === 1 2c escape catch === 1 31 branch(2) === 1 36 label(7) === 1 45 pop === 1 4a throw(0) === 1 4f label(5) === 1 5e pop === 1 63 catch(5) === 1 6c catch(7) === 1 75 escape catch === 1 7a escape catch === 1 7f label(2) === 1 8e return 0
I can't say I understand why the body is repeated twice. It only happens if the for statement lacks the repeat condition.
/ Martin Stjernholm, Roxen IS
Previous text:
2002-09-22 23:15: Subject: catch { catch { break foo; }; };
The following invocation
pike -e 'foo: for(;;) { catch { catch { break foo; }; }; }'
makes Pike bomb out on POWER with machine code optimizations. The stack is a little too messed up for me to figure out where it went wrong just from the post mortem though. What sequence of bytecodes will be generated by this code?
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
The code duplication is due to loop unrolling.
/ Henrik Grubbström (Lysator)
Previous text:
2002-09-23 00:10: Subject: catch { catch { break foo; }; };
--assembler-debug=2 or more ought to give it to you. This is what I get after peephole optimization:
=== 1 0 byte(3) === 1 1 byte(3) === 1 2 entry === 1 2 function start === 1 2 label(4) === 1 11 catch(5) === 1 1e catch(7) === 1 27 escape catch === 1 2c escape catch === 1 31 branch(2) === 1 36 label(7) === 1 45 pop === 1 4a throw(0) === 1 4f label(5) === 1 5e pop === 1 63 catch(5) === 1 6c catch(7) === 1 75 escape catch === 1 7a escape catch === 1 7f label(2) === 1 8e return 0
I can't say I understand why the body is repeated twice. It only happens if the for statement lacks the repeat condition.
/ Martin Stjernholm, Roxen IS
I've replaced the use of throw(0) to exit catch blocks normally with an opcode that uses a normal return instead of a longjmp.
At the same time I changed the default return value from catch blocks to UNDEFINED (it was a "plain" zero earlier), only because I think it's a little cleaner. I don't think it has any practical compatibility impact, but there might be other opinions?
/ Martin Stjernholm, Roxen IS
Previous text:
2002-09-23 00:10: Subject: catch { catch { break foo; }; };
--assembler-debug=2 or more ought to give it to you. This is what I get after peephole optimization:
=== 1 0 byte(3) === 1 1 byte(3) === 1 2 entry === 1 2 function start === 1 2 label(4) === 1 11 catch(5) === 1 1e catch(7) === 1 27 escape catch === 1 2c escape catch === 1 31 branch(2) === 1 36 label(7) === 1 45 pop === 1 4a throw(0) === 1 4f label(5) === 1 5e pop === 1 63 catch(5) === 1 6c catch(7) === 1 75 escape catch === 1 7a escape catch === 1 7f label(2) === 1 8e return 0
I can't say I understand why the body is repeated twice. It only happens if the for statement lacks the repeat condition.
/ Martin Stjernholm, Roxen IS
I've now added a few peep-hole optimization rules. The test program "foo: for(;;) { catch { catch { break foo; }; }; }" is now reduced from:
~~~ 1 0 byte(3) ~~~ 1 1 byte(3) ~~~ 1 2 entry ~~~ 1 3 function start ~~~ 1 4 label(0) ~~~ 1 5 label(4) ~~~ 1 6 catch(5) ~~~ 1 7 catch(7) ~~~ 1 8 escape catch ~~~ 1 9 escape catch ~~~ 1 a branch(2) ~~~ 1 b label(8) ~~~ 1 c exit catch ~~~ 1 d label(7) ~~~ 1 e pop ~~~ 1 f label(6) ~~~ 1 10 exit catch ~~~ 1 11 label(5) ~~~ 1 12 pop ~~~ 1 13 label(3) ~~~ 1 14 catch(5) ~~~ 1 15 catch(7) ~~~ 1 16 escape catch ~~~ 1 17 escape catch ~~~ 1 18 branch(2) ~~~ 1 19 exit catch ~~~ 1 1a pop ~~~ 1 1b exit catch ~~~ 1 1c pop ~~~ 1 1d branch(4) ~~~ 1 1e label(2) ~~~ 1 1f push int(0) ~~~ 1 20 return
to:
=== 1 0 byte(3) === 1 1 byte(3) === 1 2 entry === 1 3 function start === 1 3 return 0
Which I find hard to optimize any further... :-)
/ Henrik Grubbström (Lysator)
Previous text:
2002-09-23 22:25: Subject: catch { catch { break foo; }; };
I've replaced the use of throw(0) to exit catch blocks normally with an opcode that uses a normal return instead of a longjmp.
At the same time I changed the default return value from catch blocks to UNDEFINED (it was a "plain" zero earlier), only because I think it's a little cleaner. I don't think it has any practical compatibility impact, but there might be other opinions?
/ Martin Stjernholm, Roxen IS
But now the test doesn't test multi-level escape catch any more...
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2002-09-24 11:17: Subject: catch { catch { break foo; }; };
I've now added a few peep-hole optimization rules. The test program "foo: for(;;) { catch { catch { break foo; }; }; }" is now reduced from:
~~~ 1 1 byte(3) ~~~ 1 2 entry ~~~ 1 3 function start ~~~ 1 4 label(0) ~~~ 1 5 label(4) ~~~ 1 6 catch(5) ~~~ 1 7 catch(7) ~~~ 1 8 escape catch ~~~ 1 9 escape catch ~~~ 1 a branch(2) ~~~ 1 b label(8) ~~~ 1 c exit catch ~~~ 1 d label(7) ~~~ 1 e pop ~~~ 1 f label(6) ~~~ 1 10 exit catch ~~~ 1 11 label(5) ~~~ 1 12 pop ~~~ 1 13 label(3) ~~~ 1 14 catch(5) ~~~ 1 15 catch(7) ~~~ 1 16 escape catch ~~~ 1 17 escape catch ~~~ 1 18 branch(2) ~~~ 1 19 exit catch ~~~ 1 1a pop ~~~ 1 1b exit catch ~~~ 1 1c pop ~~~ 1 1d branch(4) ~~~ 1 1e label(2) ~~~ 1 1f push int(0) ~~~ 1 20 return to: === 1 0 byte(3) === 1 1 byte(3) === 1 2 entry === 1 3 function start === 1 3 return 0 Which I find hard to optimize any further... :-) / Henrik Grubbström (Lysator)
Easy enough to fix:
'foo: for(;;) { catch { catch { int q=1; break foo; }; }; }'
generates the following code:
=== 1 0 byte(4) === 1 1 byte(3) === 1 2 entry === 1 3 function start === 1 3 catch(5) === 1 a catch(7) === 1 d push 1 === 1 f assign local and pop(3) === 1 11 escape catch === 1 13 escape catch === 1 15 return 0 === 1 17 label(7) === 1 1c pop === 1 1e exit catch === 1 20 label(5) === 1 25 pop === 1 27 catch(5) === 1 2a catch(7) === 1 2d push 1 === 1 2f assign local and pop(3) === 1 31 escape catch === 1 33 escape catch === 1 35 return 0
/ Henrik Grubbström (Lysator)
Previous text:
2002-09-24 12:57: Subject: catch { catch { break foo; }; };
But now the test doesn't test multi-level escape catch any more...
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
As long as the actual test in the testsuite compiles to something with multiple escape catch in it I'm satisifed.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2002-09-24 13:17: Subject: catch { catch { break foo; }; };
Easy enough to fix:
'foo: for(;;) { catch { catch { int q=1; break foo; }; }; }'
generates the following code:
=== 1 0 byte(4) === 1 1 byte(3) === 1 2 entry === 1 3 function start === 1 3 catch(5) === 1 a catch(7) === 1 d push 1 === 1 f assign local and pop(3) === 1 11 escape catch === 1 13 escape catch === 1 15 return 0 === 1 17 label(7) === 1 1c pop === 1 1e exit catch === 1 20 label(5) === 1 25 pop === 1 27 catch(5) === 1 2a catch(7) === 1 2d push 1 === 1 2f assign local and pop(3) === 1 31 escape catch === 1 33 escape catch === 1 35 return 0
/ Henrik Grubbström (Lysator)
Ok, fixed the ones I found.
/ Henrik Grubbström (Lysator)
Previous text:
2002-09-24 13:18: Subject: catch { catch { break foo; }; };
As long as the actual test in the testsuite compiles to something with multiple escape catch in it I'm satisifed.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
I think you made some mistake though:
testsuite:2:parse error, unexpected `';'', expecting `')'' testsuite:2:Missing ')'.
/usr/var/tmp/xenofarm/pike/netbackup1.emsphone.com/buildtmp/Pike7.3-20020924-135500/src/testsuite.in:8816: Test 9958 (shift 2) (CRNL) failed. 0: mixed a() { return 20; } 1: mixed b() { return catch(int q=1; throw(a())); } 2:
Error: Compilation failed. test-install/pike/7.3.56/lib/master.pike:254: master()->compile_string("mixed a() { return 20; }\r\nmixed b() { return catch(int q=1; throw(a())); }\r\nint __cpp_line=__LINE__; int __rtl_line=[int]backtrace()[-1][1];\r\n\r\nint \200001=0;\r\n","testsuite",0) /usr/var/tmp/xenofarm/pike/netbackup1.emsphone.com/buildtmp/Pike7.3-20020924-135500/bin/test_pike.pike:664: main(3,({"/usr/var/tmp/xenofarm/pike/netbackup1.emsphone.com/buildtmp/Pike7.3-20020924-135500/bin/test_pike.pike",0,0}))
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2002-09-24 13:20: Subject: catch { catch { break foo; }; };
Ok, fixed the ones I found.
/ Henrik Grubbström (Lysator)
Jo, jag lade märke till det... Fixat.
/ Henrik Grubbström (Lysator)
Previous text:
2002-09-24 17:15: Subject: catch { catch { break foo; }; };
I think you made some mistake though:
testsuite:2:parse error, unexpected `';'', expecting `')'' testsuite:2:Missing ')'.
/usr/var/tmp/xenofarm/pike/netbackup1.emsphone.com/buildtmp/Pike7.3-20020924-135500/src/testsuite.in:8816: Test 9958 (shift 2) (CRNL) failed. 0: mixed a() { return 20; } 1: mixed b() { return catch(int q=1; throw(a())); } 2:
Error: Compilation failed. test-install/pike/7.3.56/lib/master.pike:254: master()->compile_string("mixed a() { return 20; }\r\nmixed b() { return catch(int q=1; throw(a())); }\r\nint __cpp_line=__LINE__; int __rtl_line=[int]backtrace()[-1][1];\r\n\r\nint \200001=0;\r\n","testsuite",0) /usr/var/tmp/xenofarm/pike/netbackup1.emsphone.com/buildtmp/Pike7.3-20020924-135500/bin/test_pike.pike:664: main(3,({"/usr/var/tmp/xenofarm/pike/netbackup1.emsphone.com/buildtmp/Pike7.3-20020924-135500/bin/test_pike.pike",0,0}))
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
pike-devel@lists.lysator.liu.se