|
9 | 9 | */
|
10 | 10 | package org.truffleruby.core.format.convert;
|
11 | 11 |
|
| 12 | +import com.oracle.truffle.api.dsl.Cached; |
| 13 | +import com.oracle.truffle.api.profiles.BranchProfile; |
12 | 14 | import org.truffleruby.core.format.FormatNode;
|
13 | 15 | import org.truffleruby.core.format.exceptions.CantConvertException;
|
14 | 16 | import org.truffleruby.core.format.exceptions.NoImplicitConversionException;
|
|
17 | 19 | import org.truffleruby.language.Nil;
|
18 | 20 | import org.truffleruby.language.dispatch.DispatchNode;
|
19 | 21 |
|
20 |
| -import com.oracle.truffle.api.CompilerDirectives; |
21 | 22 | import com.oracle.truffle.api.dsl.NodeChild;
|
22 | 23 | import com.oracle.truffle.api.dsl.Specialization;
|
23 | 24 | import com.oracle.truffle.api.frame.VirtualFrame;
|
24 | 25 |
|
25 |
| -import static org.truffleruby.language.dispatch.DispatchConfiguration.PRIVATE_RETURN_MISSING; |
26 |
| - |
27 | 26 | @NodeChild("value")
|
28 | 27 | public abstract class ToLongNode extends FormatNode {
|
29 | 28 |
|
30 |
| - private final boolean errorIfNeedsConversion; |
| 29 | + protected final boolean errorIfNeedsConversion; |
31 | 30 |
|
32 |
| - @Child private DispatchNode toIntNode; |
33 |
| - @Child private ToLongNode redoNode; |
| 31 | + public static ToLongNode create(boolean errorIfNeedsConversion) { |
| 32 | + return ToLongNodeGen.create(errorIfNeedsConversion, null); |
| 33 | + } |
34 | 34 |
|
35 | 35 | public ToLongNode(boolean errorIfNeedsConversion) {
|
36 | 36 | this.errorIfNeedsConversion = errorIfNeedsConversion;
|
@@ -65,25 +65,23 @@ protected long toLongNil(Nil nil) {
|
65 | 65 | }
|
66 | 66 |
|
67 | 67 | @Specialization(
|
68 |
| - guards = { "!isBoolean(object)", "!isRubyInteger(object)", "!isNil(object)" }) |
| 68 | + guards = { "errorIfNeedsConversion", "!isBoolean(object)", "!isRubyInteger(object)", "!isNil(object)" }) |
69 | 69 | protected long toLong(VirtualFrame frame, Object object) {
|
70 |
| - if (errorIfNeedsConversion) { |
71 |
| - throw new CantConvertException("can't convert Object to Integer"); |
72 |
| - } |
73 |
| - |
74 |
| - if (toIntNode == null) { |
75 |
| - CompilerDirectives.transferToInterpreterAndInvalidate(); |
76 |
| - toIntNode = insert(DispatchNode.create(PRIVATE_RETURN_MISSING)); |
77 |
| - } |
78 |
| - |
79 |
| - final Object value = toIntNode.call(object, "to_int"); |
| 70 | + throw new CantConvertException("can't convert Object to Integer"); |
| 71 | + } |
80 | 72 |
|
81 |
| - if (redoNode == null) { |
82 |
| - CompilerDirectives.transferToInterpreterAndInvalidate(); |
83 |
| - redoNode = insert(ToLongNodeGen.create(true, null)); |
| 73 | + @Specialization( |
| 74 | + guards = { "!errorIfNeedsConversion", "!isBoolean(object)", "!isRubyInteger(object)", "!isNil(object)" }) |
| 75 | + protected long toLong(VirtualFrame frame, Object object, |
| 76 | + @Cached(parameters = "PRIVATE_RETURN_MISSING") DispatchNode toIntNode, |
| 77 | + @Cached("create(true)") ToLongNode redoNode, |
| 78 | + @Cached BranchProfile noConversionAvailable) { |
| 79 | + |
| 80 | + Object result = toIntNode.call(object, "to_int"); |
| 81 | + if (result == DispatchNode.MISSING) { |
| 82 | + noConversionAvailable.enter(); |
| 83 | + throw new CantConvertException("can't convert Object to Integer"); |
84 | 84 | }
|
85 |
| - |
86 |
| - return redoNode.executeToLong(frame, value); |
| 85 | + return redoNode.executeToLong(frame, result); |
87 | 86 | }
|
88 |
| - |
89 | 87 | }
|
0 commit comments