<headius[m]>
we can talk about the original race but it should only happen now if there's truly two threads hitting a method that happens to JIT at that moment and has a //o
<headius[m]>
enebo: race!
lucasb has joined #jruby
sathomsen has joined #jruby
sathomsen has quit [Ping timeout: 258 seconds]
<enebo[m]>
nice!
<headius[m]>
enebo: the race this exposed is still there
<headius[m]>
because the IR stores its //o regexp in one place and the JIT stores its in another there's no way to guarantee it's the same one across a JIT boundary
<headius[m]>
link up there a ways shows that JIT does check if IR has already cached it but that's obviously not atomic
<headius[m]>
with according leak, softref, whatever hassles
<enebo[m]>
Can they collect
<headius[m]>
they cache it in the instruction most likely
throstur has joined #jruby
<headius[m]>
in the iseq
<enebo[m]>
yeah that would be a reasonable solution
<enebo[m]>
if that code goes away then //o can go away
<enebo[m]>
Otherwise they would need to pin it forever
<headius[m]>
the semantics are definitely to caches it at at the site
<enebo[m]>
we could store them in IRScope as regexp[] sort of thing but that is icky
<enebo[m]>
AOT could still work but we would need to persist that
<headius[m]>
ah yeah scope was the other option
<enebo[m]>
I mean icky in the sense that this problem does not feel like it is worth the effort of fixing
<headius[m]>
I think AOT wouldn't need anything special because presumably you would not be mixed mode then
<headius[m]>
the only race is when we have a transition
<enebo[m]>
well the index of ther array would be set up on load so it should just find it. With deopt we need to fall back to full interp so AOT should consider that
<enebo[m]>
OTOH long term AOT will not be the AOT of today either
<headius[m]>
I agree with you tbh but I have no idea how bad it could be if a //o produces two results
<enebo[m]>
My mind is fuzzy in how bad it can be? In my mind atm I just seem to think object identity comparison would say they are not the same regexp
<headius[m]>
btw JDK13 appears to add a dynamic CDS similar to J9 -Xshareclasses...it might be possible to start caching jit output in a CDS archive and have it already verified and ready to go at startup
<enebo[m]>
but the regions captured from two is already thread separate data
<headius[m]>
possible smaller memory/meatspace too
<enebo[m]>
nice
<headius[m]>
well it's not just object identity that's a problem
<headius[m]>
you'd potentially get two different regexp patterns
<enebo[m]>
oh at different times
<headius[m]>
e.g. /#{Time.now}/o
<enebo[m]>
ok got it. I knew there was more
<enebo[m]>
but fwiw if you are doing that in 50 threads you have no idea what is happening
<enebo[m]>
although you would clearly match on 2 different things
<headius[m]>
we do not guarantee the dynamic bits will run once
<headius[m]>
we won't guarantee that because it would require locking around evaluating them
<enebo[m]>
yeah we would need to add a lock and who knows how hairy that could get
<headius[m]>
so the minimal guarantee is that whatever's at a //o site will always be the same regexp pattern and object
<enebo[m]>
if recurses on itself!
<headius[m]>
in that case above it would be any one of random Time.now but always that one
<enebo[m]>
def foo; /#{foo}/o; end
<headius[m]>
hah
<headius[m]>
I considered locking and realized quickly that would never work
<enebo[m]>
yeah I get the problem but I just don't think people are doing at some particular time generation of the regexp contents
<headius[m]>
so it really just comes down to having one atomic memory location to store it at
<headius[m]>
no, probably not...that's my sense as well
<headius[m]>
BUT WHAT IF
<enebo[m]>
well even pointing out it is not atomically calling is a pretty big semantic difference
<headius[m]>
I still find it a really odd feature
<enebo[m]>
in fact probably more likely then the contents being different
<enebo[m]>
Still not important in real life most likely
<headius[m]>
like if you want it dynamic why isn't it always dynamic
<headius[m]>
and if you want it static why is it dynamic
<enebo[m]>
configuration single value setting
<enebo[m]>
stuff where it is actually static but not code static
<headius[m]>
well I guess that's the other thing
<headius[m]>
usually it's in a class body or something
<headius[m]>
in that case it's just FOO = Regexp.compile("#blah") really
<enebo[m]>
so the non-atomic expansion is actually a bigger problem in the sense of side-effects but I doubt it is really
<headius[m]>
do people do it in a method body?
<headius[m]>
if they do I hate you
<enebo[m]>
@@my_regexp ||= /gotohell/o
<enebo[m]>
I love the ambiguity of reading thatl ine
<enebo[m]>
Am I telling you off or making a joke about goto?
<headius[m]>
the biggest issue would certainly be side effects but I don't think even MRI guarantees that the dynamic bits won't run again
<enebo[m]>
you know what would improve that exclude...a wontfix issue which explains why we it is excluded
<headius[m]>
it's possible that MRI prevents or limits thread switching during the dynamic bits or it might just get lucky
<enebo[m]>
In fact it might be a good idea to add a tag incompatibility or something where people can figure out that it is a semantic difference for us
<headius[m]>
yeah good call...linking to this and to our wontfix
<enebo[m]>
we could probably generate a document from that
<headius[m]>
well excludes don't have tags but I can explain it there
<enebo[m]>
no I meant in github issues
<headius[m]>
I don't thikn there's a similar spec
<headius[m]>
heh, specs don't even appear to have /o in language/regexp_spec.rb
<enebo[m]>
but we just put in GH#666 in exclude string text
<headius[m]>
ah yeah
<enebo[m]>
maybe "wontfix: GH#666"
<headius[m]>
ok there's like three /o specs total in language and none test threading
<headius[m]>
good thing we don't just rely on spec
<headius[m]>
I do wonder what guarantees Hotspot makes about transitions from interpreter to compiled
<headius[m]>
we know they submit the code to a background compiler threads, and at some point they flip some switch and it no longer enters the interpreter for a given method
throsturt has joined #jruby
<enebo[m]>
OSR may help
<headius[m]>
yeah they do have the ability to transition back and forth at any time
<headius[m]>
I think the only real equivalent right now would be how they lazily bind lambdas
<headius[m]>
this case is contrived of course because even if the once didn't guarantee once execution for everything inside the regexp, it would still hang in the main thread
jrafanie has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
<headius[m]>
enebo: I just had a desire to see the expanded options from .java_opts files so I'm going to add that