Index

Show enters and exits. Hide enters and exits.

00:00:29headiusoh, I see
00:00:40headiusthe static inspection sees gsub and just marks a "needs heap scope" bit
00:00:43headiusthat's all
00:00:58evanand gsub sets it in the current scope
00:01:01headiusyes
00:01:04evank
00:01:08headiushow do you do backref?
00:01:21evanusing VariableScope.of_sender
00:01:29evanto get the callers VS
00:01:30evanthen setting it
00:01:32headiusok, same basic thing
00:01:36evanas an ivar
00:01:46headiusbut I can eliminate the scopes, not sure if that's an option for you
00:01:55evani think i'm going to generalize it into VS.set_backref
00:02:02evanso it can touch unmanaged memory
00:02:10evanVS.of_sender has to hoist the VS into managed memory
00:02:21evanwhich means the JIT can't assume as much
00:02:36headiusyes
00:02:41headiusit is teh suck
00:02:52evanwell, CallFrame/scope elimination is what I did yesterday
00:03:03headiushelping much?
00:03:08evani got enough code exposed to LLVM that it can eliminate them entirely for leaf methods
00:03:16evanhttp://gist.github.com/123098
00:03:17evanthats for
00:03:20evandef foo; 1; end
00:03:36headiusthat doesn't mean a whole lot to me
00:03:41evanthe machine code at the bottom is what you wan to look at
00:04:00evanthere is no ruby call frame info, it's all been eliminated
00:04:04evanit's just the argument check
00:04:13evanand then returning 0x3 (which is a tagged 1)
00:04:14headiusah
00:04:23headiusI assume this only works for really trivial things
00:04:27evanleaves
00:04:31evanie, no calls in the method
00:04:38headiusleaves can produces exceptions though
00:04:47headius@@foo access that doesn't exist
00:04:47evanlike... ?
00:04:52headiusfor example
00:04:54evanthats not a leaf
00:04:55evanfor me
00:04:59evansince we raise that to a method call
00:05:01headiuswhat's a leaf then?
00:05:14evanliterals, self, ivars
00:05:21headiusahh
00:05:24evannot constants because of const_missing
00:05:29headiusI should do that too
00:05:34evanit's a small step
00:05:40evanbut it's moving us in the right direction
00:05:53headiusI've been reticent to add more one-off optz since we're hopefully moving to a new compiler chain over the summer
00:06:14headiusbut yeah, that would make those methods essentially the same bytecode for us too
00:06:17headiuser
00:06:18headiussame asm
00:06:21headiusso that's good
00:06:25ddubwhy cannot you inline known constants?
00:07:04evanddub: thats true, i suppose i could have the interpreter keep some data on constant access
00:07:21evanto know it won't hit const_missing
00:07:47evanstill have to look it up again
00:07:53evanbecause of the crazy constant repointing logic
00:08:05headiusyes, can't inline without a guard anyway
00:08:16evanactually, since thats true, you stil might call const_missing
00:08:21evanbecause someone could do remove_const
00:08:31headiusyep
00:08:33ddubremove_const? oh come on...
00:08:39headiusno way to eliminate guard for const lookup
00:08:43evanddub: i know, silly.
00:08:48ddub:)
00:09:17headiusevan: ivar access when not set is supposed to produce a warning
00:09:25headiusonly hole I can think of in that set of leaf states
00:09:41evanyeah, meh on that warning.
00:09:49evanwe've never generated it.
00:09:49headiusFORK
00:09:55evanmore like a SPORK
00:10:02evanbecause i'm gently cradling it
00:10:02headiusgood call
00:10:06evanbut still have the ability to stab
00:10:09ddubKNORK
00:10:21headiusI look forward to the day we decide to be less slavishly compatible
00:10:43ddub"now that we implemented everything, we are going to start removing the stupid bits"
00:10:49ddub"like modifiable constants"
00:10:50evanwe've got round and around on whether warnings are part of the impl
00:10:57evani don't even recall where we start now.
00:11:09evans/start/stand/
00:11:18brixenthey don't change the computation so they are immaterial
00:11:27evank
00:13:09headiusI disagree, but I've learned not to try to convince you
00:13:47evanwe've had this discussion every year for the past, mmm, this would make it 3 years
00:13:53brixena very painful and long learning process headius
00:14:38brixenof course, I'm willing to consider cases in which they do change the computation
00:14:45brixenperhaps an app using expect
00:15:15evanman, shark really does not like profiling an app with JITd code
00:15:18evangeez.
00:15:36brixenit's probably totally confused
00:15:42brixenwho is executing this code!
00:16:00evanit's like "UMM why does eip point to some random heap memory...."
00:16:23evan"Hey! Who put this here?!"
00:16:44ddubhmm
00:16:58ddubcan you make remove_const just change the constant to undef ? :)
00:17:10evanheh
00:17:16evanundefined behavior alert!
00:17:21evanwe'll output that warning
00:17:54ddubhow about 'warning: if you are using remove_const you might want to consider a different career path'
00:17:55evan"Undefined Behavior Detected. Activating Tachyon Reflector."
00:18:13ddub'warning: PI is exactly 4'
00:18:19evanhah
00:31:40evandude, seriously
00:31:46evanshark has been trying for 30 minutes now.
00:31:53evananalyzing
00:35:01headiusevan: how's that leaf optz helping perf? tested at all?
00:35:10headiusI might just toss it in
00:35:45evanme
00:35:46evanmeh.
00:35:53evannot a lot of methods that just return a number
00:35:57evanwho would have thought, i know.
00:36:01evan</sarcasm>
00:37:45headiusyeah
00:37:49headiusI think that's why I never bothered
00:38:06headiusit's pretty rare to have a method that just returns self or a literal or an ivar lookup
01:33:29evanwow.
01:33:37evanso Array#at in ruby, with the JIT
01:33:46evanis a shade faster than the primitive
01:33:53ezmobnice
01:34:05evanit's so small that it's probably stats noise
01:34:40evanit's still 2x faster than MRI
01:34:45evanin all cases :D
01:34:48ezmob;)
01:34:56ezmobhow hooked up is the jit now?
01:35:03ezmobjusy jitting simple stuff like array.at?
01:35:05ezmobor more?
01:35:38evanthe specs run with the JIT on
01:35:44evanso it's running a lot.
01:36:52ezmobsweet
01:38:03brixenevan: yeah, I think we can start experimenting with removing the perf primitives and writing more in Ruby
01:38:12evanyep
01:38:13brixenwhich will be... awesome blossoms
01:38:16evanthats what i'm doing
01:38:19brixensweet!
01:38:40evanturns out even an interpretered Array#at is pretty fine
01:39:21brixennice
01:40:58evanhttp://gist.github.com/123361
01:41:10brixenevan: some current jit results on the hash classes from this morning
01:41:10brixenhttp://spreadsheets.google.com/ccc?key=rdiNYWh0xTGShVHikWVmnUA
01:41:15brixensee the JIT tab
01:41:18evanprimitive, interp, jit, mri / 3, mri
01:42:53evanbrixen: who's jenxen?
01:43:16headiusevan: got leaf optz in
01:43:19brixenevan: jenny
01:43:44evanah ok.
01:43:51headiusI remember the other reason I don't like adding these
01:43:54brixenevan: I was using her as a guinea pig to test sharing :)
01:43:55headiusthey only help benchmarks :D
01:43:59evanah ah
01:44:01headiusso I lose some benchmarks
01:44:15evanheadius: are you just detecting the AST form?
01:44:21headiusyes
01:44:23evanor did the JVM do the work
01:44:27evanah, see thats where we're different
01:44:29headiuswell, JVM does a bunch more work
01:44:30evani didn't DO anything
01:44:35evanLLVM did all that
01:44:49brixenevan: the interesting column are in purple, they basically compare how much faster the jit made 2 different hash impls
01:45:06headiusevan: sure, that's not easily visible to jvm atm
01:45:19headiussome of our optz we have to do above the level of bytecode for now
01:45:45headiusit's not a big deal
01:45:53evanyeah
01:46:02evani didn't do that because i wanted super fast leaf methods
01:46:04evanthough thats nice
01:46:15evanI did it to figure out how to give LLVM the proper visibility
01:46:21headiussure
01:47:56headiusthe lack of visibility for hotspot is largely why --fast exists
01:48:04headiusand why we're doing a better compiler this summer
01:49:12headiusdon't get me wrong...I envy you LLVM :)
01:49:22headiusI wish we had the same, but writing our own will be fun too
01:49:27evanyeah
01:49:38evanhaving alloca operations has been key
01:49:44headiusright
01:49:53evanis the JVM doing escape analysis?
01:49:55headiusjava 6 update 14 has escape analysis which will help some of this
01:49:59headiusbing
01:50:02headiusyes
01:50:11headiusbut of course we defeat some of that with current prealloc optz
01:50:33headiusprealloc makes them nearly as cheap as alloca'ed frames, but it interferes with eliminating access at all
01:51:19evanyeah
01:51:21headiusactually, it's probably cheaper than alloca'ed frames since there's no alloc at all
01:51:30headiusbut it's kinda gross
01:51:30evanthe thing about alloca is giving the compiler full visibility and control over the data structure
01:51:35evanso it can fully reason about it
01:51:36headiusright
01:51:47evanand make wide assumptions
01:51:49headiusthe equivalent for us would be to add arguments to the call path
01:51:59headiusbut propagating that is unpleasant
01:52:29headiusmay be easier with invokedynamic
01:53:33evanyou mean passing everything as arguments
01:53:47evanso you force them to be in the jvm call frame
01:54:06headiusright
01:54:14headiusin which case it just eliminates them if they're not used
01:55:01evangotcha
01:55:05headiusI think we can get almost all of it via better compilation though
01:55:12headius--fast runs rails, for example
01:55:15evanone thing i was doing at the same time was cleaning up the CallFrame
01:55:23evanto exclude things that were available as arguments
01:55:33evanie, i was doing a bunch of data movement for no reason
01:55:37headiusyeah
01:55:53headiusI saw a couple of those commits
01:56:37evandoing that helped too
01:56:48evanbecause LLVM's value numbering figures stuff out
01:56:50evanso things
01:56:51evanlike
01:56:56evandef foo(a); a; end
01:56:58evanwhich is stupid
01:57:22evanbut you can see how LLVM reduces that to doing a memory access to get a as an argument
01:57:25evanand returning it
02:00:08headiussure
02:00:13evanARG
02:00:20evanfucking A people.
02:00:29evansomeone put another copy of Array#at in common
02:00:33evanok, forget everything I said.
02:00:35evanlets retest.
02:04:32evanok
02:04:36evanwell, it's not as good
02:04:43evanbut the results are more what I figured they'd be
02:05:17evanprimitive is about 4.5x faster than interpreted
02:05:26evanprimitive is 2x faster than JIT
02:05:28evanso thats good
02:05:37evanwithin striking distance
02:10:13evannice
02:10:19evanconditionalizing calling Type.coerce_to helped
02:19:06slavahi evan
02:19:21evanhey there
02:42:21rueOK, new rule
02:42:48rueWhen you glance at the mirror and for a couple microseconds wonder who that guy is, it is bedtime
02:44:13evanhaha
02:44:14evanso true
02:44:16evani've done that.
02:44:30evan"OMG guy looking in my house! On the... 3rd floor, ah shit it's me."
02:48:18mernencatching up with the discussion before
02:49:11mernenregarding constants, the value of a constant lookup can change even without undef/const_missing, because of the scoping rules
02:49:53mernenso yeah, I guess it's impossible to optimize them without guards (just reinforcing that conclusion)
02:50:30slavawhat if you handle constant changes with some kind of de-optimization technique instead of explicit checks?
02:51:18mernenI guess that's possible too
02:51:24rueQuite possibly better
02:51:37slavalike, if a constant is redefined, checkpoint all threads, update machine code references to the constant with the new value, and resume threads
02:51:38mernenan example of what I was talking about: http://gist.github.com/123362
02:51:47slavahow often do ruby programs change constants at runtime?
02:51:52slavais this just a development thing?
02:51:56slavaor do people have inner loops that do this? :)
02:53:03mernenthese are extreme cases, as far as I know
02:53:29slavadon't penalize the common case then
02:53:38mernennot common at all, though I have already seen people using remove_const in production code
02:54:42mernenafaik, both jruby and YARV cache const values, using a global constant change counter to check
02:55:03merneni.e., (un)defining any constant instantly invalidates all caches
02:55:42mernensince in the vast majority of cases constants never change after bootup, this is very effective
02:56:21slavaa global counter is still a conditional branch and extra memory load
02:56:28slavawould be neat if there was a way to avoid that
16:13:52jcoglanhey guys
16:15:02jcoglanquick compilation problem...
16:15:39jcoglantrying to build on Ubuntu, tail of my build output looks like this:
16:15:39jcoglanvm/builtin/system.cpp: In static member function ‘static rubinius::Object* rubinius::System::vm_jit_info(rubinius::VM*)’:
16:15:39jcoglanvm/builtin/system.cpp:316: error: incomplete type ‘rubinius::LLVMState’ used in nested name specifier
16:15:39jcoglanvm/builtin/system.cpp:319: error: invalid use of incomplete type ‘struct rubinius::LLVMState’
16:15:39jcoglanvm/shared_state.hpp:29: error: forward declaration of ‘struct rubinius::LLVMState’
16:15:41jcoglanvm/builtin/system.cpp:320: error: invalid use of incomplete type ‘struct rubinius::LLVMState’
16:15:43jcoglanvm/shared_state.hpp:29: error: forward declaration of ‘struct rubinius::LLVMState’
16:15:45jcoglanvm/builtin/system.cpp:321: error: invalid use of incomplete type ‘struct rubinius::LLVMState’
16:15:47jcoglanvm/shared_state.hpp:29: error: forward declaration of ‘struct rubinius::LLVMState’
16:15:49jcoglanrake aborted!
16:15:51jcoglanCommand failed with status (1): [gcc -Ivm/external_libs/libtommath -Ivm/ext...]
16:22:27gnufiedjcoglan, i am getting the same error. I thought some forward declaration was missing.
16:30:41jcoglangnufied -- okay, I guess HEAD is broken. will try some older commits
16:51:22ddubhave you ever tried searching for yourself on wikipedia? http://en.wikipedia.org/wiki/David_Waite
16:53:06brixenddub: funny, you look much younger in person :)
17:04:13rueProbably missing a conditional define
17:05:20gnufiedrue, for fixing that compile error?
17:15:10lypanovwibbles
17:15:30brixenhey lypanov
17:15:35lypanovcan't decide if he should hack on rubinius or jruby next week
17:15:52brixenum, that shouldn't be too hard to decide
17:15:59brixenrbx is soo much more fun :)
17:15:59lypanovwhats speed like in rubinius vs mri now?
17:16:09brixendepends what you are doing
17:16:21lypanovmicrobenchmarks :P
17:16:23brixenthe specs run in 3-6x mri
17:16:30brixenahh microbenchmarks
17:16:35brixenyou're in luck :)
17:16:40brixenwe should be much faster
17:17:11lypanovlol
17:17:12lypanovw00t
17:17:26lypanovwhats a good microbenchmark for me to hack on?
17:17:53lypanovi'd like to work on improving performance of array iterators
17:18:00brixenhm, you could compare calling a method in ruby to calling a method in C
17:18:12brixensee if there is any room to lean up the call path further
17:18:24lypanovlots :P
17:18:40brixenwe there ya go :)
17:18:46brixens/we/well/
17:39:25boyscoutConditionalize use of LLVMState. - cb98565 - Brian Ford
17:39:31brixengnufied: that should fix your build
17:40:07brixenat this point, we should probably just make LLVM a dep
17:40:22brixenit's not like we're going to remove the jit :)
17:48:36lypanovdgtized: around?
17:52:27dgtizedlypanov: yup
17:53:06lypanovdgtized: i seem to recall you had interest in some more advanced optimisations and wondered if you had made much progress / brainstormed on it / had interest in talking about it?
17:54:10dgtizedwell it depends on where they go -- evan recently added some block inlining type code that really improves performance on things like Array#each
17:54:11brixenlypanov: implement equality saturation :)
17:54:32lypanovequality saturation?
17:54:57lypanovdgtized: ah! very nice. generic or specific to a few types? how does it work? can you remember commit num?
17:55:03lypanovgreps through log
17:55:46dgtizedlypanov: it's somewhere in the LLVM JIT code, which unfortunately I haven't had a chance to learn
17:56:46dgtizedit gives us a 4x speedup over MRI for Array#each however
17:56:54brixenboggles that lypanov has not heard of eqsat
17:56:56brixenlypanov: http://www.cse.ucsd.edu/~rtate/publications/eqsat/
17:57:33evanmorning
17:57:34brixenlypanov: if you could add that to LLVM, kthxbye
17:57:40brixenmorning
17:59:50ddubmorning
18:11:44lypanovbrixen: um
18:12:01lypanovbrixen: love the domain/lang specific opts side of this
18:12:12evandgtized: it's not a 4x speed up OVER MRI
18:12:22evandgtized: it's a 4x speed up over previous rubinius code
18:12:33lypanovwhich is nx time faster already?
18:12:43evanno
18:12:48evanfor Array#each, we were slower
18:12:57evanwe're now about 50% faster
18:13:06lypanovvery nice
18:13:08lypanovwhat cases?
18:13:15evanjust Array#each
18:13:16evan!
18:13:18evan:)
18:13:20lypanovgeneric or microbenchmark?
18:13:26evanmicro
18:13:38evanbut the opt is generic
18:13:39lypanovcan you remember the spec in question?
18:13:54lypanovi suppose i need to get the dang thing compiling first
18:13:58evanthe benchmark I tested with is benchmark/rubinius/bm_array_each.rb
18:14:00lypanovcleans and retries a debug build
18:14:05evanwhich is silly
18:14:14evanbut exercises the hell out of Array#each
18:14:32evanthe opt was to give the JIT knowledge about Tuple#at
18:14:52evanso it could see Tuple#at was being used, and emit a type guard and then assembly thats the equiv of Tuple#at directly
18:15:04lypanovhow did you do jitted profiling?
18:15:17brixenlypanov: yes, the domain axioms are the delicious part of eqsat
18:15:19evanhow do ya mean?
18:15:41brixenlypanov: and the boolean sat solvers have gotten really fast and sophisticated in the last few years
18:16:18lypanovevan: i mean. is there an interp/compiler level profiler that gives info on what generated the code that was slow
18:16:32lypanovor do you only have user level profiling, as in, profiling of what is slow in apps?
18:16:40lypanovwonders if that makes sense
18:16:51lypanovrubydium does two styles, one in which it gives the call stack for the program
18:17:05lypanovanother in which in uses the call stack for the compiler for any given line of generated asm
18:17:13evanlypanov: we've got a profiler builtin that we use
18:17:21lypanovmakes it easy to find out what is generating shit code
18:17:24evanthats at the VM level
18:17:53lypanovvery cool
18:18:06evaninteresting, so you were profiling the generated code using what?
18:18:32lypanova hash storing counters
18:18:43lypanovthe hash key was the call stack for the generated instruction
18:18:50lypanovinced whenever that intruction was executed
18:19:08evaneach x86 instruction did this?!
18:19:24lypanovaye. mega slow mode hehe
18:19:47evanWOW.
18:19:51evanwhat info did that give you?
18:20:07lypanovcall stacks for the heavy parts of things
18:20:15lypanoveg, stack push/pop. register lookup. etc
18:20:32lypanovs/register/variable/
18:20:33evancall stacks being... a stack trace?
18:20:57lypanovaye. sorry
18:21:36evaninteresting.
18:21:52lypanovi did some neat things with the resulting stacks by changing the filter used on the "stack" generator
18:22:02lypanovto get me method level profile hashes easily
18:22:43evanstrange
18:22:53evanmy brain still doesn't get what data that shows ya...
18:23:11lypanovas in, instead of caller i'd use caller[-3..-1] etc
18:23:40dgtizedevan: Array#each on MRI on my machine is 4.06 user time versus 0.944 user time on rubinius + jit, and 1.66 or so on rubinius without jit
18:23:41lypanovand that would give me the high level overview of which methods in the vm where using most of the actual execution time
18:23:55evandgtized: wow!
18:23:58evandgtized: nevermind then!
18:24:00evanyay!
18:24:01lypanovevan: it basically will tell you which instrinsics are being called most and why i guess
18:24:10evanthats the best nevermind ever!
18:24:24lypanov++
18:24:30evanlypanov: ah, i think I see.
18:24:45evanyou were compiling everything yes?
18:24:53lypanovevan: keep in mind that i brainstormed rubydium way more than i actually hacked on it
18:25:00evanheheh
18:25:03lypanovso out of every 1000 lines of crap
18:25:04dgtizedand if you take into account real time, then MRI drops to like 5.5 seconds
18:25:07lypanovi had a neat idea
18:25:19lypanovum
18:25:30lypanovyou could call it compiling yeah.. no. you really couldn't actually
18:25:39evanhah
18:25:46lypanovsome day i should clean up the code so people actually understand it
18:25:54evanit was sort of trace based complication, yes?
18:26:00lypanovlol
18:26:05lypanovyes. trace based complication
18:26:17rueOh, I meant to mention yesterday before I saw the stranger in the bathroom: we could use some slightly longer (but versatile) benchmarks
18:26:24dbussinkdgtized: how are you running the bench? because for me ruby is faster than rbx without jit
18:26:28rueAlso, morning
18:26:31evanrue: agreed
18:26:35evanrue: morning stranger!
18:26:56rueEven the full spec run does not seem to be able to fully shrug off the JIT cost
18:27:04evanyeah
18:27:14evanpart of that is because almost all of the specs is blocks
18:27:16dgtizeddbussink: ruby benchmark/rubinius/bm_array_each.rb ?
18:27:19evanand the JIT is ignoring blocks still
18:27:26rueYep
18:27:32lypanovwhat are you jitting now?
18:27:35dbussinkdgtized: yeah, doing that here too
18:27:38rueOh, yes, the Prawn tests...lessee now
18:27:40lypanovuser code or lib code or both?
18:27:43evanbut still, you'd hope that it would make the kernel methods fast
18:27:50evanlypanov: whatever code is in the system
18:28:01dgtizeddbussink: it's technically 1.8.7 I'm running I guess, so maybe they had a regression?
18:28:13evanlypanov: methods only atm, but it doesn't care where they come from
18:28:14lypanovcan't you dump/load that at startup/shutdown?
18:28:30dbussinkdgtized: me too, i can test with 1.8.6 too
18:28:34lypanovas in, cache the generated functions on disk
18:28:49lypanovdid that with rubydium to great effect
18:30:18lypanovwas going to use ast-md5's but never got around to it
18:30:39dbussinkdgtized: these are my numbers: http://gist.github.com/123726
18:30:50evanlypanov: i could
18:31:07evanlypanov: atm, the assembly contains some stuff specific to the current process
18:31:12evanso i'd have to weed that out.
18:32:34evanlike using raw Symbols as arguments
18:32:49dbussinkevan: do those numbers sound reasonable?
18:32:51dgtizeddbussink: that's really strange: http://gist.github.com/123730
18:33:09evandbussink: run them again
18:33:13evanwith TOTAL=5000
18:33:26evanyour numbers are too small to be trusted
18:33:27lypanovis there a way to make rake just do :debug by default so i don't forget?
18:33:34evanlypanov: nope
18:33:44evanwhy are you doing a debug build?
18:33:52lypanovcus it won't compile without it
18:34:01brixenlypanov: use gcc 4.0.1
18:34:16lypanovi don't think i can. but i'll give it a try
18:34:21brixenlypanov: are you on os x?
18:34:28lypanovsorta :D
18:34:32lypanovbetter not to ask
18:34:38lypanovi'm on gentoo/osx
18:34:40brixenoh, you did that gentoo thing didn't ya
18:34:43brixenyeah
18:34:46brixenhow's that working?
18:34:51brixenlooks crazy
18:35:03lypanovzero issues since install
18:35:04dbussinkevan: it really doesn't make a big difference actually
18:35:07lypanovand finally no need to sudo *ever*
18:35:11dbussinkevan: numbers are in the same ballbark
18:35:13lypanovi frikking hate sudo'ing
18:35:17brixenlypanov: swee
18:35:20brixener sweet
18:35:28evandbussink: repaste them.
18:35:32brixenlypanov: you could also try 4.2.3 if it's available
18:35:45dgtizeddbussink: ok, but we are definitely seeing completely different numbers -- x86 or x86_64?
18:35:46dbussinkevan: updated the gist
18:35:49lypanovwhy would i not want debug build btw?
18:35:56lypanovi want to hack on rubinius not use it :)
18:36:13evandbussink: ok, thats the numbers I get too
18:36:18dbussinkdgtized: os x 10.5
18:36:19lypanovdebug is heavy debug? useless for benches?
18:36:22evannot sure why dgtized is seeing so awesome numbers
18:36:34evanlypanov: yes
18:36:37evanuseless for benches
18:36:38dbussinkdgtized: maybe a build with pthreads enabled on linux or something like that?
18:36:42lypanovteh lameness
18:36:43brixenlypanov: 4.3.[23] rather
18:36:52lypanovwhat d'all use when develling?
18:36:59lypanovinserts a y randomly
18:37:02evanlypanov: export CC=gcc-4.0
18:37:04evanlypanov: then compile.
18:37:17lypanovoh but thats just far far too easy
18:37:24evansorry
18:37:27lypanov:D
18:37:28evani'll make shit more complicated next time.
18:38:46lypanovah neat
18:38:54lypanovgentoo apparently has a funky gcc-config thingy
18:39:04evanthey all do
18:39:05evan:D
18:39:14evanoh wait
18:39:17evanOS X doesn't
18:39:19evani guess just linux
18:39:32lypanovosx has gcc_select though or whatever its called
18:40:13evanyeah, anyway.
18:40:26lypanovto reask. is there any reason i should ever need :debug?
18:40:45evanto debug the VM
18:40:51evanthats what I use it for
18:41:06lypanovk. then i'll probably need it quite a bit as i'm hoping to badly fuck up the vm soon
18:41:07brixenlypanov: it compiles without opts so you can actually follow the code in gdb
18:41:24lypanovah, i'm more of a printf sorta guy
18:41:32brixennooo :P
18:41:43lypanovis like totally old school and stuff
18:41:51brixengangsta
18:42:42evanso, i'm working on making
18:42:50evanType.coerce_to idx, Fixnum, :to_int
18:42:51evanfaster
18:42:58evanusing an AST transform in the compiler
18:43:09lypanovdo you have cute backtraces that traces through the generated x86 up through the vm btw?
18:43:12brixenlypanov: http://tinyurl.com/art-of-debugging learn it, live it, love it
18:43:23evanlypanov: sorta
18:43:29lypanovi love ddd. don't get me wrong
18:43:31lypanovjust hate gdb
18:43:36lypanovthink its useless frankly
18:43:54lypanovdata debugging is far more useful than flow debugging
18:44:05lypanovlack of go-back-in-time power is a killer for debugging
18:44:11evanyeah
18:44:12evanagreed.
18:44:18evanhave you seen the reversible debuggers?
18:44:19lypanovjava is far better than this c shit anyway
18:44:29evanthere is some crazy patch to gdb
18:44:32evanthat lets you go back in time.
18:44:36evanno really
18:44:45lypanovread about it. pretty neat tech
18:45:10dgtizedevan: is this Type.coerce_to going to optimize for more then Fixnum?
18:45:12evanhttp://undo-software.com/undodb_man.html
18:45:15evanfor those curious
18:45:21evandgtized: we could make it do that
18:45:32evanjust Fixnum at first
18:45:35lypanovsome day you'll get to the stage when you don't have any c based stacktraces. then i'll be all happy
18:46:41dgtizedI'm going to guess that Float, Symbol, and String Type.coercion optimizations would also be useful -- but that's purely unsubstantiated
18:46:46lypanovas in, turtles all the way down. 99% of the vm will be in ruby anyway and llvm will dynamically deoptimize on debugger attach
18:47:24evanlypanov: sounds great!
18:48:40lypanovwonders if evan has more detail on the q he posted in #jruby than most of the channel probably will
18:48:58evanhehe
18:49:08evani've talked with headius about them
18:49:15evani think he's still poking at it
18:49:19evannot sure about performance
18:49:26lypanovme too in detail a while back. just wondering if anything had happened since
18:49:32lypanovits not really about perf that i'm worrying
18:49:39lypanovno benches will show the improvement for the moment
18:49:46lypanovi worry more about theoritical perf improvement
18:50:25lypanovthe java7 dyn invoke stuff is much like brixens equality saturation approach
18:50:32lypanovmost likely it will bring amazing things
18:50:39lypanovbut fuck, the engineers themselves have *no* idea why
18:51:15evanhehe
18:51:28evanthe MethodHandle thing is cool
18:51:35evani was thinking we could pretty easily add it to Rubinius
18:51:40evanbut have to figure out how we'd use it first
18:51:59lypanovi stalled on rubydium because i started asking myself one big question:
18:52:13lypanovhow could i add this opt, but in user level ruby code?
18:52:25lypanovnever found the answer :D
18:53:13evanheh
18:54:53lypanovhas anyone ever looked into which parts of rubinius perf might effect merb perf?
18:57:02evana little, not too much yet
19:02:14evanso
19:02:18evani was think
19:02:23evanmaybe we should add another visibility
19:02:33evancall it system or something
19:03:02evanthose methods wouldn't be reported by #methods, #instance_methods, etc
19:03:13evanso dynamic code that tries to remove methods wouldn't see them
19:04:35brixenhm, I like
19:04:48brixenhow would you determine it though?
19:04:50evanwe can then use them to build stuff
19:04:57evandetermine which?
19:05:00brixensay, in the case we use Rubinius.privately for now?
19:05:09brixenor you only mean for remove_method?
19:05:13brixenundef
19:05:52brixenlike, would it have normal call semantics?
19:05:59evanyeah
19:06:07evanthey'd be callable like normal methods
19:06:08brixenwhen you say visibility, I think public vs private when calling
19:06:12brixenok
19:06:13evanjust excluded from lists
19:06:22brixenhm
19:06:26brixenso no reflection
19:06:28brixen?
19:06:30evanwell, i was thinking visibility, but it's more like tagging
19:06:37evanno, reflecting is fine
19:06:50evanmaybe ala macruby, there is another argument to #methods
19:06:55evanthat indicates if you want to see system methods
19:06:59brixenyeah
19:07:01evanor we add #system_methods
19:07:11evanrather than it being a visibility in the method_table
19:07:18evanit could be a tag on the CompiledMethod itself
19:07:23dgtizedwhich methods are in that category?
19:07:26evandef blah
19:07:27evan 1
19:07:29evanend.system!
19:07:53evandgtized: well, i'm working on adding Object#__fixnum__
19:08:03evanthat returns true if the objcet is a Fixnum
19:08:06evansomething like that
19:09:11brixenwell, then the only thing it gives is protection from being undef'd?
19:09:28evana couple things
19:09:43evanif it doesn't show up in #methods, then people won't automatically undef it, using builder style code
19:09:48evanor blankslate
19:09:57brixenok
19:10:04evanplus, yes, undef could raise an exception if you try to undef one
19:10:32brixenI'd prefer system_method :foo rather than end.system!
19:10:39evansure
19:11:22brixenso, these are tagged :system_method or whatever but are essentially public?
19:11:29brixenfor visibility?
19:11:42evanhm. seems like it, yes.
19:12:02evanor they could be private and accessing using a special synta
19:12:04evanx
19:12:08evanperhaps something like
19:12:15evanSystem.__fixnum__ obj
19:12:32evanthe compiler would flip that to call __fixnum__ as a private method on obj
19:13:51brixenhrm, I'm not a big fan of that syntax
19:13:54evanok
19:13:57brixenif it's used in a lot of places
19:14:10brixennot sure it adds much over just being a public method
19:14:20evansure
19:14:31brixenif redefines/undef's won't work, might as well be public
19:14:39evanso would we not allow system methods to be masked?
19:14:53brixenlike redefined?
19:15:02evanclass A < Object; def __fixnum__; true; end; end
19:15:20brixenmaybe only in kernel mode, to allow for bootstrapping
19:15:23brixenbut not in user code
19:15:24evanshould that raise an error
19:15:35evanit's not a redefine
19:15:46evanbut rather a subclass mask
19:15:49brixenright
19:16:03brixenhrm
19:16:11evani'm thinking about these a bit in the context of the JIT
19:16:27evanprimarily, the ability to have the JIT know about some system methods
19:16:36evanand emit custom code for them without guards
19:16:41brixenyeah
19:16:51evanbecause it can reason that __fixnum__ IS always what it thinks it is.
19:17:19brixeni guess we could start with them being open and if you (the user) breaks it, we could disallow that
19:17:33brixenif they are not normally visible...
19:17:43brixenI guess you'd still need to prevent accidental conflicts
19:17:52evanwell
19:17:57evanif the JIT speculates
19:18:04evanthen their overriden version may never be called.
19:18:14evanoh oh
19:18:16evanactually
19:18:17evannm.
19:18:23evanwe can let them override them.
19:18:38evanjust realized that the JIT can just look at the SendSite cache to know which version was used
19:19:01evani guess, for that matter, we could all them to undef and such if they really want
19:20:41brixenmakes sense
19:25:18evanhm, this Type.coerce_to rewrite is just making shit slower...
19:25:19evan:/
19:27:38evanuumm
19:27:41evanwtf did I do...
19:27:55rueUnfucking argument processing in core from MRI conventions (all 8 of them) would probably be a much higher yield
19:28:15evaneh?
19:28:21evanwhich argument processing do ya mean?
19:29:01rueThe reason Type.coerce_to exists to begin with
19:29:37evanhm, so what do we use instead?
19:30:26rueWell, we cannot really break compatibility there, I think
19:30:32ddubcould you just make certain operations really inefficient?
19:30:58ddublike say, remove_const could result in all cached code being flushed (in the absense of a way of telling which particular methods are using said constant)
19:31:04evanrue: i'm not sure what ya mean by unfucking argument processing
19:31:34evantherealadam: WELCOME TO THE THUNDERDOME
19:31:52ddubis there a fakeadam?
19:32:36rueSeveral
19:32:57rueevan: coerce_to does 2 kind_ofs and one send
19:33:11lypanovddub: i agree with penalizing the stupid fucks that play with this sort of code
19:33:17rueAlso, wtf #coerce_to_comparison evil
19:33:32evandid someone write that?
19:33:51ddub#coerce_to_evil
19:33:55evansweet zeus
19:33:56evanwtf.
19:34:15rueThat is not my favourite kind of core code :P
19:34:19evanrue: it's unused
19:34:22evanlets nuke it.
19:34:34evanbefore someone noticies
19:35:10lypanovk. gotta run
19:35:11rueddub: Yes, I think it is OK to optimise for the common case (at the very least initially, with potential updates at $5 apiece)
19:35:24evanmarcandre added it
19:35:43ruemarcandre: Bad!
19:35:52evanit's pretty dumb.
19:35:57rueNo cookie
19:36:14marcandreWhat have I done exactly?
19:36:24evanmarcandre: Type.coerce_to_comparison
19:36:27evanwhats the point of it
19:36:33rueevan: So, a sane implementation could just directly do the #to_whatever call instead of bothering with TWO #kind_of?s
19:36:57marcandreIsn't it to map -5 to -1, for example?
19:37:08evanyou tell me
19:37:08marcandreneeds a ram upgrade
19:37:09evanyou wrote it
19:37:58rueHrm
19:38:50rueThere is *significant* perf degradation when I load the Prawn tests multiple times...I wonder if it is hitting the caches really badly or something
19:39:10marcandreOk. So the idea is to raise an error if a comparison block/method returns nil.
19:39:28rueEssentially, 1x run is ~2m, 2x is ~5m, 3x is ~10m
19:39:45evanrue: werid.
19:40:02marcandreThe checking for <=> 0 was just to mimick MRI, but it's not really needed here, since the result is then compared with 0 again.
19:40:03ddubsounds like really you shouldn't be looking at prawn
19:40:23rueddub: ?
19:40:42rueHee, Brain Ford :)
19:40:45ddubsorry, a little bit of prawnographic humor
19:41:14rueOh, oh, I see...it is that thing with humans and their appendages..
19:41:15evanmarcandre: you mean for nil, yes?
19:42:08brixenrue: he could have just gone all the way with Brain Food :)
19:42:09marcandreI mean raising if nil, but the different returns with tests for > 0, <0 could go.
19:43:25evanmarcandre: hm, ok, i see...
19:43:49marcandreWhat exactly is the problem with it?
19:43:50evanit still seems weird.
19:44:19evanwhy is this not
19:44:23evanraise ....
19:44:26evanreturn cmp
19:44:57marcandreIt is now :-)
19:44:58boyscoutMore efficient coerce_to_comparison - ba27148 - Marc-Andre Lafortune
19:45:19evanmacournoyer: so you only use this in enumerable
19:45:26evanwhy not make it a private helper method
19:45:32evanit would be faster to call that way
19:47:29marcandreevan: I'd be surprised if other places in the code wouldn't need it. Let me check
19:47:46evanmarcandre: most things don't care about checking the result of <=>
19:47:51evanthey just compare and let it blow up
19:48:05evanthats faster too
19:48:17marcandrebtw, macournoyer is the famous Marc-André Cournoyer (also from Montreal). I'm Marc-André Lafortune
19:48:38evanyes, we know :D
19:48:45evanwe're happy to have to marc-andre's
19:48:49evantwo
19:48:55macournoyerya!
19:49:12marcandreevan: you don't get the right error, though... NoMethodError on nil vs "can't compare a & b"
19:49:15macournoyerand my parents thought they gave me a unique name...
19:49:25marcandreyeah, mine too ;-)
19:49:26evanmarcandre: so wrap that in a begin/rescue
19:49:48evanthats sort of like being named Evan
19:49:50evani don't run into too many
19:49:56evanall though there are a ton in the ruby community
19:50:04evanlike at least 5!
19:50:09macournoyeryes, a lot
19:51:40marcandreevan: begin/rescue is cute, but what if the block calls "nil > 0"? Then we're _supposed_ to raise a NoMethodError...
19:52:16evanstupid MRI
19:52:18evanGAH
19:52:20rueevan: ^^ The argument processing I was referring to :P
19:54:09rueActually, not using coerce_to would remove three, not two method calls
19:55:59evanie, just call the method
19:56:02evanto_i or whatever
19:56:18marcandreif you need it, what could be done is putting a "|| raise ..." after all comparisons
19:56:34evanFUCK no.
19:56:38marcandrelol
19:56:41evanthats disgusting.
19:56:56brixen|| die ... it's very perlish
19:57:16marcandreas for putting it private in Enumerable: it doesn't belong there!
19:57:50marcandremoreover, I just double checked that Array#sort doesn't raise the right error if arguments can't be compared...
19:58:32marcandreNow you can decide "fuck the specs, let the comparison fail on nil > 0", but to be 100% compliant, I think coerce_to_comparison is needed
19:59:07brixenoption 2: get MRI to be consistent about the errors
19:59:12brixenlong shot, I know, but...
19:59:43marcandreWhy do you guys think MRI is not consistent?
19:59:51evanor, rather that Type.coerce_to
19:59:51rueBecause it is not? :)
19:59:55evanwhy not go the smalltalk route
20:00:16evandevise a small number of methods make up the protocol
20:00:22marcandrerue: yeah, I realize that there are still many inconsistencies around :-)
20:00:27evanand distribute them around the hierarchy for desired effect
20:00:27marcandrebut in this case?
20:00:33evanin the case of Type.coerce for Fixnum
20:00:46evanclass Fixnum; def __to_fixnum__; self; end;
20:01:02evanclass Object; def __to_fixnum__; Type.coerce_to self, Fixnum, :to_int; end; end
20:01:09evanthen you call __to_fixnum__
20:01:22evanwhere you NEED a fixnum
20:01:44evanagain, this is a good usecase for system methods
20:01:48evan__to_fixnum__ being such.
20:01:55rueMeh, I would just let it fail :)
20:03:13brixenmarcandre: I'm talking about nil > 0 raising a NME
20:04:02marcandrebrixen: MRI doesn't raise a NME, rbx does
20:04:45brixenmarcandre: yes MRI does on nil > 0
20:04:53marcandreI mean things like the current Array#sort do.
20:05:20marcandreOh yes. You'd rather have a "can't compare nil with 0"?
20:06:04brixenmarcandre: there are just a lot of places coercion is handled in MRI and not always consistently
20:07:02marcandreBut in the case of methods needing to compare x and y, if x <=> y returns nil it's ok to raise an ArgumentError instead of a NME on nil, no?
20:08:52brixenthe fact that nil <=> 0 != 0 <=> nil is ugh
20:09:34marcandreoh. yes. I see.
20:11:15marcandreI didn't realize that. You're right
20:11:30marcandreIf nil <=> 0 returned nil, that would be much nicer I think.
20:12:19brixenmarcandre: you've looked through MRI source: rb_Integer, rb_to_int, rb_check_to_integer, rb_to_integer, rb_check_convert_type, rb_convert_type, convert_type, rb_f_integer ?
20:12:21marcandreAnd not having the coerce_to_comparison call would generate the right class of exception (albeit without the informative message)
20:12:51marcandreI try to avoid it ;-)
20:13:21brixenwell, it's very complex how all those are used throughout the code
20:13:33brixenthat's partly what I mean by consistency
20:13:47brixenMRI is so complex in this area, oddities are sure to surface
20:15:33brixenI think that <=> should either always return { nil, -1, 0, 1 } or have a NotComparableError exception and return { -1, 0, 1 }
20:15:59marcandreI'd vote for that too...
20:16:02brixenbut should never raise NME
20:16:21marcandreAs there been discussion on ruby-core about having an Object#<=> defined?
20:16:31brixennot sure
20:17:21rueEven converting a NoMethodError to TypeError would still save two method calls
20:18:27brixenright, ArgumentError masquerading as a TypeError is another inconsistency
20:18:41brixenit'd be nice to query rubyspec for these cases
20:19:50marcandreIf you don't mind the less informative error, instead of coerce_to_comparison(a, b, block.call(a,b)) < 0 we could use 0> block.call(a,b)
20:20:07marcandreThis would throw an ArgumentError if it returns nil.
20:20:54marcandreOnly the message would be less informative "comparison of Fixnum with nil failed" instead of "comparison of a.class with b.class failed"
20:22:30therealadamevan: ahoy (belated)
20:23:49evanavast
20:24:25brixenmarcandre: I wonder if it'd be too hard to get a rational protocol for all relational operators
20:24:56brixenmarcandre: based on a NotComparableError exception ond { true, false } or { -1, 0, 1 }
20:25:15brixento hard to convince MRI*
20:25:27marcandrebrixen: personally, I like the fact that <=> returns nil
20:25:47brixenwell, there's just no accounting for taste... :P
20:26:26marcandreBut it should be symetrical, at least. It would be easy to implement: use recursion guards and reverse the arguments. Return nil if recursion detected.
20:26:56marcandreThe thing is, you can't change the semantics of <=>.
20:27:22marcandreYou could define another operator, that would call <=> || raise NotComparableError
20:27:57marcandreBut unless it's something like __compare__ there would be too much change of a conflict.
20:30:15brixenmarcandre: I dunno, NilClass is not a Comparable, so 0 <=> nil => nil is just madness IMO
20:30:26brixenbut I need food... bbiab...
20:31:05marcandreBut nil == 0 # => false, nil != 0 # => true, exactly like a == b and a != b if a <=> b returns nil
20:33:02rueAaaaargh
20:33:13rueI think we should paste this conversation to ruby-core :/
20:34:48marcandreI'll be glad to post a feature request on redmine, especially if we can present it well
20:36:33brixenmunches pizza
20:37:37brixenmarcandre: it is true that #== and #!= are equality relations distinct from what I consider comparable (partial-ordering) relations like #<=> #< #> etc
20:38:17brixenmarcandre: but either all comparable relations should return nil for "not comparable" or they all should raise
20:38:41brixenthe inconsistency between 0 <=> nil and 0 < nil sucks
20:38:51marcandreHmmm. The thing is: if x and y are not comparable... then they are not equal, right?
20:39:01brixenno, not in my view
20:39:19brixenbecause equality can be based on identity or equal value
20:39:30marcandreSo if x <=> y returns nil (or raises a NotComparableError), I still would like x == y to return false
20:39:38brixenwhich has no connotation of comparable, in the sense of a partial order
20:40:16brixenyes, #== is in a distinct class of operators from #<=> IMO
20:41:46marcandreIn some ways, yes. But you're adding weight to the current position of MRI...
20:42:21brixenmm, no
20:42:40brixenin my scheme, 0 <=> nil and 0 < nil behave consistently
20:42:50brixen0 == nil => false
20:43:08brixenequality is something you can define between *any* a and b
20:43:19marcandreYou mean nil <=> 0, because 0 <=> nil is already nil
20:43:26brixeneither based on identity or equal value, with coercion semantics for value comparison
20:44:09brixenno, I mean http://gist.github.com/123802
20:45:10marcandreFunny, I don't see that as being inconsistent.
20:45:26marcandreThere are cases where two objects are different but no order exist between them.
20:46:13marcandreIn that case, it is informative to answer that they are different (i.e. <=> returns nil) but asking < can not return a meaningful value so it raises an error
20:46:29brixenhow is that consistent?
20:46:37brixenneither op can return an answer
20:46:57marcandrewell, nil means that they can't be compared, as per definition of <=>
20:47:16brixenand nil could mean they can't be compared according to #<
20:47:43marcandreYeah, except that you'd have to rewrite all the code!
20:48:01marcandreunless a < b ==> if a < b == false
20:49:23brixenyes, I think they should both raise, not return nil
20:50:00marcandreOk. But then you want everyone that ever defined a <=> method on their classes to rewrite it...
20:50:47boyscoutRemove cruft - 2ba827a - Evan Phoenix
20:50:47boyscoutSpeed up a basic form of Type.coerce_to - 52879f7 - Evan Phoenix
20:50:47brixenI suppose...
20:51:35marcandreI think a lofty goal would be to have Ruby be at least symetrical with respect to it's comparison operators.
20:52:02brixenwell, might as well add consistent to that lofty goal :)
20:52:19brixenit'll probably break some code no matter what you do
20:53:01marcandreWell, I think it would break code that would compare apples and oranges and rely on the error being throw to be of type NoMethodError...
20:53:16brixenmarcandre: exactly
20:53:20brixenhow crazy is that
20:53:47brixenwhat's NME got to do with comparability?
20:53:55marcandreIt would be crazy to do that, so I'd have no pity for those cases
20:54:28marcandreThe more I think about it, the more I believe there should be an <=> operator defined by default.
20:54:52marcandreI think another argument is that some methods of Enumerable rely on <=>, and that's the only operator they have to rely on.
20:55:26brixensounds like you see 3 classes of comparison: equality, comparability (#<=>), and relational (#<, etc)
20:55:32marcandreIt would make Enumerable even more pure than it is right now.
20:55:53marcandreI see the <=> as asking all the questions at the same time, for efficiency.
20:56:27brixenthen #<=> must behave like any other relation operator to pass my def of consistency
20:56:29marcandreI.e. "tell me if these guys are the same or different, and if different, can you order them"?
20:56:42brixenheh
20:56:44evanwho ever keeps writing "if("
20:56:45evanSTOP IT.
20:56:49evanin ruby
20:57:06brixenmarcandre: you're bact to 3 classes of op
20:57:09brixener back
20:58:11marcandreNot sure what you mean by classes, but I see two: one that requires an order (otherwise raises an ArgumentError) and one that doesn't.
20:59:03brixenmarcandre: well a <=> x => 0 ==> a == x
20:59:12brixenso <=> subsumes ==
20:59:24marcandrechecks the definition for subsumes
20:59:50brixenreturning -1 or 1 ==> a, b can be ordered
21:00:05marcandrecan be ordered and are different, yes
21:00:08brixenso the only other possibility is that a, b are not comparable at all
21:00:58brixenI'm having trouble seeing the value of <=> having a different result that < for the case where you cannot compare at all
21:01:02marcandreWell, they could be semi-ordered, so they are comparable in that they can sometimes be ordered but not always.
21:01:14brixenexample?
21:01:18marcandregraphs
21:01:54marcandreI can't draw here, but some graphs are subgraphs of others (<) but that's not always the case.
21:02:07marcandre*---* < *---*---*
21:02:26marcandre*---* < Triangle
21:02:36brixenhmm
21:02:36marcandreTriangle <=> Square # ==> nil
21:05:52brixensorry, back..
21:05:55marcandrehttp://en.wikipedia.org/wiki/Partially_ordered_set
21:06:17brixenyeah
21:06:42brixenso, a < b ==> a <=> b => a value
21:07:12brixenthere is no case in which a <=> b => nil that a < b is defined
21:07:16brixenand vice versa
21:07:26marcandreNo, indeed.
21:07:30brixenso, why have different results?
21:08:05marcandreWhen do you have different results?
21:08:26brixenwell, a < b raises and a <=> b => nil
21:08:44brixenessentiall, you want to say: if a <=> b then x else y end
21:08:54brixenI guess that's reason enough
21:09:22marcandreYeah. Basically I think it's quite useful to return nil in that case
21:09:46marcandre<=> doesn't _assume_ they are ordered, while < does.
21:10:14marcandreAnd the fact that < returns false, there's no way you'd want to return nil and false with a different meaning.
21:10:34brixenindeed
21:10:44marcandreBut really, I think the point is moot. Changing the semantics of <=> is next to impossible, I believe
21:11:14brixenok, I'll settle for symmetric
21:11:16brixen:)
21:11:19marcandreThe only hope for some symmetry and consistency is to have a <=> defined for all objects, in the same that == and != are defined
21:11:30boyscoutStyle cleanup - 37fe0d3 - Evan Phoenix
21:11:40brixenbut I still think raising if objects are not comparable is a valid solution
21:12:25brixenyeah, I agree, #<=> should be defined everywhere
21:13:59marcandreHow about this: I'll write something up to propose adding <=> everywhere, and if it passes, I'll let you write something to propose it raises an error ;-)
21:14:39brixennah, you've convinced me :)
21:15:06brixenit's actually very convenient to have a value that signifies undefined for computation
21:15:18brixenand one you can use as a boolean noless
21:16:43marcandreI've got to prepare for game night, but I'll write something up and email it later tonight or tomorrow, and I'll cc rue and evan so anyone can pitch in for suggestions
21:16:55brixensweet
22:12:58rueOh wtf. MTpro seems to allow <script /> in blog posts by default :/