10
10
package org .truffleruby .language .dispatch ;
11
11
12
12
import com .oracle .truffle .api .Assumption ;
13
- import com .oracle .truffle .api .HostCompilerDirectives .InliningCutoff ;
14
13
import com .oracle .truffle .api .RootCallTarget ;
15
14
import com .oracle .truffle .api .dsl .Cached ;
16
15
import com .oracle .truffle .api .dsl .GenerateUncached ;
19
18
import com .oracle .truffle .api .frame .Frame ;
20
19
import com .oracle .truffle .api .interop .TruffleObject ;
21
20
import com .oracle .truffle .api .nodes .DirectCallNode ;
22
- import com .oracle .truffle .api .profiles .ConditionProfile ;
23
- import org .truffleruby .core .cast .ToSymbolNode ;
24
- import org .truffleruby .core .exception .ExceptionOperations .ExceptionFormatter ;
21
+ import com .oracle .truffle .api .profiles .InlinedConditionProfile ;
25
22
import org .truffleruby .core .hash .RubyHash ;
26
23
import org .truffleruby .core .kernel .TruffleKernelNodes .GetSpecialVariableStorage ;
27
24
import org .truffleruby .core .klass .RubyClass ;
28
- import org .truffleruby .core .symbol .RubySymbol ;
29
- import org .truffleruby .language .RubyGuards ;
30
25
import org .truffleruby .language .RubyRootNode ;
31
26
import org .truffleruby .language .SpecialVariablesSendingNode ;
32
27
import org .truffleruby .language .arguments .ArgumentsDescriptor ;
33
28
import org .truffleruby .language .arguments .EmptyArgumentsDescriptor ;
34
29
import org .truffleruby .language .arguments .KeywordArgumentsDescriptorManager ;
35
30
import org .truffleruby .language .arguments .RubyArguments ;
36
- import org .truffleruby .language .control .RaiseException ;
37
- import org .truffleruby .language .methods .CallForeignMethodNode ;
38
31
import org .truffleruby .language .methods .CallInternalMethodNode ;
39
32
import org .truffleruby .language .methods .InternalMethod ;
40
33
import org .truffleruby .language .methods .LookupMethodNode ;
@@ -290,46 +283,33 @@ protected Object dispatch(
290
283
uncached = "getValidAssumption()" ) Assumption specialVariableAssumption ,
291
284
@ Cached MetaClassNode metaclassNode ,
292
285
@ Cached LookupMethodNode methodLookup ,
293
- @ Cached ConditionProfile methodMissing ,
286
+ @ Cached InlinedConditionProfile methodMissing ,
294
287
@ Cached CallInternalMethodNode callNode ,
295
- @ Cached CallForeignMethodNode callForeign ,
296
- @ Cached DispatchNode callMethodMissing ,
297
- @ Cached ToSymbolNode toSymbol ,
298
- @ Cached GetSpecialVariableStorage readingNode ) {
288
+ @ Cached GetSpecialVariableStorage readingNode ,
289
+ @ Cached LazyDispatchMethodMissingNode lazyDispatchMethodMissingNode ) {
299
290
return dispatchInternal (frame , receiver , methodName , rubyArgs , config , literalCallNode ,
300
- metaclassNode , methodLookup , methodMissing , callNode , readingNode , callForeign , callMethodMissing ,
301
- toSymbol , specialVariableAssumption );
291
+ metaclassNode , methodLookup , methodMissing , callNode , readingNode , specialVariableAssumption ,
292
+ lazyDispatchMethodMissingNode );
302
293
}
303
294
304
295
protected final Object dispatchInternal (Frame frame , Object receiver , String methodName , Object [] rubyArgs ,
305
296
DispatchConfiguration config ,
306
297
LiteralCallNode literalCallNode ,
307
298
MetaClassNode metaClassNode ,
308
299
LookupMethodNode lookupMethodNode ,
309
- ConditionProfile methodMissingProfile ,
300
+ InlinedConditionProfile methodMissingProfile ,
310
301
CallInternalMethodNode callNode ,
311
302
GetSpecialVariableStorage readingNode ,
312
- CallForeignMethodNode callForeign ,
313
- DispatchNode callMethodMissing ,
314
- ToSymbolNode toSymbol , Assumption specialVariableAssumption ) {
303
+ Assumption specialVariableAssumption ,
304
+ LazyDispatchMethodMissingNode lazyDispatchMethodMissingNode ) {
315
305
assert RubyArguments .getSelf (rubyArgs ) == receiver ;
316
306
317
307
final RubyClass metaclass = metaClassNode .execute (this , receiver );
318
308
final InternalMethod method = lookupMethodNode .execute (frame , metaclass , methodName , config );
319
309
320
- if (methodMissingProfile .profile (method == null || method .isUndefined ())) {
321
- switch (config .missingBehavior ) {
322
- case RETURN_MISSING :
323
- return MISSING ;
324
- case CALL_METHOD_MISSING :
325
- // Both branches implicitly profile through lazy node creation
326
- if (RubyGuards .isForeignObject (receiver )) { // TODO (eregon, 16 Aug 2021) maybe use a final boolean on the class to know if foreign
327
- return callForeign (receiver , methodName , rubyArgs , callForeign );
328
- } else {
329
- return callMethodMissing (frame , receiver , methodName , rubyArgs , literalCallNode ,
330
- callMethodMissing , toSymbol );
331
- }
332
- }
310
+ if (methodMissingProfile .profile (this , method == null || method .isUndefined ())) {
311
+ return lazyDispatchMethodMissingNode .get (this ).execute (frame , receiver , methodName , rubyArgs , config ,
312
+ literalCallNode );
333
313
}
334
314
335
315
RubyArguments .setMethod (rubyArgs , method );
@@ -343,75 +323,6 @@ protected final Object dispatchInternal(Frame frame, Object receiver, String met
343
323
}
344
324
345
325
346
- @ InliningCutoff
347
- private Object callMethodMissing (Frame frame , Object receiver , String methodName , Object [] rubyArgs ,
348
- LiteralCallNode literalCallNode , DispatchNode callMethodMissing , ToSymbolNode toSymbol ) {
349
- // profiles through lazy node creation
350
- final RubySymbol symbolName = toSymbol .execute (this , methodName );
351
-
352
- final Object [] newArgs = RubyArguments .repack (rubyArgs , receiver , 0 , 1 );
353
-
354
- RubyArguments .setArgument (newArgs , 0 , symbolName );
355
- final Object result = callMethodMissing .execute (frame , receiver , "method_missing" , newArgs ,
356
- DispatchConfiguration .PRIVATE_RETURN_MISSING_IGNORE_REFINEMENTS ,
357
- literalCallNode );
358
-
359
- if (result == MISSING ) {
360
- throw new RaiseException (getContext (), coreExceptions ().noMethodErrorFromMethodMissing (
361
- ExceptionFormatter .NO_METHOD_ERROR ,
362
- receiver ,
363
- methodName ,
364
- RubyArguments .getPositionalArguments (rubyArgs ),
365
- this ));
366
- }
367
-
368
- return result ;
369
- }
370
-
371
- @ InliningCutoff
372
- protected Object callForeign (Object receiver , String methodName , Object [] rubyArgs ,
373
- CallForeignMethodNode callForeignMethodNode ) {
374
- // profiles through lazy node creation
375
- //final CallForeignMethodNode callForeignMethodNode = getCallForeignMethodNode();
376
-
377
- final Object block = RubyArguments .getBlock (rubyArgs );
378
- final Object [] arguments = RubyArguments .getPositionalArguments (rubyArgs );
379
- return callForeignMethodNode .execute (receiver , methodName , block , arguments );
380
- }
381
-
382
- // protected CallForeignMethodNode getCallForeignMethodNode() {
383
- // if (callForeign == null) {
384
- // CompilerDirectives.transferToInterpreterAndInvalidate();
385
- // callForeign = insert(CallForeignMethodNode.create());
386
- // }
387
- // return callForeign;
388
- // }
389
-
390
- // protected DispatchNode getMethodMissingNode() {
391
- // if (callMethodMissing == null) {
392
- // CompilerDirectives.transferToInterpreterAndInvalidate();
393
- // // #method_missing ignores refinements on CRuby: https://bugs.ruby-lang.org/issues/13129
394
- // callMethodMissing = insert(
395
- // DispatchNode.create());
396
- // }
397
- // return callMethodMissing;
398
- // }
399
-
400
- // protected void methodMissingMissingProfileEnter() {
401
- // if (!methodMissingMissingProfile) {
402
- // CompilerDirectives.transferToInterpreterAndInvalidate();
403
- // methodMissingMissingProfile = true;
404
- // }
405
- // }
406
-
407
- // protected RubySymbol nameToSymbol(String methodName) {
408
- // if (toSymbol == null) {
409
- // CompilerDirectives.transferToInterpreterAndInvalidate();
410
- // toSymbol = insert(ToSymbolNodeGen.create());
411
- // }
412
- // return toSymbol.execute(methodName);
413
- // }
414
-
415
326
/** This will be called from the {@link CallInternalMethodNode} child whenever it creates a new
416
327
* {@link DirectCallNode}. */
417
328
public final void applySplittingInliningStrategy (RootCallTarget callTarget , String methodName ,
0 commit comments