9
9
*/
10
10
package org .truffleruby .language .dispatch ;
11
11
12
+ import com .oracle .truffle .api .dsl .Cached ;
13
+ import com .oracle .truffle .api .dsl .Specialization ;
12
14
import com .oracle .truffle .api .profiles .CountingConditionProfile ;
15
+ import com .oracle .truffle .api .profiles .InlinedBranchProfile ;
16
+ import com .oracle .truffle .api .profiles .InlinedConditionProfile ;
13
17
import org .truffleruby .RubyContext ;
14
18
import org .truffleruby .RubyLanguage ;
15
19
import org .truffleruby .core .array .ArrayAppendOneNode ;
16
20
import org .truffleruby .core .array .AssignableNode ;
17
21
import org .truffleruby .core .array .RubyArray ;
18
22
import org .truffleruby .core .cast .BooleanCastNode ;
19
- import org .truffleruby .core .cast .BooleanCastNodeGen ;
20
23
import org .truffleruby .core .inlined .LambdaToProcNode ;
21
24
import org .truffleruby .core .string .FrozenStrings ;
22
25
import org .truffleruby .core .symbol .RubySymbol ;
37
40
import com .oracle .truffle .api .CompilerDirectives ;
38
41
import com .oracle .truffle .api .frame .VirtualFrame ;
39
42
import com .oracle .truffle .api .nodes .ExplodeLoop ;
40
- import com .oracle .truffle .api .profiles .BranchProfile ;
41
- import com .oracle .truffle .api .profiles .ConditionProfile ;
42
43
import org .truffleruby .language .methods .LookupMethodOnSelfNode ;
43
44
44
45
import java .util .Map ;
@@ -230,10 +231,11 @@ private SplatToArgsNode createSplatToArgsNode() {
230
231
public Object isDefined (VirtualFrame frame , RubyLanguage language , RubyContext context ) {
231
232
if (definedNode == null ) {
232
233
CompilerDirectives .transferToInterpreterAndInvalidate ();
233
- definedNode = insert (new DefinedNode ());
234
+ definedNode = insert (
235
+ RubyCallNodeFactory .DefinedNodeGen .create (methodName , receiver , arguments , dispatchConfig ));
234
236
}
235
237
236
- return definedNode .isDefined (frame , context );
238
+ return definedNode .execute (frame , context );
237
239
}
238
240
239
241
public String getName () {
@@ -290,48 +292,65 @@ public RubyNode cloneUninitialized() {
290
292
return copy .copyFlags (this );
291
293
}
292
294
293
- private class DefinedNode extends RubyBaseNode {
295
+ abstract static class DefinedNode extends RubyBaseNode {
294
296
295
- private final RubySymbol methodNameSymbol = getSymbol (methodName );
297
+ private final RubySymbol methodNameSymbol ;
298
+ private final String methodName ;
299
+ private final DispatchConfiguration dispatchConfig ;
296
300
301
+ @ Child private RubyNode receiver ;
302
+ @ Children private final RubyNode [] arguments ;
297
303
@ Child private DispatchNode respondToMissing = DispatchNode .create (PRIVATE_RETURN_MISSING );
298
- @ Child private BooleanCastNode respondToMissingCast = BooleanCastNodeGen .create (null );
299
304
305
+ public DefinedNode (
306
+ String methodName ,
307
+ RubyNode receiver ,
308
+ RubyNode [] arguments ,
309
+ DispatchConfiguration dispatchConfig ) {
310
+ this .methodName = methodName ;
311
+ this .methodNameSymbol = getSymbol (methodName );
312
+ this .receiver = receiver ;
313
+ this .arguments = arguments ;
314
+ this .dispatchConfig = dispatchConfig ;
300
315
301
- @ Child private LookupMethodOnSelfNode lookupMethodNode = LookupMethodOnSelfNode . create ();
316
+ }
302
317
303
- private final ConditionProfile receiverDefinedProfile = ConditionProfile .create ();
304
- private final BranchProfile argumentNotDefinedProfile = BranchProfile .create ();
305
- private final BranchProfile allArgumentsDefinedProfile = BranchProfile .create ();
306
- private final BranchProfile receiverExceptionProfile = BranchProfile .create ();
307
- private final ConditionProfile methodNotFoundProfile = ConditionProfile .create ();
318
+ public abstract Object execute (VirtualFrame frame , RubyContext context );
308
319
320
+ @ Specialization
309
321
@ ExplodeLoop
310
- public Object isDefined (VirtualFrame frame , RubyContext context ) {
311
- if (receiverDefinedProfile .profile (receiver .isDefined (frame , getLanguage (), context ) == nil )) {
322
+ protected Object isDefined (VirtualFrame frame , RubyContext context ,
323
+ @ Cached LookupMethodOnSelfNode lookupMethodNode ,
324
+ @ Cached BooleanCastNode respondToMissingCast ,
325
+ @ Cached InlinedConditionProfile receiverDefinedProfile ,
326
+ @ Cached InlinedBranchProfile allArgumentsDefinedProfile ,
327
+ @ Cached InlinedBranchProfile receiverExceptionProfile ,
328
+ @ Cached InlinedConditionProfile methodNotFoundProfile ,
329
+ @ Cached InlinedBranchProfile argumentNotDefinedProfile ) {
330
+ if (receiverDefinedProfile .profile (this , receiver .isDefined (frame , getLanguage (), context ) == nil )) {
312
331
return nil ;
313
332
}
314
333
315
334
for (RubyNode argument : arguments ) {
316
335
if (argument .isDefined (frame , getLanguage (), context ) == nil ) {
317
- argumentNotDefinedProfile .enter ();
336
+ argumentNotDefinedProfile .enter (this );
318
337
return nil ;
319
338
}
320
339
}
321
340
322
- allArgumentsDefinedProfile .enter ();
341
+ allArgumentsDefinedProfile .enter (this );
323
342
324
343
final Object receiverObject ;
325
344
try {
326
345
receiverObject = receiver .execute (frame );
327
346
} catch (RaiseException e ) {
328
- receiverExceptionProfile .enter ();
347
+ receiverExceptionProfile .enter (this );
329
348
return nil ;
330
349
}
331
350
332
351
final InternalMethod method = lookupMethodNode .execute (frame , receiverObject , methodName , dispatchConfig );
333
352
334
- if (methodNotFoundProfile .profile (method == null )) {
353
+ if (methodNotFoundProfile .profile (this , method == null )) {
335
354
final Object r = respondToMissing .call (receiverObject , "respond_to_missing?" , methodNameSymbol , false );
336
355
337
356
if (r != DispatchNode .MISSING && !respondToMissingCast .execute (r )) {
@@ -341,7 +360,5 @@ public Object isDefined(VirtualFrame frame, RubyContext context) {
341
360
342
361
return FrozenStrings .METHOD ;
343
362
}
344
-
345
363
}
346
-
347
364
}
0 commit comments