adam12 has joined #jruby
sapphire1896[m] has joined #jruby
sapphire1896[m] has left #jruby [#jruby]
sagax has joined #jruby
curious-antelope has joined #jruby
curious-antelope has left #jruby [#jruby]
smudge-the-cat has joined #jruby
smudge-the-cat has left #jruby [#jruby]
smudge-the-cat has joined #jruby
smudge-the-cat has left #jruby [#jruby]
brometeo[m] has joined #jruby
<headius> transfer spec only seems to hang in a full run... still trying to narrow it down
<enebo[m]> This is a head scratcher. I know this is on windows and windows is weird with IO already but why would JIT cause this?
<headius> oh I glanced at it but did not realize it was only happening in jit
<headius> yup I have no idwa
<headius> idea
<enebo[m]> I marked it for 9.3.9.0 since it is a logstash bug
<headius> I need to get a windows VM up and going again on new machine
<headius> aha I was not running right specs... Fiber#transfer is in stdlib 'fiber' technically
<headius> enebo: I can think of no reason why jit would cause that issue... nothing there should be compiled in and it's all done via method calls and constant lookups
<headius> need to set a breakpoint in StringIO.new at the point it is called from jitted code and see what's up
<headius> woot I think I have a repro
<headius> combination of some weird Fiber#resume that is supposed to error (but doesn't) and trying to transfer from the root fiber... seems like some fiber data gets corrupted
<enebo[m]> headius: I asked a question...why the ENV["test"] = ""
<headius> Yeah I don't know what that is either and it shouldn't affect anything
<headius> Are you able to reproduce this?
<enebo[m]> I need to try it still
<enebo[m]> I am just confused out of the gate why JIT would cause this
<enebo[m]> I am not surprised something broke on windows involving IO but the fact JIT causes it makes no sense to me
<headius> Nor to me
<enebo[m]> heh...ENV["test"] = "" is the issue...now to figure out why
<headius> Wut
<headius> Is it resetting the external encoding somehow?
<enebo[m]> but only when JIT :)
<headius> So in that case the jit would compile the whole script, embedding the encodings of those strings, and if that's the old encoding and ENV is somehow altering the global external encoding, that might cause it to reset
<headius> Oh but the sequence is wrong
<headius> The updated external encoding happens after that line
<headius> 🤷‍♂️
<enebo[m]> yeah fun one
<headius> Check that the default external encoding has actually been updated after that line
<enebo[m]> yeah I am just tracing through Encoding.default_external =
<enebo[m]> This would change it to whatever is UTF_8
<headius> Yeah I still don't have a good theory. Even if ENV does mess with the external encoding, the next line should reset it
<enebo[m]> Ok a new clue
<enebo[m]> I make "" into a string with forced encoding of UTF-8 and it works
<enebo[m]> heh...progress but still no clue
<headius> I don't see anything in ENV logic that would mess with default_external
<enebo[m]> If I move the ENV to the top it does not change the behavior
<enebo[m]> It is sort of like if ENV is used the default_external is cached in the JIT
<headius> enebo: some day I'll learn to test old versions first... this hanging transfer spec also hands on 9.3
<headius> likely never worked quite right but was hard erroring due to missing features when running under 3.0 mode
<headius> s/hands/hangs/
<headius> the problem is a bit tricky... if I am getting this right, main thread resumes fiber1, which then resumes the main fiber... does not detect it is in the process of resuming so it goes ahead and transfers control back... but now the main fiber looks like it is supposed to return to fiber1, which is dead, and a subsequent transfer from main fiber to a new fiber hangs waiting for that dead fiber to pick it up
<headius> it is supposed to error when fiber1 tries to resume main fiber but because main fiber does not have anyone waiting on it, it looks like it is resumable
<headius> so it corrupts the main fiber
<headius> basically incorrectly says "this fiber is being waited on by fiber1, so when it transfers, that's the fiber you should return to"
<headius> may be simple enough to just always error if trying to resume root fiber from a child fiber, since there's no way you could be doing that unless main fiber were already resuming
<enebo[m]> headius: heh. yeah re not testing older versions
<headius> enebo: I pushed a fix for this fiber thing that just hard errors if a fiber tries to resume the root fiber
<headius> that spec now passes and does not muck up the root fiber's state, so the subsequent transfer spec also runs to completion and passes
<headius> may need an overhaul of this in the shorter term but that's a bigger job... I feel like I finally understand what transfer is (pass control to the target fiber, but have it return to the fiber waiting on me)
<headius> enebo: could that stringio bug be modifying some global blank string to have that encoding?
<headius> I think that is the problem
<headius> JIT mode will cache a single instance of ByteList for all strings of the same content in a given file
<headius> strDup dups the RubyString object but shares the ByteList
<headius> it may be using a global blank ByteList
<headius> we probably should have a ByteList subtype or sibling type that is fully immutable for this and frozen string cases, so there's no chance to mutate it accidentally
<enebo[m]> OMG
<headius> JIT uses a global static blank bytelist for empty strings
<enebo[m]> This makes sense...let me try a non-empty string but this string bank maybe is broken?
<headius> it does mark it shared but getByteList does not unshare so we end up modifying the global blank bytelist
<headius> so strDup.getByteList just uses the same shared bytelist again
<headius> and then we set default Locale Encoding into it
<headius> if that line I linked above is modified to unshare or explicitly dups the bytelist it will be fixed I bet
<headius> so yeah we need an immutable bytelist type, which would also potentially optimize frozen strings better too
<headius> supertype bytelist, subtypes mutable and immutable
<headius> only bimorphic so even older hotspot should still be able to optimize it
<enebo[m]> I will remove sharing
<headius> it should only require making all methods call through getters to get ByteList innards, and then we error if setters are used on immutable one
<enebo[m]> immutability would have prevented this so that is a good idea
<enebo[m]> but not a today thing
<headius> heh no
<enebo[m]> this not sharing on env values is not really a big deal
<enebo[m]> if you are constantly setting env then you have at least two problems
<enebo[m]> hmm it may be used for a bit more but I will test this
<headius> did a quick experiment in refactoring toward a mutable bytelist and it's probably a day's work to split into mutable and immutable
<headius> main problem is we have a lot of places that `new ByteList` that would need to go through a factory method to get mutable or immutable appropriately
<headius> or we can do the weak hack of just introducing ImmutableByteList that overrides setters to error rather than having final fields
<headius> we lose some benefit of truly final fields but it would catch mutation bugs
<enebo[m]> download bellsoft liberica
<enebo[m]> my windows machine has ideas
<enebo[m]> and those ideas are slow and confusing
<headius> ha
<headius> not just a simple refactoring... we arraycopy directly into the array and stuff so each method needs to be reviewed
<headius> we'd need to go through setter and mutator methods for any mutation so that a subtype can error
<headius> so yeah it is doable but a project
<enebo[m]> headius: the fix for today is going to just be str.getByteList().shallowDup() right?
<enebo[m]> we can still share the backing array of whatever byte[] we are making
<headius> that should be enough since we only mutate the encoding
<headius> if we get around to this ByteList rework, you would do dupWithEncoding and have more fluent-style mechanisms for getting a new ByteList from an old one that knows about mutability
<enebo[m]> My windows box is just not loading JRuby no matter what I try. I don't want to spend 10x the time loading the IDE when I can just fix this on the linux side (I will edit with vi to test though)
<headius> not loading JRuby?
<headius> like IntelliJ not loading the project?
<enebo[m]> ultimately I feel we should consider encoding to be part of sharing
<headius> well the bigger issue is that ByteList has no knowledge of its shared status
<headius> this all plays into ByteList being too dumb and all the sharing and code range logic living outside of it
<enebo[m]> yeah I see
<enebo[m]> ok well I find the concept of bytelist as something to be redone. It is {bytes, index, size, encoding} but it is clear in how we use it that this tuple is not really enough without ripping all the values out of it
<enebo[m]> or at least we have had hundreds of bugs from this not quite enough and no abstraction
<headius> yeah this is a classic bug
<enebo[m]> yep. It tends to be 'begin' but this is the same sort of issue
<headius> we need to bake frozen/immutable into ByteList all the way down
<enebo[m]> yeah
<enebo[m]> we will get that done when we port over to Kotlin
<headius> you freeze a string, it flips to a frozen ByteList... if you dup that string for mutation it creates a new mutable ByteList, but if you dup it into a new frozen string it can share
<headius> hah
<headius> yeah once we hire a team of interns to do all the work for us
<enebo[m]> I have wondered how much a language with immutability builtin can eliminate checks in its compiled code
<enebo[m]> Rust eliminates a ton so I am joking about Kotlin but it does know about immutable values
<enebo[m]> interesting non of that code is even being hit
<enebo[m]> That has to be the base problem but that specific code is not being hit by the ENV snippet
<enebo[m]> Hmm no @JRubyMethod for op_aset until RubyHash
<headius> it is overridden
<headius> doesn't matter if it is @JRubyMethod if it overrides the op_aset from RubyHash
<enebo[m]> yeah
<enebo[m]> It is not being called
<enebo[m]> so why would that be?
<headius> op_aset is overridden by StringOnlyRubyHash, are you saying that is not being called?
<enebo[m]> I have a print in it and even in newString and nothing is printing
<headius> that calls case_aware_op_aset which calls newName which does the encoding juggling
<enebo[m]> I have prints in all of those
<headius> on Windows?
<enebo[m]> on windows yeah
<enebo[m]> I am using vi since I cannot get idea to load the project but I can see maven compiling the file I am changing
<headius> you sure it'
<enebo[m]> I can also still see the error go away if I don't jit
<enebo[m]> no
<headius> it's running the right one?
<headius> I don't see how it could not be calling this
<enebo[m]> :)
<enebo[m]> Maybe I am calling installed one
<enebo[m]> I will double check
<headius> []= is op_aset, overridden in that env hash
<enebo[m]> it wouldn't be the firs time
<enebo[m]> yeah
<enebo[m]> I mean I know that
<headius> yeah
<headius> I suspect pebkac
<headius> otherwise I have no idea
<enebo[m]> haha. I switched about 30 tries beforehand
<enebo[m]> I hate programming
<headius> hahah
<enebo[m]> I did a new command line and just typed it because I am quick
<enebo[m]> then just hit muscle memory
<headius> it happens... just last week I could not get a debug breakpoint to fire because I was debugging the wrong codebase
<enebo[m]> yeah
<enebo[m]> This reminds me that in something else I was writing I needed to use the word content and all I could write is context
<enebo[m]> Every time I would try and write the word I would write context
<enebo[m]> ok well shallowDup fixes it :)
<headius> several of these WIP specs are basically things that always failed but now there's a new version of the spec for 3.x
<enebo[m]> yeah I have fixed a few where I know it was broken in 9.3 but it I also fixed 3-4 other problems and those were not broken on 9.3
<enebo[m]> So I should make smaller commits
<enebo[m]> headius: so why only windows?
<headius> it may affect unix too but the default filesystem, locale, and internal encodings are usually all UTF-8 so we don't see it
<enebo[m]> aha
<headius> I could not reproduce on unix but I'm not sure how to force the locale encoding to be something different
<enebo[m]> yeah you are right. This is a problem everywhere but it happens to only be windows which is not already UTF-8
<headius> I am quickly implementing Thread.ignore_deadlock to do nothing... should that be a verbose or non-verbose warning?
<enebo[m]> ah I see you answered this already. I was going to comment on this but you did it
<headius> it is a weird feature
<enebo[m]> hmm
<enebo[m]> headius: verbose obviously is a simple answer but it depends on how much someone depends on this feature to do something
<headius> I don't see a way to implement deadlock detection without overhauling locks and doing a lot of work at those boundaries
<headius> which is why JDK only does it when you pull a thread dump
<headius> our default is really "ignore" since we don't fast fail when you walk into a deadlock
<enebo[m]> look for "ignore_deadlock" on github
<enebo[m]> If a super common gem does it then people will complain
<headius> 3.0 feature, I doubt it is used in the wild much yet
<enebo[m]> I guess start with verbose and we can promote it if anyone ever notices
<enebo[m]> but if this does end up some common boilerplate in a library then people will complain that they endlessly see this warning on boot
<headius> nearly all uses are in tests for this feature
<headius> there are a couple sets in the wild but all seem to be setting to false
<headius> three instances in the wild that are not tests or specs for the feature
<headius> I will look up the feature and the justification...
<headius> TR no-ops as well
<headius> they don't warn
<headius> ffs
<enebo[m]> in that case
<headius> it looks like it was added because they have some edge cases where they get false positives, specifically surrounding signal handlers
<headius> which they run in the current thread still, I believe
<headius> ioquatix disagrees and so do I but the discussion is otherwise all in Japanese
<headius> I
<enebo[m]> meh
<headius> I will just do it without a warning... should not have added this feature in the first place and instead fixed signal handling
<enebo[m]> yeah no warning seems right
<headius> how about notImplemented bit?
<headius> it would still be callable but if someone checked for it they'd know not to use it
<headius> we can pass specs with what I have, no warning and notImplemented = true
<enebo[m]> yeah I guess so
<enebo[m]> I don't know if anyone will do that but that is a valid strategy
<headius> can I impl it in Ruby so we don't add more useless methods to Java?
<headius> I'll push a PR
<headius> I'm going to run through and audit the 2.7, 3.0, and 3.1 feature list issues
<enebo[m]> ok
<headius> if that PR looks ok I will merge
<enebo[m]> yeah at some level I wonder about load time with lots of Ruby but that is our long term goal
<enebo[m]> if this ends up stacking up we might want to dump a single file of all core_ext or something like that
<headius> it is doable and not too hard, we just haven't done it
<headius> smash into a single file during build or even precompile
<headius> I appreciate the concern but it is a general thing we need to fix so I feel like adding one more is not a huge concern right now
<enebo[m]> oh I agree...just bringing it up
<headius> this is some new comment pragma that I guess freezes constant values at assignment
<enebo[m]> ah I have not looked at it at all
<headius> ok
<enebo[m]> adding the pragma should be really easy but I suppose we need to mark those nodes
<headius> seems like it is driven by Ractor interest so I'm not sure how crucial i tis
<enebo[m]> I figured it was only for ractor but you are right...someone may use it anyways
<enebo[m]> Actually having seen the examples I am not sure anyone would use it
<headius> yeah it is weird
<headius> moving on... I will keep auditing and impl anything really small, and then circle back to the key features we are missing
<headius> we are close
<enebo[m]> we need hash identhash impls
<enebo[m]> TestHash#test_slice_on_identhash [/home/runner/work/jruby/jruby/test/mri/ruby/test_hash.rb:1168]:
<enebo[m]> <{"str"=>1, "str"=>2}> expected but was
<enebo[m]> <{"str"=>2}>.
<enebo[m]> I believe this is used in Rails now
<headius> working but a little weird on that output
<headius> I will call the feature done and filed this to track the weirdness
<enebo[m]> I just fixed something on 9.3 which was double warning
<enebo[m]> I did merge that so it maybe is a similar thing
<enebo[m]> quick check
<headius> ok
<headius> enebo: you implemented that Kernel#clone freezing stuff yeah?
<enebo[m]> HAHAHAHAHA
<enebo[m]> headius: yeah
<enebo[m]> so this is double printing
<headius> ok
<enebo[m]> because we are compiling the main script and failing
<enebo[m]> Or it looks that way. First one is tryCompile and second one is interpreter
<headius> ahhh ok
<headius> so it treats the syntax error in compile or interpret and falls back
<headius> this must be a parser error in CRuby though yeah?
<enebo[m]> I am tracing this back
<headius> yield in any class or sclass body should syntax error out
<enebo[m]> ah yeah precompileCLI will catch any Exception
<headius> it should propagate RaiseException
<headius> probably
<headius> but still think this should happen in parser
<enebo[m]> well in this case for sure
<enebo[m]> It happens as a check in IRBuilder
<enebo[m]> but it could happen in parser although I think this happens in compile.c in MRI too
<enebo[m]> there are at least a dozen syntaxerror in irbuilder
<headius> yeah that would be fine too then
<headius> so it just needs to propagate it
<enebo[m]> but is there a reason why RaiseException would still work if then interpreted
<headius> not that I can think of
<headius> that is only raised for ruby reasons
<enebo[m]> I can't but I don't trust my mind today :)
<headius> compile failure in JIT should always be NotCompileableException
<enebo[m]> we can just never rewrite the JIT in Ruby now :P
<headius> and I guess I do other Exception in case of compiler bugs
<headius> NPE or whatever
<enebo[m]> but yeah we have to use the right exception in JIT
<headius> I will try a fix
<enebo[m]> I just added an empty raiseexception catch
<enebo[m]> compiling
<enebo[m]> hmm
<headius> you can catch SyntaxError
<headius> if you want to keep it narrow
<enebo[m]> I don't if it doesn't need to be
<enebo[m]> If for example we live create a Ruby instance in IR builder at some point and it is invalid it can be almost any kind of raise exception
<enebo[m]> it will not work when interpreted either
<enebo[m]> so maybe less code is better and broader will reduce doing some stuff twice
<enebo[m]> diff --git a/core/src/main/java/org/jruby/Ruby.java b/core/src/main/java/org/jruby/Ruby.java... (full message at <https://libera.ems.host/_matrix/media/r0/download/libera.chat/d84881b362d78fc8b25a445968c3e47f323bc30c>)
<enebo[m]> ARRG :)
<enebo[m]> anyways this works for the double stuff
<enebo[m]> I will throw it into a PR
<headius> yeah fix runWithGetsLoop too because that does the compile as well
<headius> it probably shouldn't duplicate this logic but it does
<enebo[m]> ok
<headius> and it catches Throwable... yuck
<enebo[m]> haha I was just going to point that out
<headius> so I am done for today.. 3.0 remaining issues are almost all related to scheduler or ractor, with a few little things here and there and the big one being the prepend/include module stuff
<headius> I suspect we are down to that and a couple other key items and in good shape
<enebo[m]> refinements issue somewhere which could even be the include/prepend thing
<headius> Yeah so that and greening up those library suites and then we can do a review of what remains failing
<headius> I feel like we got several folks already running off of snapshots