Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Truffle] Fix null FrameSlot when kwarg is not used #2535

Merged
merged 1 commit into from
Jan 28, 2015

Conversation

jgraichen
Copy link
Contributor

When calling a method having a keyword argument that is not used in the method body the frame descriptor cannot find a frame slot and returns null.

Example:

def method(a: 1)
end

method(a: 2)

With assertions enabled it returns the following:

> JAVA_OPTS="-ea" ./bin/jruby -X+T -e "def method(a: 1); end; method(a: 2)"
Truffle internal error: java.lang.AssertionError
java.lang.AssertionError
        at org.jruby.truffle.nodes.methods.locals.FrameSlotNode.<init>(FrameSlotNode.java:27)
        at org.jruby.truffle.nodes.methods.locals.WriteLocalVariableNode.<init>(WriteLocalVariableNode.java:25)
        at org.jruby.truffle.nodes.methods.locals.WriteLocalVariableNodeFactory$WriteLocalVariableBaseNode.<init>(WriteLocalVariableNodeFactory.java:81)
        at org.jruby.truffle.nodes.methods.locals.WriteLocalVariableNodeFactory$WriteLocalVariableUninitializedNode.<init>(WriteLocalVariableNodeFactory.java:180)
        at org.jruby.truffle.nodes.methods.locals.WriteLocalVariableNodeFactory$WriteLocalVariableUninitializedNode.create0(WriteLocalVariableNodeFactory.java:233)
        at org.jruby.truffle.nodes.methods.locals.WriteLocalVariableNodeFactory.create(WriteLocalVariableNodeFactory.java:64)
        at org.jruby.truffle.translator.LoadArgumentsTranslator.visitKeywordArgNode(LoadArgumentsTranslator.java:198)
        at org.jruby.truffle.translator.LoadArgumentsTranslator.visitKeywordArgNode(LoadArgumentsTranslator.java:36)
        at org.jruby.ast.KeywordArgNode.accept(KeywordArgNode.java:25)
        at org.jruby.truffle.translator.LoadArgumentsTranslator.visitArgsNode(LoadArgumentsTranslator.java:131)
        at org.jruby.truffle.translator.LoadArgumentsTranslator.visitArgsNode(LoadArgumentsTranslator.java:36)
        at org.jruby.ast.ArgsNode.accept(ArgsNode.java:168)
        at org.jruby.truffle.translator.MethodTranslator.compileFunctionNode(MethodTranslator.java:91)
        at org.jruby.truffle.translator.BodyTranslator.translateMethodDefinition(BodyTranslator.java:1036)
        at org.jruby.truffle.translator.BodyTranslator.visitDefnNode(BodyTranslator.java:1011)
        at org.jruby.truffle.translator.BodyTranslator.visitDefnNode(BodyTranslator.java:68)
        at org.jruby.ast.DefnNode.accept(DefnNode.java:56)
        at org.jruby.truffle.translator.BodyTranslator.visitNewlineNode(BodyTranslator.java:1961)
        at org.jruby.truffle.translator.BodyTranslator.visitNewlineNode(BodyTranslator.java:68)
        at org.jruby.ast.NewlineNode.accept(NewlineNode.java:71)
        at org.jruby.truffle.translator.BodyTranslator.visitBlockNode(BodyTranslator.java:309)
        at org.jruby.truffle.translator.BodyTranslator.visitBlockNode(BodyTranslator.java:68)
        at org.jruby.ast.BlockNode.accept(BlockNode.java:58)
        at org.jruby.truffle.translator.TranslatorDriver.parse(TranslatorDriver.java:154)
        at org.jruby.truffle.translator.TranslatorDriver.parse(TranslatorDriver.java:116)
        at org.jruby.truffle.runtime.RubyContext.execute(RubyContext.java:216)
        at org.jruby.truffle.runtime.RubyContext.load(RubyContext.java:183)
        at org.jruby.truffle.TruffleBridgeImpl.execute(TruffleBridgeImpl.java:176)
        at org.jruby.truffle.TruffleBridgeImpl.execute(TruffleBridgeImpl.java:155)
        at org.jruby.Ruby.runInterpreter(Ruby.java:856)
        at org.jruby.Ruby.runInterpreter(Ruby.java:870)
        at org.jruby.Ruby.runNormally(Ruby.java:766)
        at org.jruby.Ruby.runFromMain(Ruby.java:569)
        at org.jruby.Main.doRunFromMain(Main.java:404)
        at org.jruby.Main.internalRun(Main.java:299)
        at org.jruby.Main.run(Main.java:226)
        at org.jruby.Main.main(Main.java:198)

Without assertions it will end in a NullPointerException when trying to write the keyword argument to the frame as a local variable.

This patch simply changes findFrameSlot to findOrAddFrameSlot when transforming the AST to Truffle nodes. I did not (yet) found out why there is no slot.

I am not sure if there is no better solution. If you can point me somewhere else that would be great. Also what would be the best place to add a test for that if wanted?

When a keyword argument is not used in the method body there is no frame
slot for the argument resulting a NullPointerException when writing the
argument to the frame.

This fix changes the AST translator to create the frame slot if it
cannot be found by using `findOrAddFrameSlot` instead of
`findFrameSlot`.
@jgraichen
Copy link
Contributor Author

Without assertions:

> JAVA_OPTS="-Djruby.truffle.exceptions.print_java=true" ./bin/jruby -X+T -e "def method(a: 1); end; method(a: 2)"
java.lang.NullPointerException
        at org.jruby.truffle.nodes.methods.locals.FrameSlotNode.isKind(FrameSlotNode.java:109)
        at org.jruby.truffle.nodes.methods.locals.FrameSlotNode.isFixnumKind(FrameSlotNode.java:89)
        at org.jruby.truffle.nodes.methods.locals.WriteLocalVariableNodeFactory$WriteLocalVariableBaseNode.specialize0(WriteLocalVariableNodeFactory.java:112)
        at org.jruby.truffle.nodes.methods.locals.WriteLocalVariableNodeFactory$WriteLocalVariableUninitializedNode.executeUninitialized0(WriteLocalVariableNodeFactory.java:218)
        at org.jruby.truffle.nodes.methods.locals.WriteLocalVariableNodeFactory$WriteLocalVariableUninitializedNode.execute(WriteLocalVariableNodeFactory.java:206)
        at org.jruby.truffle.nodes.RubyNode.executeVoid(RubyNode.java:200)
        at org.jruby.truffle.nodes.control.SequenceNode.execute(SequenceNode.java:80)
        at org.jruby.truffle.nodes.methods.CatchBreakAsReturnNode.execute(CatchBreakAsReturnNode.java:36)
        at org.jruby.truffle.nodes.methods.CatchReturnNode.execute(CatchReturnNode.java:39)
        at org.jruby.truffle.nodes.methods.CatchNextNode.execute(CatchNextNode.java:36)
        at org.jruby.truffle.nodes.methods.CatchRetryAsErrorNode.execute(CatchRetryAsErrorNode.java:32)
        at org.jruby.truffle.nodes.methods.ExceptionTranslatingNode.execute(ExceptionTranslatingNode.java:52)
        at org.jruby.truffle.nodes.RubyRootNode.execute(RubyRootNode.java:54)
        at com.oracle.truffle.api.impl.DefaultCallTarget.call(DefaultCallTarget.java:77)
        at com.oracle.truffle.api.impl.DefaultDirectCallNode.call(DefaultDirectCallNode.java:65)
        at org.jruby.truffle.nodes.dispatch.CachedBoxedDispatchNode.executeDispatch(CachedBoxedDispatchNode.java:138)
        at org.jruby.truffle.nodes.dispatch.UnresolvedDispatchNode.doRubyBasicObject(UnresolvedDispatchNode.java:184)
        at org.jruby.truffle.nodes.dispatch.UnresolvedDispatchNode.executeDispatch(UnresolvedDispatchNode.java:67)
        at org.jruby.truffle.nodes.dispatch.DispatchHeadNode.dispatch(DispatchHeadNode.java:53)
        at org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode.call(CallDispatchHeadNode.java:35)
        at org.jruby.truffle.nodes.RubyCallNode.execute(RubyCallNode.java:94)
        at org.jruby.truffle.nodes.control.TraceNode.execute(TraceNode.java:52)
        at org.jruby.truffle.nodes.control.SequenceNode.execute(SequenceNode.java:83)
        at org.jruby.truffle.nodes.methods.CatchNextNode.execute(CatchNextNode.java:36)
        at org.jruby.truffle.nodes.methods.CatchReturnAsErrorNode.execute(CatchReturnAsErrorNode.java:37)
        at org.jruby.truffle.nodes.methods.CatchRetryAsErrorNode.execute(CatchRetryAsErrorNode.java:32)
        at org.jruby.truffle.nodes.methods.SetMethodDeclarationContext.execute(SetMethodDeclarationContext.java:44)
        at org.jruby.truffle.nodes.TopLevelRaiseHandler.execute(TopLevelRaiseHandler.java:32)
        at org.jruby.truffle.nodes.control.SequenceNode.execute(SequenceNode.java:83)
        at org.jruby.truffle.nodes.RubyRootNode.execute(RubyRootNode.java:54)
        at com.oracle.truffle.api.impl.DefaultCallTarget.call(DefaultCallTarget.java:77)
        at org.jruby.truffle.runtime.RubyContext.execute(RubyContext.java:220)
        at org.jruby.truffle.runtime.RubyContext.load(RubyContext.java:183)
        at org.jruby.truffle.TruffleBridgeImpl.execute(TruffleBridgeImpl.java:176)
        at org.jruby.truffle.TruffleBridgeImpl.execute(TruffleBridgeImpl.java:155)
        at org.jruby.Ruby.runInterpreter(Ruby.java:856)
        at org.jruby.Ruby.runInterpreter(Ruby.java:870)
        at org.jruby.Ruby.runNormally(Ruby.java:766)
        at org.jruby.Ruby.runFromMain(Ruby.java:569)
        at org.jruby.Main.doRunFromMain(Main.java:404)
        at org.jruby.Main.internalRun(Main.java:299)
        at org.jruby.Main.run(Main.java:226)
        at org.jruby.Main.main(Main.java:198)
-e:1:in `<main>': internal implementation error - NullPointerException null (RubyTruffleError)
        from -e:1:in `<main>'

chrisseaton added a commit that referenced this pull request Jan 28, 2015
[Truffle] Fix null FrameSlot when kwarg is not used
@chrisseaton chrisseaton merged commit 47f9a70 into jruby:master Jan 28, 2015
@chrisseaton
Copy link
Contributor

Thanks very much!

@chrisseaton chrisseaton modified the milestone: truffle-dev May 4, 2015
@enebo enebo added this to the Non-Release milestone Dec 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants