Skip to content

Loading…

Range#size missing from JRuby 1.7.8 in 2.0 mode #1252

Closed
wants to merge 25 commits into from

9 participants

@tedpennings

Range#size appears to be missing from the latest JRuby in Ruby 2.0.0 mode. Range#size was added to Ruby in 2.0.0. The other new Range methods added, like #bsearch, appear to be there -- only #range is missing.

irb(main):055:0> puts RUBY_VERSION
2.0.0
=> nil
irb(main):056:0> puts JRUBY_VERSION
1.7.8
=> nil
irb(main):057:0> (80..85).class
=> Range
irb(main):058:0> (80..85).size
NoMethodError: undefined method `size' for 80..85:Range
    from (irb):58:in `evaluate'
    from org/jruby/RubyKernel.java:1123:in `eval'
    from org/jruby/RubyKernel.java:1519:in `loop'
    from org/jruby/RubyKernel.java:1284:in `catch'
    from org/jruby/RubyKernel.java:1284:in `catch'
    from /Users/n0173592/.rvm/rubies/jruby-1.7.8/bin/irb:13:in `(root)'
irb(main):059:0> (80..85).first
=> 80
irb(main):060:0> (80..85).respond_to? :size
=> false

Enumerator#size appears to be defective and may be related:

# same session as above -- 1.7.8 in 2.0 mode
irb(main):061:0> [1,2,3,4]
=> [1, 2, 3, 4]
irb(main):062:0> [1,2,3,4].class
=> Array
irb(main):063:0> [1,2,3,4].each.size
=> nil   # should be 4
irb(main):064:0> [1,2,3,4].each.class
=> Enumerator
irb(main):065:0> [1,2,3,4].each.respond_to? :size
=> true

For comparison, here's the MRI 2.0 behavior:

2.0.0p247 :001 > RUBY_VERSION
 => "2.0.0" 
2.0.0p247 :002 > JRUBY_VERSION
NameError: uninitialized constant JRUBY_VERSION
    from (irb):2
    from /Users/n0173592/.rvm/rubies/ruby-2.0.0-p247/bin/irb:13:in `<main>'
2.0.0p247 :003 > (80..85).class
 => Range 
2.0.0p247 :004 > (80..85).size
 => 6 
2.0.0p247 :005 > (80..85).first
 => 80 
2.0.0p247 :006 > (80..85).respond_to? :size
 => true 
2.0.0p247 :007 > [1,2,3,4].each.size
 => 4 
2.0.0p247 :008 > [1,2,3,4].each.class
 => Enumerator 
2.0.0p247 :009 > [1,2,3,4].each.respond_to? :size
 => true 

I'd be happy to send in a PR for this if you could point me in the direction of where this should be implemented. It looks like the RubyRange.java and RubyEnumerator.java classes are probably the most obvious places, but I wanted to ask before just sending in a PR for that (+tests).

@tedpennings tedpennings reopened this
@enebo
JRuby Team member

RubyRange.java seems like it is where a @JRubyMethod for this should be made. Enumerable size in 2.0+ appears to be a funcall to a size method if it is available or nil.

@tedpennings

Ok cool, thanks @enebo ! I'll take a stab at Range#size tonight. I'll give Enumerable some thought but it might be a little too in depth for me.

@dmarcotte dmarcotte added a commit to dmarcotte/jruby that referenced this pull request
@dmarcotte dmarcotte Implement Numeric#step.size
Gets Numeric#step.size doing its thing by putting the following pieces
in place:
* implement Numeric#intervalStepSize closely following the MRI
implementation (https://github.com/ruby/ruby/blob/09b02349c212cac6395e9a634e3d4610e9bbc48c/numeric.c#L1799)
* implement Numeric#floatStepSize which Numeric#intervalStepSize relies
on, again porting from MRI (https://github.com/ruby/ruby/blob/09b02349c212cac6395e9a634e3d4610e9bbc48c/numeric.c#L1748))
* refactor Numeric#floatStep19 to also use the new floatStepSize, which
not only avoids duplication, but also fixes some tests
* create Numeric#stepSize, and use it to enumeratorizeWithSize our steps

We'll be able to un-exclude test_size_for_step from test_enumerator.rb
once Range#size is implemented (jruby#1252).
52e8116
@dmarcotte dmarcotte added a commit to dmarcotte/jruby that referenced this pull request
@dmarcotte dmarcotte Implement Numeric#step.size
Gets Numeric#step.size doing its thing by putting the following pieces
in place:
* implement Numeric#intervalStepSize closely following the MRI
implementation (https://github.com/ruby/ruby/blob/09b02349c212cac6395e9a634e3d4610e9bbc48c/numeric.c#L1799)
* implement Numeric#floatStepSize which Numeric#intervalStepSize relies
on, again porting from MRI (https://github.com/ruby/ruby/blob/09b02349c212cac6395e9a634e3d4610e9bbc48c/numeric.c#L1748))
* refactor Numeric#floatStep19 to also use the new floatStepSize, which
not only avoids duplication, but also fixes some tests
* create Numeric#stepSize, and use it to enumeratorizeWithSize our steps

We'll be able to un-exclude test_size_for_step from test_enumerator.rb
once Range#size is implemented (jruby#1252).
633f935
@dmarcotte

Hey @tedpennings, hopefully I'm not chiming in too late, but there's been a couple of recent changes that should help you fix this up:

  • #1281 added Numeric#intervalStepSize which you'll want to call in your Range#size (similar to how it's implemented in MRI)
  • #1039 added RubyEnumerator#enumeratorizeWithSize which you'll be able to use in Range#each instead of enumeratorize to fix the enum cases you note above

Then you'll be able to delete exclude :test_size, "needs investigation" from test/mri/excludes/TestRange.rb to get the tests for this in test/mri/ruby/test_range.rb running in CI.

Hope that helps! Let me know if you have any questions...

@tedpennings

Thanks @dmarcotte ! I'm going to take a crack at this now. I'll update this issue once I've got something to show :smile:

@tedpennings

How do the above two commits look? Is there anything that should be done in there to ensure that the @JRubyMethod is only available in 2.0+ mode? (1.9 doesn't have a Range#size method)

I'll take another look at the Range#step and Range#each enumerator size problem tomorrow. I think that's a bit bigger. It might be worth a separate issue. I can create it if that would help.

@dmarcotte

Looking good @tedpennings! A few notes:

  • this should be checking instanceof RubyNumeric rather than instanceof RubyInteger
  • test_size won't pass until Range#each.size is fixed, so we should fix it here. You should be able replace enumeratorize(runtime, this, "each"); with enumeratorizeWithSize(context, this, "each", size(context)); to get this going (let me know if I'm missing something here!)
  • can you also rebase again from master when you make these changes? The tests happened to be in bad shape the last time you rebased, so Travis can't currently run on your changes

As for 2.0 vs. 1.9: the next major version of JRuby (the version being worked on in master) will only support a single Ruby version, so what you've got here is correct.

Finally, good call on step.size. That needs to be taken care of too, but it should be tackled separately, so yeah sending an issue for that would be great.

Hope that all makes sense! Thanks again, and feel free to let me know if you have more questions.

@tedpennings

Ok @dmarcotte - I'll rebase when I get home.

You're right re RubyNumeric instead of RubyInteger. I was thinking of the (quirky) MRI 2.0 behavior where it will return a size for a range of floats, and an Enumerable with size for each/step, but it won't return an array for them.

2.0.0p247 :003 > (1.5..5.5).size
 => 5 
2.0.0p247 :004 > (1.5...5.5).size
 => 4 
2.0.0p247 :005 > (1.5...5.5).each
 => #<Enumerator: 1.5...5.5:each> 
2.0.0p247 :006 > (1.5...5.5).each.size
 => 4 
2.0.0p247 :007 > (1.5...5.5).step
 => #<Enumerator: 1.5...5.5:step> 
2.0.0p247 :008 > (1.5...5.5).step.size
 => 4 
2.0.0p247 :009 > (1.5...5.5).to_a
TypeError: can't iterate from Float
    from (irb):9:in `each'
    from (irb):9:in `to_a'
    from (irb):9
    from /Users/ted/.rvm/rubies/ruby-2.0.0-p247/bin/irb:13:in `<main>'

Last night another test case came to mind that I think we need to consider. RubyNumeric/intervalStepSize doesn't handle RubyBignum. For a range size, that's actually a significant limitation, so RubyNumeric.intervalStepSize might need refactoring.

Here's the error you get with my present PR from Bignums:

 $ bin/jruby -S irb
irb(main):001:0> a=2**64
=> 18446744073709551616
irb(main):002:0> b=a**2 # 2^128
=> 340282366920938463463374607431768211456
irb(main):003:0> c=b**2  # 2^256
=> 115792089237316195423570985008687907853269984665640564039457584007913129639936
irb(main):004:0> c.class
=> Bignum
irb(main):005:0> (b..c)
=> 340282366920938463463374607431768211456..115792089237316195423570985008687907853269984665640564039457584007913129639936
irb(main):006:0> (b..c).size
Java::JavaLang::ClassCastException: org.jruby.RubyBignum cannot be cast to org.jruby.RubyFixnum
    from org.jruby.RubyNumeric.intervalStepSize(RubyNumeric.java:917)
    from org.jruby.RubyRange.size(RubyRange.java:676)
    from org.jruby.RubyRange$INVOKER$i$0$0$size.call(RubyRange$INVOKER$i$0$0$size.gen)
    from org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:306)
    from org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:136)
    from org.jruby.ast.CallNoArgNode.interpret(CallNoArgNode.java:60)
    from org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    from org.jruby.ast.RootNode.interpret(RootNode.java:129)
    from org.jruby.evaluator.ASTInterpreter.INTERPRET_EVAL(ASTInterpreter.java:95)
    from org.jruby.evaluator.ASTInterpreter.evalWithBinding(ASTInterpreter.java:179)
    from org.jruby.RubyKernel.evalCommon(RubyKernel.java:934)
    from org.jruby.RubyKernel.eval19(RubyKernel.java:898)
    from org.jruby.RubyKernel$INVOKER$s$0$3$eval19.call(RubyKernel$INVOKER$s$0$3$eval19.gen)
    from org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:180)
    from org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:70)
    from org.jruby.ast.FCallManyArgsNode.interpret(FCallManyArgsNode.java:60)
... 126 levels...
    from Users.n0173592.Developer.jruby.bin.jirb.load(/Users/n0173592/Developer/jruby/bin/jirb)
    from org.jruby.Ruby.runScript(Ruby.java:809)
    from org.jruby.Ruby.runScript(Ruby.java:802)
    from org.jruby.Ruby.runNormally(Ruby.java:671)
    from org.jruby.Ruby.runFromMain(Ruby.java:520)
    from org.jruby.Main.doRunFromMain(Main.java:395)
    from org.jruby.Main.internalRun(Main.java:290)
    from org.jruby.Main.run(Main.java:217)
    from org.jruby.Main.main(Main.java:197)
    from sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    from sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    from sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    from java.lang.reflect.Method.invoke(Method.java:606)
    from org.flatland.drip.Main.invoke(Main.java:117)
    from org.flatland.drip.Main.start(Main.java:88)
    from org.flatland.drip.Main.main(Main.java:64)irb(main):007:0> 
@dmarcotte

Great catch on the class cast error @tedpennings! I'll get that fixed up very soon; I reckon you don't need to worry about it for your PR.

subbuss and others added some commits
@subbuss subbuss Minor: Removed dead arg to call in Helpers ddced11
@subbuss subbuss [IR] Some more fixes and FIXMEs to inlining code
* More progress inlining code on bench_method_dispatch.rb

* The next set of crashers in inlining requires fixes to the
  WrappedIRClosure operand to take an explicit self arg so that
  on inlining, the correct (original) self can be passed into
  the block rather than passing the self from the host scope
  into which code got inlined. TO BE DONE.
37b11f8
@subbuss subbuss [IR] Extend WrappedIRClosure to include an explicit self operand
* This fix is required for proper inlining of scopes that contain
  blocks so that the self prior-to-inlining can be passed into
  the block after-inlining into another scope.

* With this fix, bench_method_dispatch.rb runs with -Xir.profile=true
  without crashing. Same for bench_fib_recursive, bench_red_black,
  shootout/meteor, shootout/mandelbrot, bench_richards,
  bench_neural_net, and bench_tictactoe.

* There are still known bugs in the inlining code (search for
  FIXMEs or 'This is buggy' comments in the relevant code), but the
  correctness has moved along far enough to enable profiling and
  inlining on a large enough set of programs without crashing or
  yielding incorrect results.
4b53d5c
@subbuss subbuss [IR] Fixed broken build from 8fc3ee3 7f7db18
@tedpennings tedpennings fix an instanceof check to use the right supertype (Numeric) 82a142e
@BanzaiMan BanzaiMan Undo fast_finish b029b86
@BanzaiMan BanzaiMan Re-enable fast_finish 2b7a389
@dmarcotte dmarcotte 1.9+ blockless Struct#select returns an enumerator 6c95796
David Masover Added failing test for basic subList functionality. ef61252
David Masover subList toIndex should be exclusive. Fixes #1274. 91e6dc8
@user454322 user454322 Adding spec for JRUBY-5946
 This  accompanies jruby/jruby@2c8e310
dcfe934
@dmarcotte dmarcotte Add Enumerator#cycle.size and Array#cycle.size d6edc7f
David Masover subList size should be toIndex - fromIndex.
Related to #1274.
Tests pass now.
c14878d
@dmarcotte dmarcotte Fix cast error for step.size on bignums e0a3121
@bruceadams bruceadams Don't set java.net.preferIPv4Stack in shell scripts #1286 443307d
@enebo enebo Fixes 1291. Sidekiq - Minitest error: NoMethodError: unmocked method …
…:==, expected one of []
b94cde6
@enebo enebo Unbreak master..poor merge 15ce044
@dragonsinth dragonsinth Fix #1222, StringIO.gets w/ utf8 5c91aa1
@mkristian mkristian replaced JavaUtilLoggingLogger with StandardErrorLogger using the sam…
…e format. removed any import or usage of java.util.logging
c5a2f5c
@mkristian mkristian no release repository in any artifact which get published on maven ce…
…ntral (surprised that oss.sonatype.org does not prevent that). that just produces a lot of traffic on that repository and if that repository is inaccessible the artifact can NOT be used anymore

[skip ci]
7bb3871
@enebo enebo Fixes #1198. Strings not printed properly to windows console 7f1f958
@subbuss subbuss Always pass RootNode into runInterpreter
* This prevents IR interpreter from crashing since it always
  expects a RootNode.
* 2 more failing specs now green.
bb6147b
@subbuss subbuss [IR] Begin/end block share scope of its lexical parent.
* Thus far, begin/end block were getting their own scope whereas
  they ought to share their parent's scope just like for-loops.
  This patch fixes it.

* One more spec now green. More debugging needed to figure out
  why the other BEGIN_spec is still failing.
df3347c
@tedpennings

Hm I think I failed at git :( I'll create a new PR for this one change and you can close this as unmerged.

For future reference, how would I rebase to make this work but not have a million commits in this PR?

@dmarcotte

Hrm... looks like you were working on master in your fork, so I think when you rebased it and force-pushed, the commits you pulled in are now in a strict sense "different" from the ones already in jruby/master.

You should be able to avoid this by always working on a branch in your fork, and keeping its master up to date from jruby/master with git pull upstream master (this assumes you called your jruby remote "upsteam", i.e. you've done git remote add upstream git@github.com:jruby/jruby.git)

Note that since the rebase monkeyed with your master's history, to get back to a good state, the easiest thing may be to re-fork and apply your changes in a branch there.

Hope that solves it for you... as always, more questions are welcome.

@tedpennings

Thanks, doing that now. I'll create a new PR once it's done.

I think I'm going to add some rspec tests for different strange range conditions too, just so we have our bases covered re integer overflows and casts, e.g., (Fixnum..Bignum).size #=> Fixnum; (Fixnum..Bignum).size #=> Bignum; (Bignum..Bignum).size #=> Fixnum, etc

@dmarcotte

Sounds good.

The specs sound great too, but I'd say they should be sent to RubySpec rather than be added here, so you should be good to go with the PR as-is.

Let me know if you need anything else!

(Oh, and let me know if it'll be a while before you can send for whatever reason. No worries if that's the case! It's just that I'm putting off sending a change that would conflict with yours to avoid causing you churn, but I don't want to sit on it too long.)

@tedpennings

Ok all set, see #1305 . Thanks for all the help!

@dmarcotte dmarcotte added a commit to dmarcotte/jruby that referenced this pull request
@tedpennings tedpennings Add a size method to RubyRange to resolve #1252 5311ed7
@enebo enebo closed this in #1305
@enebo enebo modified the milestone: JRuby 1.7.10, JRuby 1.7.11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 2, 2013
  1. @tedpennings
  2. @tedpennings

    core/src/main/java/org/jruby/RubyRange.java

    tedpennings committed
    Implement Range#size to fix #1252
Commits on Dec 4, 2013
  1. @subbuss @tedpennings
  2. @subbuss @tedpennings

    [IR] Some more fixes and FIXMEs to inlining code

    subbuss committed with tedpennings
    * More progress inlining code on bench_method_dispatch.rb
    
    * The next set of crashers in inlining requires fixes to the
      WrappedIRClosure operand to take an explicit self arg so that
      on inlining, the correct (original) self can be passed into
      the block rather than passing the self from the host scope
      into which code got inlined. TO BE DONE.
  3. @subbuss @tedpennings

    [IR] Extend WrappedIRClosure to include an explicit self operand

    subbuss committed with tedpennings
    * This fix is required for proper inlining of scopes that contain
      blocks so that the self prior-to-inlining can be passed into
      the block after-inlining into another scope.
    
    * With this fix, bench_method_dispatch.rb runs with -Xir.profile=true
      without crashing. Same for bench_fib_recursive, bench_red_black,
      shootout/meteor, shootout/mandelbrot, bench_richards,
      bench_neural_net, and bench_tictactoe.
    
    * There are still known bugs in the inlining code (search for
      FIXMEs or 'This is buggy' comments in the relevant code), but the
      correctness has moved along far enough to enable profiling and
      inlining on a large enough set of programs without crashing or
      yielding incorrect results.
  4. @subbuss @tedpennings
  5. @tedpennings
Commits on Dec 5, 2013
  1. @BanzaiMan @tedpennings

    Undo fast_finish

    BanzaiMan committed with tedpennings
  2. @BanzaiMan @tedpennings

    Re-enable fast_finish

    BanzaiMan committed with tedpennings
  3. @dmarcotte @tedpennings
  4. @tedpennings

    Added failing test for basic subList functionality.

    David Masover committed with tedpennings
  5. @tedpennings

    subList toIndex should be exclusive. Fixes #1274.

    David Masover committed with tedpennings
  6. @user454322 @tedpennings

    Adding spec for JRUBY-5946

    user454322 committed with tedpennings
     This  accompanies jruby/jruby@2c8e310
  7. @dmarcotte @tedpennings
  8. @tedpennings

    subList size should be toIndex - fromIndex.

    David Masover committed with tedpennings
    Related to #1274.
    Tests pass now.
  9. @dmarcotte @tedpennings
  10. @bruceadams @tedpennings
  11. @enebo @tedpennings
  12. @enebo @tedpennings

    Unbreak master..poor merge

    enebo committed with tedpennings
  13. @dragonsinth @tedpennings
  14. @mkristian @tedpennings

    replaced JavaUtilLoggingLogger with StandardErrorLogger using the sam…

    mkristian committed with tedpennings
    …e format. removed any import or usage of java.util.logging
  15. @mkristian @tedpennings

    no release repository in any artifact which get published on maven ce…

    mkristian committed with tedpennings
    …ntral (surprised that oss.sonatype.org does not prevent that). that just produces a lot of traffic on that repository and if that repository is inaccessible the artifact can NOT be used anymore
    
    [skip ci]
  16. @enebo @tedpennings
  17. @subbuss @tedpennings

    Always pass RootNode into runInterpreter

    subbuss committed with tedpennings
    * This prevents IR interpreter from crashing since it always
      expects a RootNode.
    * 2 more failing specs now green.
  18. @subbuss @tedpennings

    [IR] Begin/end block share scope of its lexical parent.

    subbuss committed with tedpennings
    * Thus far, begin/end block were getting their own scope whereas
      they ought to share their parent's scope just like for-loops.
      This patch fixes it.
    
    * One more spec now green. More debugging needed to figure out
      why the other BEGIN_spec is still failing.
Showing with 271 additions and 282 deletions.
  1. +0 −3 bin/jruby.bash
  2. +0 −3 bin/jruby.sh
  3. +1 −1 core/src/main/java/org/jruby/Ruby.java
  4. +38 −18 core/src/main/java/org/jruby/RubyArray.java
  5. +27 −2 core/src/main/java/org/jruby/RubyEnumerable.java
  6. +8 −1 core/src/main/java/org/jruby/RubyIO.java
  7. +1 −1 core/src/main/java/org/jruby/RubyNumeric.java
  8. +8 −0 core/src/main/java/org/jruby/RubyRange.java
  9. +9 −12 core/src/main/java/org/jruby/RubyStruct.java
  10. +1 −1 core/src/main/java/org/jruby/ext/stringio/StringIO.java
  11. +5 −3 core/src/main/java/org/jruby/ir/IRBuilder.java
  12. +9 −0 core/src/main/java/org/jruby/ir/IRClosure.java
  13. +5 −18 core/src/main/java/org/jruby/ir/IREvalScript.java
  14. +4 −0 core/src/main/java/org/jruby/ir/IRScope.java
  15. +2 −0 core/src/main/java/org/jruby/ir/IRScriptBody.java
  16. +4 −3 core/src/main/java/org/jruby/ir/instructions/BuildLambdaInstr.java
  17. +1 −3 core/src/main/java/org/jruby/ir/instructions/OptArgMultipleAsgnInstr.java
  18. +1 −1 core/src/main/java/org/jruby/ir/instructions/ReceiveClosureInstr.java
  19. +22 −5 core/src/main/java/org/jruby/ir/interpreter/Interpreter.java
  20. +0 −5 core/src/main/java/org/jruby/ir/operands/Self.java
  21. +13 −6 core/src/main/java/org/jruby/ir/operands/WrappedIRClosure.java
  22. +8 −8 core/src/main/java/org/jruby/ir/passes/CompilerPass.java
  23. +25 −4 core/src/main/java/org/jruby/ir/transformations/inlining/CFGInliner.java
  24. +10 −8 core/src/main/java/org/jruby/ir/transformations/inlining/InlinerInfo.java
  25. +1 −1 core/src/main/java/org/jruby/runtime/CompiledIRBlockBody.java
  26. +3 −3 core/src/main/java/org/jruby/runtime/Helpers.java
  27. +1 −1 core/src/main/java/org/jruby/runtime/InterpretedIRBlockBody.java
  28. +3 −3 core/src/main/java/org/jruby/runtime/load/LoadService.java
  29. +0 −2 core/src/main/java/org/jruby/util/TypeConverter.java
  30. +1 −1 core/src/main/java/org/jruby/util/cli/Options.java
  31. +0 −153 core/src/main/java/org/jruby/util/log/JavaUtilLoggingLogger.java
  32. +0 −3 core/src/main/java/org/jruby/util/log/LoggerFactory.java
  33. +15 −2 core/src/main/java/org/jruby/util/log/StandardErrorLogger.java
  34. +1 −1 core/src/test/java/org/jruby/javasupport/test/TestBSF.java
  35. +20 −0 core/src/test/java/org/jruby/test/TestRubyArray.java
  36. +0 −4 pom.xml
  37. +5 −0 spec/regression/GH-1296_interval_step_size_for_bignum_spec.rb
  38. +12 −0 spec/regression/JRUBY-5946_IO_select_write_nil.rb
  39. +0 −1 test/mri/excludes/TestEnumerator.rb
  40. +0 −1 test/mri/excludes/TestRange.rb
  41. +7 −0 test/test_io.rb
View
3 bin/jruby.bash
@@ -301,9 +301,6 @@ if [[ $darwin && -z "$JAVA_ENCODING" ]]; then
java_args=("${java_args[@]}" "-Dfile.encoding=UTF-8")
fi
-# prefer IPv4 to IPv6; see https://github.com/jruby/jruby/issues/775
-java_args=("${java_args[@]}" "-Djava.net.preferIPv4Stack=true")
-
# Append the rest of the arguments
ruby_args=("${ruby_args[@]}" "$@")
View
3 bin/jruby.sh
@@ -250,9 +250,6 @@ if [[ -z "$JAVA_ENCODING" ]]; then
java_args="${java_args} -Dfile.encoding=UTF-8"
fi
-# prefer IPv4 to IPv6; see https://github.com/jruby/jruby/issues/775
-java_args=("${java_args[@]}" "-Djava.net.preferIPv4Stack=true")
-
# Append the rest of the arguments
ruby_args="${ruby_args} $@"
View
2 core/src/main/java/org/jruby/Ruby.java
@@ -852,7 +852,7 @@ public IRubyObject runInterpreterBody(Node scriptNode) {
assert scriptNode != null : "scriptNode is not null";
assert scriptNode instanceof RootNode : "scriptNode is not a RootNode";
- return runInterpreter(((RootNode) scriptNode).getBodyNode());
+ return runInterpreter(scriptNode);
}
public Parser getParser() {
View
56 core/src/main/java/org/jruby/RubyArray.java
@@ -1831,30 +1831,26 @@ public IRubyObject op_equal(ThreadContext context, IRubyObject obj) {
}
public RubyBoolean compare(ThreadContext context, MethodNames method, IRubyObject other) {
-
- Ruby runtime = context.runtime;
-
if (!(other instanceof RubyArray)) {
- if (!other.respondsTo("to_ary")) {
- return runtime.getFalse();
- } else {
- return Helpers.rbEqual(context, other, this);
- }
+ if (!other.respondsTo("to_ary")) return context.runtime.getFalse();
+
+ return Helpers.rbEqual(context, other, this);
}
RubyArray ary = (RubyArray) other;
- if (realLength != ary.realLength) {
- return runtime.getFalse();
- }
+ if (realLength != ary.realLength) return context.runtime.getFalse();
for (int i = 0; i < realLength; i++) {
- if (!invokedynamic(context, elt(i), method, ary.elt(i)).isTrue()) {
- return runtime.getFalse();
- }
+ IRubyObject a = elt(i);
+ IRubyObject b = ary.elt(i);
+
+ if (a == b) continue; // matching MRI opt. mock frameworks can throw errors if we don't
+
+ if (!invokedynamic(context, a, method, b).isTrue()) return context.runtime.getFalse();
}
- return runtime.getTrue();
+ return context.runtime.getTrue();
}
/** rb_ary_eql
@@ -3309,7 +3305,7 @@ public IRubyObject drop_while(ThreadContext context, Block block) {
*/
@JRubyMethod(name = "cycle")
public IRubyObject cycle(ThreadContext context, Block block) {
- if (!block.isGiven()) return enumeratorize(context.runtime, this, "cycle");
+ if (!block.isGiven()) return enumeratorizeWithSize(context, this, "cycle", cycleSize(context, null));
return cycleCommon(context, -1, block);
}
@@ -3319,7 +3315,7 @@ public IRubyObject cycle(ThreadContext context, Block block) {
@JRubyMethod(name = "cycle")
public IRubyObject cycle(ThreadContext context, IRubyObject arg, Block block) {
if (arg.isNil()) return cycle(context, block);
- if (!block.isGiven()) return enumeratorize(context.runtime, this, "cycle", arg);
+ if (!block.isGiven()) return enumeratorizeWithSize(context, this, "cycle", new IRubyObject[] { arg }, cycleSize(context, arg));
long times = RubyNumeric.num2long(arg);
if (times <= 0) return context.runtime.getNil();
@@ -3336,6 +3332,30 @@ private IRubyObject cycleCommon(ThreadContext context, long n, Block block) {
return context.runtime.getNil();
}
+ private IRubyObject cycleSize(ThreadContext context, IRubyObject cycleArg) {
+ Ruby runtime = context.runtime;
+ IRubyObject n = runtime.getNil();
+
+ if (realLength == 0) {
+ return RubyFixnum.zero(runtime);
+ }
+
+ if (cycleArg != null) {
+ n = cycleArg;
+ }
+
+ if (n.isNil()) {
+ return RubyFloat.newFloat(runtime, RubyFloat.INFINITY);
+ }
+
+ long multiple = RubyNumeric.num2long(n);
+ if (multiple <= 0) {
+ return RubyFixnum.zero(runtime);
+ }
+
+ return length().callMethod(context, "*", RubyFixnum.newFixnum(runtime, multiple));
+ }
+
/** rb_ary_product
*
@@ -4193,7 +4213,7 @@ public List subList(int fromIndex, int toIndex) {
throw new IndexOutOfBoundsException();
}
- IRubyObject subList = subseq(fromIndex, toIndex - fromIndex + 1);
+ IRubyObject subList = subseq(fromIndex, toIndex - fromIndex);
return subList.isNil() ? null : (List) subList;
}
View
29 core/src/main/java/org/jruby/RubyEnumerable.java
@@ -177,7 +177,7 @@ public IRubyObject yield(ThreadContext context, IRubyObject[] args) {
@JRubyMethod
public static IRubyObject cycle(ThreadContext context, IRubyObject self, final Block block) {
if (!block.isGiven()) {
- return enumeratorize(context.runtime, self, "cycle");
+ return enumeratorizeWithSize(context, self, "cycle", cycleSize(context, self, null));
}
return cycleCommon(context, self, -1, block);
@@ -187,7 +187,7 @@ public static IRubyObject cycle(ThreadContext context, IRubyObject self, final B
public static IRubyObject cycle(ThreadContext context, IRubyObject self, IRubyObject arg, final Block block) {
if (arg.isNil()) return cycle(context, self, block);
if (!block.isGiven()) {
- return enumeratorize(context.runtime, self, "cycle", arg);
+ return enumeratorizeWithSize(context, self, "cycle", new IRubyObject[] { arg }, cycleSize(context, self, arg));
}
long times = RubyNumeric.num2long(arg);
@@ -226,6 +226,31 @@ public IRubyObject yield(ThreadContext context, IRubyObject[] args) {
return runtime.getNil();
}
+ private static IRubyObject cycleSize(ThreadContext context, IRubyObject self, IRubyObject cycleArg) {
+ Ruby runtime = context.runtime;
+ IRubyObject n = runtime.getNil();
+ IRubyObject size = enumSize(context, self);
+
+ if (size == null || size.isNil()) {
+ return runtime.getNil();
+ }
+
+ if (cycleArg != null) {
+ n = cycleArg;
+ }
+
+ if (n.isNil()) {
+ return RubyFloat.newFloat(runtime, RubyFloat.INFINITY);
+ }
+
+ long multiple = RubyNumeric.num2long(n);
+ if (multiple <= 0) {
+ return RubyFixnum.zero(runtime);
+ }
+
+ return size.callMethod(context, "*", RubyFixnum.newFixnum(runtime, multiple));
+ }
+
@JRubyMethod(name = "take")
public static IRubyObject take(ThreadContext context, IRubyObject self, IRubyObject n, Block block) {
final Ruby runtime = context.runtime;
View
9 core/src/main/java/org/jruby/RubyIO.java
@@ -1390,9 +1390,16 @@ protected int fwrite(RubyString buffer) {
buffer = (RubyString)doWriteConversion(getRuntime().getCurrentContext(), buffer);
int len = buffer.size();
-
+
if ((n = len) <= 0) return n;
+ // console() can detect underlying windows codepage so we will just write to it
+ // and hope it is legible.
+ if (Platform.IS_WINDOWS && tty_p(getRuntime().getCurrentContext()).isTrue()) {
+ System.console().printf("%s", buffer.asJavaString());
+ return len;
+ }
+
try {
if (openFile.isSync()) {
openFile.fflush(writeStream);
View
2 core/src/main/java/org/jruby/RubyNumeric.java
@@ -914,7 +914,7 @@ public static RubyNumeric intervalStepSize(ThreadContext context, IRubyObject fr
if (!excludeLast || from.callMethod(context, "+", result.callMethod(context, "*", step)).callMethod(context, cmpString, to).isTrue()) {
result = result.callMethod(context, "+", RubyFixnum.newFixnum(runtime, 1));
}
- return (RubyFixnum) result;
+ return (RubyNumeric) result;
}
}
View
8 core/src/main/java/org/jruby/RubyRange.java
@@ -670,6 +670,14 @@ public IRubyObject last(ThreadContext context, IRubyObject arg) {
return ((RubyArray) RubyKernel.new_array(context, this, this)).last(arg);
}
+ @JRubyMethod
+ public IRubyObject size(ThreadContext context) {
+ if (begin instanceof RubyNumeric && end instanceof RubyNumeric) {
+ return RubyNumeric.intervalStepSize(context, begin, end, RubyFixnum.one(context.runtime), isExclusive);
+ }
+ return context.nil;
+ }
+
private static final ObjectMarshal RANGE_MARSHAL = new ObjectMarshal() {
@Override
public void marshalTo(Ruby runtime, Object obj, RubyClass type,
View
21 core/src/main/java/org/jruby/RubyStruct.java
@@ -32,13 +32,15 @@
***** END LICENSE BLOCK *****/
package org.jruby;
-import static org.jruby.RubyEnumerator.enumeratorize;
-
-
-import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.common.IRubyWarnings.ID;
+import org.jruby.exceptions.RaiseException;
+import org.jruby.internal.runtime.methods.CallConfiguration;
+import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
+import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
@@ -48,15 +50,10 @@
import org.jruby.runtime.marshal.UnmarshalStream;
import org.jruby.util.ByteList;
import org.jruby.util.IdUtil;
-import org.jruby.common.IRubyWarnings.ID;
-import org.jruby.exceptions.RaiseException;
-import org.jruby.internal.runtime.methods.CallConfiguration;
-import org.jruby.internal.runtime.methods.DynamicMethod;
-import org.jruby.runtime.ClassIndex;
-
-import static org.jruby.runtime.Visibility.*;
+import static org.jruby.RubyEnumerator.enumeratorize;
import static org.jruby.runtime.Helpers.invokedynamic;
+import static org.jruby.runtime.Visibility.PRIVATE;
import static org.jruby.runtime.invokedynamic.MethodNames.HASH;
/**
@@ -442,7 +439,7 @@ public RubyArray members() {
public RubyArray members19() {
return members19(classOf(), Block.NULL_BLOCK);
}
-
+
@JRubyMethod
public RubyArray select(ThreadContext context, Block block) {
RubyArray array = RubyArray.newArray(context.runtime);
View
2 core/src/main/java/org/jruby/ext/stringio/StringIO.java
@@ -433,7 +433,7 @@ private static int bm_search(byte[] little, int lstart, int llen, byte[] big, in
j--;
}
if (j < 0) return k + 1;
- i += skip[big[i + bstart]];
+ i += skip[big[i + bstart] & 0xFF];
}
return -1;
}
View
8 core/src/main/java/org/jruby/ir/IRBuilder.java
@@ -449,7 +449,9 @@ public Operand buildLambda(LambdaNode node, IRScope s) {
// catchUncaughtBreakInLambdas(closure);
Variable lambda = s.getNewTemporaryVariable();
- s.addInstr(new BuildLambdaInstr(lambda, closure, node.getPosition()));
+ // SSS FIXME: Is this the right self here?
+ WrappedIRClosure lambdaBody = new WrappedIRClosure(getSelf(s), closure);
+ s.addInstr(new BuildLambdaInstr(lambda, lambdaBody, node.getPosition()));
return lambda;
}
@@ -2485,7 +2487,7 @@ public Operand buildForIter(final ForNode forNode, IRScope s) {
closure.addInstr(new ReturnInstr(closureRetVal));
}
- return new WrappedIRClosure(closure);
+ return new WrappedIRClosure(getSelf(s), closure);
}
public Operand buildGlobalAsgn(GlobalAsgnNode globalAsgnNode, IRScope s) {
@@ -2639,7 +2641,7 @@ public Operand buildIter(final IterNode iterNode, IRScope s) {
closure.addInstr(new ReturnInstr(closureRetVal));
}
- return new WrappedIRClosure(closure);
+ return new WrappedIRClosure(getSelf(s), closure);
}
public Operand buildLiteral(LiteralNode literalNode, IRScope s) {
View
9 core/src/main/java/org/jruby/ir/IRClosure.java
@@ -40,6 +40,7 @@
// for-loop body closures are special in that they dont really define a new variable scope.
// They just silently reuse the parent scope. This changes how variables are allocated (see IRMethod.java).
private boolean isForLoopBody;
+ private boolean isBeginEndBlock;
// Block parameters
private List<Operand> blockArgs;
@@ -105,6 +106,14 @@ protected IRClosure(IRManager manager, IRScope lexicalParent, String fileName, i
this.nestingDepth = n;
}
+ public void setBeginEndBlock() {
+ this.isBeginEndBlock = true;
+ }
+
+ public boolean isBeginEndBlock() {
+ return isBeginEndBlock;
+ }
+
public void setParameterList(String[] parameterList) {
this.parameterList = parameterList;
}
View
23 core/src/main/java/org/jruby/ir/IREvalScript.java
@@ -61,6 +61,7 @@ public String getScopeName() {
@Override
public void recordBeginBlock(IRClosure beginBlockClosure) {
if (beginBlocks == null) beginBlocks = new ArrayList<IRClosure>();
+ beginBlockClosure.setBeginEndBlock();
beginBlocks.add(beginBlockClosure);
}
@@ -68,6 +69,7 @@ public void recordBeginBlock(IRClosure beginBlockClosure) {
@Override
public void recordEndBlock(IRClosure endBlockClosure) {
if (endBlocks == null) endBlocks = new ArrayList<IRClosure>();
+ endBlockClosure.setBeginEndBlock();
endBlocks.add(endBlockClosure);
}
@@ -84,24 +86,9 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
LOG.info("Graph:\n" + cfg().toStringGraph());
LOG.info("CFG:\n" + cfg().toStringInstrs());
}
- try {
- context.pushScope(evalScope);
-
- // Since IR introduces additional local vars, we may need to grow the dynamic scope.
- // To do that, IREvalScript has to tell the dyn-scope how many local vars there are.
- // Since the same static scope (the scope within which the eval string showed up)
- // might be shared by multiple eval-scripts, we cannot 'setIRScope(this)' once and
- // forget about it. We need to set this right before we are ready to grow the
- // dynamic scope local var space.
- ((IRStaticScope)getStaticScope()).setIRScope(this);
- evalScope.growIfNeeded();
-
- // FIXME: Do not push new empty arg array in every time
- return Interpreter.INTERPRET_EVAL(context, self, this, clazz, new IRubyObject[] {}, backtraceName, block, null);
- }
- finally {
- context.popScope();
- }
+
+ // FIXME: Do not push new empty arg array in every time
+ return Interpreter.INTERPRET_EVAL(context, self, this, clazz, new IRubyObject[] {}, backtraceName, block, null);
}
@Override
View
4 core/src/main/java/org/jruby/ir/IRScope.java
@@ -428,6 +428,10 @@ public boolean isForLoopBody() {
return false;
}
+ public boolean isBeginEndBlock() {
+ return false;
+ }
+
public Label getNewLabel(String prefix) {
return new Label(prefix + "_" + allocateNextPrefixedName(prefix));
}
View
2 core/src/main/java/org/jruby/ir/IRScriptBody.java
@@ -47,6 +47,7 @@ public String toString() {
@Override
public void recordBeginBlock(IRClosure beginBlockClosure) {
if (beginBlocks == null) beginBlocks = new ArrayList<IRClosure>();
+ beginBlockClosure.setBeginEndBlock();
beginBlocks.add(beginBlockClosure);
}
@@ -54,6 +55,7 @@ public void recordBeginBlock(IRClosure beginBlockClosure) {
@Override
public void recordEndBlock(IRClosure endBlockClosure) {
if (endBlocks == null) endBlocks = new ArrayList<IRClosure>();
+ endBlockClosure.setBeginEndBlock();
endBlocks.add(endBlockClosure);
}
View
7 core/src/main/java/org/jruby/ir/instructions/BuildLambdaInstr.java
@@ -22,11 +22,11 @@
private Variable result;
private Operand[] operands;
- public BuildLambdaInstr(Variable lambda, IRClosure lambdaBody, ISourcePosition position) {
+ public BuildLambdaInstr(Variable lambda, WrappedIRClosure lambdaBody, ISourcePosition position) {
super(Operation.LAMBDA);
this.result = lambda;
- this.operands = new Operand[] { new WrappedIRClosure(lambdaBody) };
+ this.operands = new Operand[] { lambdaBody };
this.position = position;
}
@@ -46,7 +46,7 @@ public void updateResult(Variable v) {
@Override
public Instr cloneForInlining(InlinerInfo ii) {
// SSS FIXME: This is buggy. The lambda body might have to be cloned depending on cloning context.
- return new BuildLambdaInstr(ii.getRenamedVariable(getResult()), getLambdaBody(), position);
+ return new BuildLambdaInstr(ii.getRenamedVariable(getResult()), (WrappedIRClosure)operands[0], position);
}
@Override
@@ -69,6 +69,7 @@ public Object interpret(ThreadContext context, DynamicScope currDynScope, IRubyO
IRClosure body = getLambdaBody();
// ENEBO: Now can live nil be passed as block reference?
+ // SSS FIXME: Should we do the same %self retrieval as in the case of WrappedIRClosure? Or are lambdas special??
return RubyProc.newProc(context.runtime,
(Block) (body == null ? context.runtime.getIRManager().getNil() : operands[0]).retrieve(context, self, currDynScope, temp),
Block.Type.LAMBDA, position);
View
4 core/src/main/java/org/jruby/ir/instructions/OptArgMultipleAsgnInstr.java
@@ -39,10 +39,8 @@ public Instr cloneForInlining(InlinerInfo ii) {
public Object interpret(ThreadContext context, DynamicScope currDynScope, IRubyObject self, Object[] temp, Block block) {
// ENEBO: Can I assume since IR figured this is an internal array it will be RubyArray like this?
RubyArray rubyArray = (RubyArray) array.retrieve(context, self, currDynScope, temp);
- Object val;
-
int n = rubyArray.getLength();
- return minArgsLength <= n ? rubyArray.entry(index) : UndefinedValue.UNDEFINED;
+ return minArgsLength < n ? rubyArray.entry(index) : UndefinedValue.UNDEFINED;
}
@Override
View
2 core/src/main/java/org/jruby/ir/instructions/ReceiveClosureInstr.java
@@ -34,9 +34,9 @@ public void updateResult(Variable v) {
@Override
public Instr cloneForInlining(InlinerInfo ii) {
switch (ii.getCloneMode()) {
- case METHOD_INLINE:
case NORMAL_CLONE:
return new ReceiveClosureInstr(ii.getRenamedVariable(result));
+ case METHOD_INLINE:
case CLOSURE_INLINE:
// SSS FIXME: This is not strictly correct -- we have to wrap the block into an
// operand type that converts the static code block to a proc which is a closure.
View
27 core/src/main/java/org/jruby/ir/interpreter/Interpreter.java
@@ -147,11 +147,28 @@ public static IRubyObject interpretCommonEval(Ruby runtime, String file, int lin
IRScope containingIRScope = getEvalContainerScope(runtime, ss);
IREvalScript evalScript = IRBuilder.createIRBuilder(runtime, runtime.getIRManager()).buildEvalRoot(ss, containingIRScope, file, lineNumber, rootNode);
evalScript.prepareForInterpretation(false);
-// evalScript.runCompilerPass(new CallSplitter());
ThreadContext context = runtime.getCurrentContext();
- runBeginEndBlocks(evalScript.getBeginBlocks(), context, self, null); // FIXME: No temp vars yet right?
- IRubyObject rv = evalScript.call(context, self, evalScript.getStaticScope().getModule(), rootNode.getScope(), block, backtraceName);
- runBeginEndBlocks(evalScript.getEndBlocks(), context, self, null); // FIXME: No temp vars right?
+
+ IRubyObject rv = null;
+ try {
+ DynamicScope s = rootNode.getScope();
+ context.pushScope(s);
+
+ // Since IR introduces additional local vars, we may need to grow the dynamic scope.
+ // To do that, IREvalScript has to tell the dyn-scope how many local vars there are.
+ // Since the same static scope (the scope within which the eval string showed up)
+ // might be shared by multiple eval-scripts, we cannot 'setIRScope(this)' once and
+ // forget about it. We need to set this right before we are ready to grow the
+ // dynamic scope local var space.
+ ((IRStaticScope)evalScript.getStaticScope()).setIRScope(evalScript);
+ s.growIfNeeded();
+
+ runBeginEndBlocks(evalScript.getBeginBlocks(), context, self, null); // FIXME: No temp vars yet right?
+ rv = evalScript.call(context, self, evalScript.getStaticScope().getModule(), s, block, backtraceName);
+ runBeginEndBlocks(evalScript.getEndBlocks(), context, self, null); // FIXME: No temp vars right?
+ } finally {
+ context.popScope();
+ }
return rv;
}
@@ -169,7 +186,7 @@ public static void runBeginEndBlocks(List<IRClosure> beBlocks, ThreadContext con
for (IRClosure b: beBlocks) {
// SSS FIXME: Should I piggyback on WrappedIRClosure.retrieve or just copy that code here?
b.prepareForInterpretation(false);
- Block blk = (Block)(new WrappedIRClosure(b)).retrieve(context, self, context.getCurrentScope(), temp);
+ Block blk = (Block)(new WrappedIRClosure(b.getSelf(), b)).retrieve(context, self, context.getCurrentScope(), temp);
blk.yield(context, null);
}
}
View
5 core/src/main/java/org/jruby/ir/operands/Self.java
@@ -33,11 +33,6 @@ public Variable clone(InlinerInfo ii) {
}
@Override
- public Operand cloneForInlining(InlinerInfo ii) {
- return ii.getSelfValue(this);
- }
-
- @Override
public void visit(IRVisitor visitor) {
visitor.Self(this);
}
View
19 core/src/main/java/org/jruby/ir/operands/WrappedIRClosure.java
@@ -13,15 +13,17 @@
import java.util.List;
public class WrappedIRClosure extends Operand {
+ private Variable self;
private final IRClosure closure;
- public WrappedIRClosure(IRClosure scope) {
- this.closure = scope;
+ public WrappedIRClosure(Variable self, IRClosure closure) {
+ this.self = self;
+ this.closure = closure;
}
@Override
public void addUsedVariables(List<Variable> l) {
- /* Nothing to o */
+ l.add(self);
}
public IRClosure getClosure() {
@@ -35,19 +37,24 @@ public boolean canCopyPropagate() {
@Override
public String toString() {
- return closure.toString();
+ return self + ":" + closure.toString();
}
@Override
public Operand cloneForInlining(InlinerInfo ii) {
- return new WrappedIRClosure(closure.cloneForInlining(ii));
+ return new WrappedIRClosure(ii.getRenamedVariable(self), closure.cloneForInlining(ii));
}
@Override
public Object retrieve(ThreadContext context, IRubyObject self, DynamicScope currDynScope, Object[] temp) {
BlockBody body = closure.getBlockBody();
closure.getStaticScope().determineModule();
- Binding binding = context.currentBinding(self, currDynScope);
+
+ // In non-inlining scenarios, this.self will always be %self.
+ // However, in inlined scenarios, this.self will be the self in the original scope where the closure
+ // was present before inlining.
+ IRubyObject selfVal = (this.self instanceof Self) ? self : (IRubyObject)this.self.retrieve(context, self, currDynScope, temp);
+ Binding binding = context.currentBinding(selfVal, currDynScope);
return new Block(body, binding);
}
View
16 core/src/main/java/org/jruby/ir/passes/CompilerPass.java
@@ -3,9 +3,9 @@
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+
import org.jruby.ir.IRScope;
+import org.jruby.util.log.LoggerFactory;
/**
* A mechanism for executing code against an IRScope or transforming the
@@ -106,17 +106,17 @@ public static CompilerPass createPassInstance(Class<? extends CompilerPass> pass
try {
return (CompilerPass) passClass.getDeclaredConstructor().newInstance();
} catch (InstantiationException ex) {
- Logger.getLogger(CompilerPass.class.getName()).log(Level.SEVERE, null, ex);
+ LoggerFactory.getLogger(CompilerPass.class.getName()).error(null, ex);
} catch (IllegalAccessException ex) {
- Logger.getLogger(CompilerPass.class.getName()).log(Level.SEVERE, null, ex);
+ LoggerFactory.getLogger(CompilerPass.class.getName()).error(null, ex);
} catch (IllegalArgumentException ex) {
- Logger.getLogger(CompilerPass.class.getName()).log(Level.SEVERE, null, ex);
+ LoggerFactory.getLogger(CompilerPass.class.getName()).error(null, ex);
} catch (InvocationTargetException ex) {
- Logger.getLogger(CompilerPass.class.getName()).log(Level.SEVERE, null, ex);
+ LoggerFactory.getLogger(CompilerPass.class.getName()).error(null, ex);
} catch (NoSuchMethodException ex) {
- Logger.getLogger(CompilerPass.class.getName()).log(Level.SEVERE, null, ex);
+ LoggerFactory.getLogger(CompilerPass.class.getName()).error(null, ex);
} catch (SecurityException ex) {
- Logger.getLogger(CompilerPass.class.getName()).log(Level.SEVERE, null, ex);
+ LoggerFactory.getLogger(CompilerPass.class.getName()).error(null, ex);
}
return null;
View
29 core/src/main/java/org/jruby/ir/transformations/inlining/CFGInliner.java
@@ -13,11 +13,12 @@
import org.jruby.ir.instructions.CallBase;
import org.jruby.ir.instructions.JumpInstr;
import org.jruby.ir.instructions.ModuleVersionGuardInstr;
-import org.jruby.ir.instructions.ToAryInstr;
+import org.jruby.ir.instructions.CopyInstr;
import org.jruby.ir.instructions.YieldInstr;
import org.jruby.ir.operands.Array;
import org.jruby.ir.operands.Label;
import org.jruby.ir.operands.Operand;
+import org.jruby.ir.operands.Splat;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.operands.WrappedIRClosure;
import org.jruby.ir.representations.BasicBlock;
@@ -122,7 +123,15 @@ public void inlineMethod(IRScope scope, RubyModule implClass, int classToken, Ba
}
// Host method data init
- InlinerInfo ii = new InlinerInfo(call, cfg);
+ Operand callReceiver = call.getReceiver();
+ Variable callReceiverVar;
+ if (callReceiver instanceof Variable) {
+ callReceiverVar = (Variable)callReceiver;
+ } else {
+ callReceiverVar = hostScope.getNewTemporaryVariable();
+ }
+
+ InlinerInfo ii = new InlinerInfo(call, cfg, callReceiverVar);
// Inlinee method data init
CFG methodCFG = scope.getCFG();
@@ -169,9 +178,21 @@ public void inlineMethod(IRScope scope, RubyModule implClass, int classToken, Ba
BasicBlock destination = e.getDestination().getData();
if (destination != mExit) {
BasicBlock dstBB = ii.getRenamedBB(destination);
+ if (callReceiver != callReceiverVar) {
+ dstBB.insertInstr(new CopyInstr(callReceiverVar, callReceiver));
+ }
if (!ii.canMapArgsStatically()) {
- // FIXME: Does call args need renaming via hostCloneInfo??
- dstBB.addInstr(new ToAryInstr((Variable)ii.getArgs(), new Array(call.getCallArgs()), cfg.getScope().getManager().getTrue()));
+ // SSS FIXME: This is buggy!
+ // This code has to mimic whatever CallBase.prepareArguments does!
+ // We may need a special instruction that takes care of this.
+ Operand args;
+ Operand[] callArgs = call.cloneCallArgs(hostCloneInfo);
+ if (callArgs.length == 1 && callArgs[0] instanceof Splat) {
+ args = callArgs[0];
+ } else {
+ args = new Array(callArgs);
+ }
+ dstBB.insertInstr(new CopyInstr((Variable)ii.getArgs(), args));
}
cfg.addEdge(callBB, dstBB, CFG.EdgeType.FALL_THROUGH);
}
View
18 core/src/main/java/org/jruby/ir/transformations/inlining/InlinerInfo.java
@@ -37,7 +37,7 @@
private Map<Variable, Variable> varRenameMap;
private Map<BasicBlock, BasicBlock> bbRenameMap;
private List yieldSites;
- private Operand callReceiver;
+ private Variable callReceiver;
private String inlineVarPrefix;
private CloneMode cloneMode;
@@ -76,12 +76,12 @@ public InlinerInfo(CFG c) {
this.argsArray = null;
}
- public InlinerInfo(CallBase call, CFG c) {
+ public InlinerInfo(CallBase call, CFG c, Variable callReceiver) {
init(c);
this.cloneMode = CloneMode.METHOD_INLINE;
this.call = call;
this.callArgs = call.getCallArgs();
- this.callReceiver = call.getReceiver();
+ this.callReceiver = callReceiver;
this.canMapArgsStatically = !containsSplat(callArgs);
this.argsArray = this.canMapArgsStatically ? null : getInlineHostScope().getNewTemporaryVariable();
synchronized(globalInlineCount) {
@@ -147,7 +147,6 @@ public void setupYieldArgsAndYieldResult(YieldInstr yi, BasicBlock yieldBB, Arit
// SSS FIXME: The code below is not entirely correct. We have to process 'yi.getYieldArg()' similar
// to how InterpretedIRBlockBody (1.8 and 1.9 modes) processes it. We may need a special instruction
// that takes care of aligning the stars and bringing good fortune to arg yielder and arg receiver.
-
IRScope callerScope = getInlineHostScope();
boolean needSpecialProcessing = (blockArityValue != -1) && (blockArityValue != 1);
Variable yieldArgArray = callerScope.getNewTemporaryVariable();
@@ -159,6 +158,12 @@ public void setupYieldArgsAndYieldResult(YieldInstr yi, BasicBlock yieldBB, Arit
}
public Variable getRenamedVariable(Variable v) {
+ // Special case for %self
+ if (v instanceof Self) {
+ return cloneMode == CloneMode.NORMAL_CLONE ? v : callReceiver;
+ }
+
+ // Everything else
Variable newVar = this.varRenameMap.get(v);
if (newVar == null) {
switch (cloneMode) {
@@ -188,6 +193,7 @@ public Variable getRenamedVariable(Variable v) {
LocalVariable l_newVar = (LocalVariable)newVar;
if (l_v.getScopeDepth() != l_newVar.getScopeDepth()) newVar = l_newVar.cloneForDepth(l_v.getScopeDepth());
}
+
return newVar;
}
@@ -241,10 +247,6 @@ public Operand getArg(int argIndex, boolean restOfArgArray) {
}
}
- public Operand getSelfValue(Self self) {
- return cloneMode == CloneMode.NORMAL_CLONE ? self : callReceiver;
- }
-
public Operand getCallClosure() {
return call.getClosureArg(hostCFG.getScope().getManager().getNil());
}
View
2 core/src/main/java/org/jruby/runtime/CompiledIRBlockBody.java
@@ -212,7 +212,7 @@ protected IRubyObject commonYieldPath(ThreadContext context, IRubyObject[] args,
if (klass == null) self = prepareSelf(binding);
try {
DynamicScope prevScope = binding.getDynamicScope();
- DynamicScope newScope = closure.isForLoopBody() ? prevScope : DynamicScope.newDynamicScope(getStaticScope(), prevScope);
+ DynamicScope newScope = closure.isForLoopBody() || closure.isBeginEndBlock() ? prevScope : DynamicScope.newDynamicScope(getStaticScope(), prevScope);
context.pushScope(newScope);
// FIXME: Need a compiler equivalent of this -- what do we call here?
// return Interpreter.INTERPRET_BLOCK(context, self, closure, args, binding.getMethod(), block, type);
View
6 core/src/main/java/org/jruby/runtime/Helpers.java
@@ -1966,15 +1966,15 @@ public static IRubyObject unsplatValue19IfArityOne(IRubyObject argsResult, Block
public static IRubyObject[] argsCatToArguments(IRubyObject[] args, IRubyObject cat) {
IRubyObject[] ary = splatToArguments(cat);
- return argsCatToArgumentsCommon(args, ary, cat);
+ return argsCatToArgumentsCommon(args, ary);
}
public static IRubyObject[] argsCatToArguments19(IRubyObject[] args, IRubyObject cat) {
IRubyObject[] ary = splatToArguments19(cat);
- return argsCatToArgumentsCommon(args, ary, cat);
+ return argsCatToArgumentsCommon(args, ary);
}
- private static IRubyObject[] argsCatToArgumentsCommon(IRubyObject[] args, IRubyObject[] ary, IRubyObject cat) {
+ private static IRubyObject[] argsCatToArgumentsCommon(IRubyObject[] args, IRubyObject[] ary) {
if (ary.length > 0) {
IRubyObject[] newArgs = new IRubyObject[args.length + ary.length];
System.arraycopy(args, 0, newArgs, 0, args.length);
View
2 core/src/main/java/org/jruby/runtime/InterpretedIRBlockBody.java
@@ -187,7 +187,7 @@ protected IRubyObject commonYieldPath(ThreadContext context, IRubyObject[] args,
if (klass == null) self = prepareSelf(binding);
try {
DynamicScope prevScope = binding.getDynamicScope();
- DynamicScope newScope = closure.isForLoopBody() ? prevScope : DynamicScope.newDynamicScope(getStaticScope(), prevScope);
+ DynamicScope newScope = closure.isForLoopBody() || closure.isBeginEndBlock() ? prevScope : DynamicScope.newDynamicScope(getStaticScope(), prevScope);
context.pushScope(newScope);
return Interpreter.INTERPRET_BLOCK(context, self, closure, args, binding.getMethod(), block, type);
}
View
6 core/src/main/java/org/jruby/runtime/load/LoadService.java
@@ -986,13 +986,13 @@ protected void checkEmptyLoad(String file) throws RaiseException {
protected void debugLogTry(String what, String msg) {
if (RubyInstanceConfig.DEBUG_LOAD_SERVICE) {
- LOG.info( "LoadService: trying " + what + ": " + msg );
+ LOG.info( "trying " + what + ": " + msg );
}
}
protected void debugLogFound(String what, String msg) {
if (RubyInstanceConfig.DEBUG_LOAD_SERVICE) {
- LOG.info( "LoadService: found " + what + ": " + msg );
+ LOG.info( "found " + what + ": " + msg );
}
}
@@ -1004,7 +1004,7 @@ protected void debugLogFound( LoadServiceResource resource ) {
} catch (IOException e) {
resourceUrl = e.getMessage();
}
- LOG.info( "LoadService: found: " + resourceUrl );
+ LOG.info( "found: " + resourceUrl );
}
}
View
2 core/src/main/java/org/jruby/util/TypeConverter.java
@@ -28,8 +28,6 @@
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import org.jruby.Ruby;
import org.jruby.RubyBoolean;
import org.jruby.RubyClass;
View
2 core/src/main/java/org/jruby/util/cli/Options.java
@@ -155,7 +155,7 @@
public static final Option<Boolean> LOG_BACKTRACES = bool(DEBUG, "log.backtraces", false, "Log every time an exception backtrace is generated.");
public static final Option<Boolean> LOG_CALLERS = bool(DEBUG, "log.callers", false, "Log every time a Kernel#caller backtrace is generated.");
public static final Option<Boolean> LOG_WARNINGS = bool(DEBUG, "log.warnings", false, "Log every time a built-in warning backtrace is generated.");
- public static final Option<String> LOGGER_CLASS = string(DEBUG, "logger.class", new String[] {"class name"}, "org.jruby.util.log.JavaUtilLoggingLogger", "Use specified class for logging.");
+ public static final Option<String> LOGGER_CLASS = string(DEBUG, "logger.class", new String[] {"class name"}, "org.jruby.util.log.StandardErrorLogger", "Use specified class for logging.");
public static final Option<Boolean> DUMP_INSTANCE_VARS = bool(DEBUG, "dump.variables", false, "Dump class + instance var names on first new of Object subclasses.");
public static final Option<Boolean> JI_SETACCESSIBLE = bool(JAVA_INTEGRATION, "ji.setAccessible", true, "Try to set inaccessible Java methods to be accessible.");
View
153 core/src/main/java/org/jruby/util/log/JavaUtilLoggingLogger.java
@@ -1,153 +0,0 @@
-/***** BEGIN LICENSE BLOCK *****
- * Version: EPL 1.0/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Eclipse Public
- * License Version 1.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.eclipse.org/legal/epl-v10.html
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * Copyright (C) 2001-2011 The JRuby Community (and contribs)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the EPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the EPL, the GPL or the LGPL.
- ***** END LICENSE BLOCK *****/
-package org.jruby.util.log;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.Arrays;
-import java.util.logging.ConsoleHandler;
-import java.util.logging.Formatter;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-import org.joda.time.DateTime;
-
-public class JavaUtilLoggingLogger implements Logger {
- private final java.util.logging.Logger logger;
-
- public JavaUtilLoggingLogger(String loggerName) {
- logger = java.util.logging.Logger.getLogger(loggerName);
- logger.setUseParentHandlers(false);
- ConsoleHandler handler = new ConsoleHandler();
- handler.setFormatter(new Formatter() {
- @Override
- public String format(LogRecord lr) {
- StringBuilder sb = new StringBuilder();
- sb
- .append(new DateTime(lr.getMillis()).toString())
- .append(": ")
- .append(lr.getLoggerName())
- .append(": ")
- .append(lr.getMessage())
- .append("\n");
- return sb.toString();
- }
- });
- logger.addHandler(handler);
- }
-
- public String getName() {
- return logger.getName();
- }
-
- public void warn(String message, Object... args) {
- if (logger.isLoggable(Level.WARNING)) {
- logger.warning(message + (args.length == 0 ? "" : "\n" + Arrays.toString(args)));
- }
- }
-
- public void warn(Throwable throwable) {
- if (logger.isLoggable(Level.WARNING)) {
- logger.warning(getLoggingOutput(throwable));
- }
- }
-
- public void warn(String message, Throwable throwable) {
- if (logger.isLoggable(Level.WARNING)) {
- logger.warning(message + "\n" + getLoggingOutput(throwable));
- }
- }
-
- public void error(String message, Object... args) {
- if (logger.isLoggable(Level.SEVERE)) {
- logger.severe(message + (args.length == 0 ? "" : "\n" + Arrays.toString(args)));
- }
- }
-
- public void error(Throwable throwable) {
- if (logger.isLoggable(Level.SEVERE)) {
- logger.severe(getLoggingOutput(throwable));
- }
- }
-
- public void error(String message, Throwable throwable) {
- if (logger.isLoggable(Level.SEVERE)) {
- logger.severe(message + "\n" + getLoggingOutput(throwable));
- }
- }
-
- public void info(String message, Object... args) {
- if (logger.isLoggable(Level.INFO)) {
- logger.info(message + (args.length == 0 ? "" : "\n" + Arrays.toString(args)));
- }
- }
-
- public void info(Throwable throwable) {
- if (logger.isLoggable(Level.INFO)) {
- logger.info(getLoggingOutput(throwable));
- }
- }
-
- public void info(String message, Throwable throwable) {
- if (logger.isLoggable(Level.INFO)) {
- logger.info(message + "\n" + getLoggingOutput(throwable));
- }
- }
-
- public void debug(String message, Object... args) {
- if (isDebugEnabled()) {
- logger.finest(message + (args.length == 0 ? "" : "\n" + Arrays.toString(args)));
- }
- }
-
- public void debug(Throwable throwable) {
- if (isDebugEnabled()) {
- logger.finest(getLoggingOutput(throwable));
- }
- }
-
- public void debug(String message, Throwable throwable) {
- if (isDebugEnabled()) {
- logger.finest(message + "\n" + getLoggingOutput(throwable));
- }
- }
-
- public boolean isDebugEnabled() {
- return logger.isLoggable(Level.FINEST);
- }
-
- public void setDebugEnable(boolean debug) {
- logger.setLevel(Level.FINEST);
- }
-
- private String getLoggingOutput(Throwable throwable) {
- StringWriter sw = new StringWriter();
- throwable.printStackTrace(new PrintWriter(sw));
- return sw.toString();
- }
-
-}
View
3 core/src/main/java/org/jruby/util/log/LoggerFactory.java
@@ -36,8 +36,6 @@
private static final String BACKUP_LOGGER_CLASS = "org.jruby.util.log.StandardErrorLogger";
private static final Constructor<?> CTOR;
- private static final Logger LOG;
-
static {
Constructor<?> ctor;
Logger log;
@@ -58,7 +56,6 @@
}
}
CTOR = ctor;
- LOG = log;
}
public static Logger getLogger(String loggerName) {
View
17 core/src/main/java/org/jruby/util/log/StandardErrorLogger.java
@@ -29,6 +29,8 @@
import java.io.PrintStream;
+import org.joda.time.DateTime;
+
public class StandardErrorLogger implements Logger {
private final String loggerName;
@@ -112,16 +114,27 @@ public void setDebugEnable(boolean debug) {
}
private void write(String message, Object[] args) {
- writer.write(message, args);
+ writer.write(format(message), args);
}
private void write(String message, Throwable throwable) {
- writer.write(message);
+ writer.write(format(message));
writeStackTrace(throwable);
}
private void writeStackTrace(Throwable throwable) {
throwable.printStackTrace(writer.getStream());
}
+
+ private String format(String message){
+ StringBuilder sb = new StringBuilder();
+ sb
+ .append(new DateTime(System.currentTimeMillis()).toString())
+ .append(": ")
+ .append(loggerName)
+ .append(": ")
+ .append(message);
+ return sb.toString();
+ }
}
View
2 core/src/test/java/org/jruby/javasupport/test/TestBSF.java
@@ -105,7 +105,7 @@ public void testModifyList() throws Exception{
assertEquals(3, ((Number) array[2]).longValue());
List subList = list.subList(0, 2);
- assertEquals(3, subList.size());
+ assertEquals(2, subList.size());
//subList.clear();
// Sublist is supposed to share same backing store as list...TODO in RubyArray.
View
20 core/src/test/java/org/jruby/test/TestRubyArray.java
@@ -27,6 +27,9 @@
***** END LICENSE BLOCK *****/
package org.jruby.test;
+import java.util.Arrays;
+import java.util.List;
+
import org.jruby.Ruby;
import org.jruby.RubyArray;
@@ -168,4 +171,21 @@ public void testSetsLeftoverValuesToNullInDelete() throws Exception {
assertNotSame("first element nil", runtime.getNil(), arr.eltInternal(0));
assertSame("second element not nil", runtime.getNil(), arr.eltInternal(1));
}
+
+ private void assertSublistContainsCorrectSubset(final List<?> list) {
+ final List<?> subList = list.subList(1, 3);
+ assertEquals(2, subList.size());
+ assertEquals("bar", subList.get(0));
+ assertEquals("baz", subList.get(1));
+ }
+
+ public void testSubListContainsCorrectSubset() {
+ // Demonstrates that this is a fair test
+ final List<?> javaArray = Arrays.asList("foo", "bar", "baz", "anything");
+ assertSublistContainsCorrectSubset(javaArray);
+
+ // Ruby should give the same results
+ final RubyArray rubyArray = (RubyArray)runtime.evalScriptlet("$h = ['foo', 'bar', 'baz', 'anything']");
+ assertSublistContainsCorrectSubset(rubyArray);
+ }
}
View
4 pom.xml
@@ -27,10 +27,6 @@
<enabled>true</enabled>
</snapshots>
</repository>
- <repository>
- <id>rubygems-releases</id>
- <url>http://rubygems-proxy.torquebox.org/releases</url>
- </repository>
</repositories>
<modules>
View
5 spec/regression/GH-1296_interval_step_size_for_bignum_spec.rb
@@ -0,0 +1,5 @@
+describe "Numeric#step.size" do
+ it "does not result in a ClassCastException when passed a bignum" do
+ 5.step(2**64).size.should == 18446744073709551612
+ end
+end
View
12 spec/regression/JRUBY-5946_IO_select_write_nil.rb
@@ -0,0 +1,12 @@
+require 'rspec'
+
+describe "JRUBY-5946 IO.select returns write array with nil elements" do
+ it "returns writes elements correctly even when there aren't reads nor errors elements" do
+ @rd, @wr = IO.pipe
+ rd_arr, wr_arr, err_arr = IO.select([@rd,@wr],[@wr],[],0)
+ rd_arr.size.should == 0
+ wr_arr.size.should == 1
+ wr_arr.should == [@wr]
+ err_arr.size.should == 0
+ end
+end
View
1 test/mri/excludes/TestEnumerator.rb
@@ -16,7 +16,6 @@
exclude :test_peek_values_modify, "needs investigation"
exclude :test_rewind_clear_feed, "needs investigation"
exclude :test_size_for_array_combinatorics, "needs investigation"
-exclude :test_size_for_cycle, "needs investigation"
exclude :test_size_for_downup_to, "needs investigation"
exclude :test_size_for_each_cons, "needs investigation"
exclude :test_size_for_each_slice, "needs investigation"
View
1 test/mri/excludes/TestRange.rb
@@ -9,6 +9,5 @@
exclude :test_max, "needs investigation"
exclude :test_range_bsearch_for_floats, "needs investigation"
exclude :test_range_numeric_string, "needs investigation"
-exclude :test_size, "needs investigation"
exclude :test_step, "needs investigation"
exclude :test_step_ruby_core_35753, "needs investigation"
View
7 test/test_io.rb
@@ -540,4 +540,11 @@ def test_rubyio_fileno_mapping_leak
closed_io_count = JRuby.runtime.fileno_int_map_size
assert_equal(starting_count, closed_io_count)
end
+
+ # JRUBY-1222
+ def test_stringio_gets_utf8
+ @stringio = StringIO.new("®\r\n®\r\n")
+ assert_equal "®\r\n", @stringio.gets("\r\n")
+ assert_equal "®\r\n", @stringio.gets("\r\n")
+ end
end
Something went wrong with that request. Please try again.