|
103 | 103 | import org.truffleruby.language.RubySourceNode;
|
104 | 104 | import org.truffleruby.language.WarnNode;
|
105 | 105 | import org.truffleruby.language.WarningNode;
|
106 |
| -import org.truffleruby.language.arguments.ReadCallerFrameNode; |
107 | 106 | import org.truffleruby.language.arguments.RubyArguments;
|
108 | 107 | import org.truffleruby.language.backtrace.Backtrace;
|
109 | 108 | import org.truffleruby.language.backtrace.BacktraceFormatter;
|
|
119 | 118 | import org.truffleruby.language.loader.RequireNode;
|
120 | 119 | import org.truffleruby.language.loader.RequireNodeGen;
|
121 | 120 | import org.truffleruby.language.locals.FindDeclarationVariableNodes.FindAndReadDeclarationVariableNode;
|
122 |
| -import org.truffleruby.language.methods.DeclarationContext; |
123 | 121 | import org.truffleruby.language.methods.GetMethodObjectNode;
|
124 | 122 | import org.truffleruby.language.methods.InternalMethod;
|
125 | 123 | import org.truffleruby.language.objects.AllocationTracing;
|
@@ -1425,104 +1423,71 @@ protected Object send(Frame callerFrame, Object self, Object[] rubyArgs, RootCal
|
1425 | 1423 |
|
1426 | 1424 | }
|
1427 | 1425 |
|
1428 |
| - @CoreMethod(names = "respond_to?", required = 1, optional = 1) |
1429 |
| - @NodeChild(value = "object", type = RubyNode.class) |
1430 |
| - @NodeChild(value = "name", type = RubyNode.class) |
1431 |
| - @NodeChild(value = "includeProtectedAndPrivate", type = RubyBaseNodeWithExecute.class) |
1432 |
| - public abstract static class RespondToNode extends CoreMethodNode { |
1433 |
| - |
1434 |
| - @Child private InternalRespondToNode dispatch; |
1435 |
| - @Child private InternalRespondToNode dispatchIgnoreVisibility; |
1436 |
| - @Child private InternalRespondToNode dispatchRespondToMissing; |
1437 |
| - @Child private ReadCallerFrameNode readCallerFrame; |
1438 |
| - @Child private DispatchNode respondToMissingNode; |
1439 |
| - @Child private BooleanCastNode booleanCastNode; |
1440 |
| - private final ConditionProfile ignoreVisibilityProfile = ConditionProfile.create(); |
1441 |
| - private final ConditionProfile isTrueProfile = ConditionProfile.create(); |
1442 |
| - private final ConditionProfile respondToMissingProfile = ConditionProfile.create(); |
1443 |
| - |
1444 |
| - public RespondToNode() { |
1445 |
| - dispatch = InternalRespondToNode.create(DispatchConfiguration.PUBLIC); |
1446 |
| - dispatchIgnoreVisibility = InternalRespondToNode.create(); |
1447 |
| - dispatchRespondToMissing = InternalRespondToNode.create(); |
1448 |
| - } |
1449 |
| - |
1450 |
| - /** Callers should pass null for the frame here, unless they want to use refinements and can ensure the direct |
1451 |
| - * caller is a Ruby method */ |
1452 |
| - public abstract boolean executeDoesRespondTo(VirtualFrame frame, Object object, Object name, |
1453 |
| - boolean includeProtectedAndPrivate); |
| 1426 | + @ImportStatic(DispatchConfiguration.class) |
| 1427 | + @GenerateUncached |
| 1428 | + @CoreMethod(names = "respond_to?", required = 1, optional = 1, alwaysInlined = true) |
| 1429 | + public abstract static class RespondToNode extends AlwaysInlinedMethodNode { |
1454 | 1430 |
|
1455 |
| - @CreateCast("includeProtectedAndPrivate") |
1456 |
| - protected RubyBaseNodeWithExecute coerceToBoolean(RubyBaseNodeWithExecute includeProtectedAndPrivate) { |
1457 |
| - return BooleanCastWithDefaultNode.create(false, includeProtectedAndPrivate); |
| 1431 | + public final boolean executeDoesRespondTo(Object self, Object name, boolean includeProtectedAndPrivate) { |
| 1432 | + final Object[] rubyArgs = RubyArguments.allocate(2); |
| 1433 | + RubyArguments.setArgument(rubyArgs, 0, name); |
| 1434 | + RubyArguments.setArgument(rubyArgs, 1, includeProtectedAndPrivate); |
| 1435 | + return (boolean) execute(null, self, rubyArgs, null); |
1458 | 1436 | }
|
1459 | 1437 |
|
1460 | 1438 | @Specialization
|
1461 |
| - protected boolean doesRespondTo( |
1462 |
| - VirtualFrame frame, Object object, Object name, boolean includeProtectedAndPrivate, |
1463 |
| - @Cached ConditionProfile notSymbolOrStringProfile, |
| 1439 | + protected boolean doesRespondTo(Frame callerFrame, Object self, Object[] rubyArgs, RootCallTarget target, |
| 1440 | + @Cached BranchProfile notSymbolOrStringProfile, |
1464 | 1441 | @Cached ToJavaStringNode toJavaString,
|
1465 |
| - @Cached ToSymbolNode toSymbolNode) { |
1466 |
| - if (notSymbolOrStringProfile.profile(!RubyGuards.isRubySymbolOrString(name))) { |
| 1442 | + @Cached ToSymbolNode toSymbolNode, |
| 1443 | + @Cached BooleanCastNode castArgumentNode, |
| 1444 | + @Cached ConditionProfile ignoreVisibilityProfile, |
| 1445 | + @Cached ConditionProfile isTrueProfile, |
| 1446 | + @Cached ConditionProfile respondToMissingProfile, |
| 1447 | + @Cached(parameters = "PUBLIC") InternalRespondToNode dispatchPublic, |
| 1448 | + @Cached InternalRespondToNode dispatchPrivate, |
| 1449 | + @Cached InternalRespondToNode dispatchRespondToMissing, |
| 1450 | + @Cached DispatchNode respondToMissingNode, |
| 1451 | + @Cached BooleanCastNode castMissingResultNode) { |
| 1452 | + final Object name = RubyArguments.getArgument(rubyArgs, 0); |
| 1453 | + final int nArgs = RubyArguments.getPositionalArgumentsCount(rubyArgs, false); |
| 1454 | + final boolean includeProtectedAndPrivate = nArgs >= 2 && |
| 1455 | + castArgumentNode.executeToBoolean(RubyArguments.getArgument(rubyArgs, 1)); |
| 1456 | + |
| 1457 | + if (!RubyGuards.isRubySymbolOrString(name)) { |
| 1458 | + notSymbolOrStringProfile.enter(); |
1467 | 1459 | throw new RaiseException(
|
1468 | 1460 | getContext(),
|
1469 |
| - coreExceptions().typeErrorIsNotAOrB(object, "symbol", "string", this)); |
| 1461 | + coreExceptions().typeErrorIsNotAOrB(self, "symbol", "string", this)); |
1470 | 1462 | }
|
1471 | 1463 |
|
1472 |
| - final boolean ret; |
1473 |
| - useCallerRefinements(frame); |
1474 |
| - |
| 1464 | + final String methodName = toJavaString.executeToJavaString(name); |
| 1465 | + final boolean found; |
1475 | 1466 | if (ignoreVisibilityProfile.profile(includeProtectedAndPrivate)) {
|
1476 |
| - ret = dispatchIgnoreVisibility.execute(frame, object, toJavaString.executeToJavaString(name)); |
| 1467 | + found = dispatchPrivate.execute(callerFrame, self, methodName); |
1477 | 1468 | } else {
|
1478 |
| - ret = dispatch.execute(frame, object, toJavaString.executeToJavaString(name)); |
| 1469 | + found = dispatchPublic.execute(callerFrame, self, methodName); |
1479 | 1470 | }
|
1480 | 1471 |
|
1481 |
| - if (isTrueProfile.profile(ret)) { |
| 1472 | + if (isTrueProfile.profile(found)) { |
1482 | 1473 | return true;
|
1483 | 1474 | } else if (respondToMissingProfile
|
1484 |
| - .profile(dispatchRespondToMissing.execute(frame, object, "respond_to_missing?"))) { |
1485 |
| - return respondToMissing(object, toSymbolNode.execute(name), includeProtectedAndPrivate); |
| 1475 | + .profile(dispatchRespondToMissing.execute(callerFrame, self, "respond_to_missing?"))) { |
| 1476 | + return castMissingResultNode.executeToBoolean(respondToMissingNode.call(self, "respond_to_missing?", |
| 1477 | + toSymbolNode.execute(name), includeProtectedAndPrivate)); |
1486 | 1478 | } else {
|
1487 | 1479 | return false;
|
1488 | 1480 | }
|
1489 | 1481 | }
|
1490 |
| - |
1491 |
| - private boolean respondToMissing(Object object, RubySymbol name, boolean includeProtectedAndPrivate) { |
1492 |
| - if (respondToMissingNode == null) { |
1493 |
| - CompilerDirectives.transferToInterpreterAndInvalidate(); |
1494 |
| - respondToMissingNode = insert(DispatchNode.create()); |
1495 |
| - } |
1496 |
| - |
1497 |
| - if (booleanCastNode == null) { |
1498 |
| - CompilerDirectives.transferToInterpreterAndInvalidate(); |
1499 |
| - booleanCastNode = insert(BooleanCastNode.create()); |
1500 |
| - } |
1501 |
| - |
1502 |
| - return booleanCastNode.executeToBoolean( |
1503 |
| - respondToMissingNode.call(object, "respond_to_missing?", name, includeProtectedAndPrivate)); |
1504 |
| - } |
1505 |
| - |
1506 |
| - private void useCallerRefinements(VirtualFrame frame) { |
1507 |
| - if (frame != null) { |
1508 |
| - if (readCallerFrame == null) { |
1509 |
| - CompilerDirectives.transferToInterpreterAndInvalidate(); |
1510 |
| - readCallerFrame = insert(ReadCallerFrameNode.create()); |
1511 |
| - } |
1512 |
| - DeclarationContext context = RubyArguments.getDeclarationContext(readCallerFrame.execute(frame)); |
1513 |
| - RubyArguments.setDeclarationContext(frame, context); |
1514 |
| - } |
1515 |
| - } |
1516 | 1482 | }
|
1517 | 1483 |
|
1518 |
| - @CoreMethod(names = "respond_to_missing?", required = 2) |
1519 |
| - public abstract static class RespondToMissingNode extends CoreMethodArrayArgumentsNode { |
1520 |
| - |
| 1484 | + @GenerateUncached |
| 1485 | + @CoreMethod(names = "respond_to_missing?", required = 2, alwaysInlined = true) |
| 1486 | + public abstract static class RespondToMissingNode extends AlwaysInlinedMethodNode { |
1521 | 1487 | @Specialization
|
1522 |
| - protected boolean doesRespondToMissing(Object object, Object name, Object unusedIncludeAll) { |
| 1488 | + protected boolean respondToMissing(Frame callerFrame, Object self, Object[] rubyArgs, RootCallTarget target) { |
1523 | 1489 | return false;
|
1524 | 1490 | }
|
1525 |
| - |
1526 | 1491 | }
|
1527 | 1492 |
|
1528 | 1493 | @CoreMethod(names = "set_trace_func", isModuleFunction = true, required = 1)
|
|
0 commit comments