11/*
2- * Copyright (c) 2024, 2025 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2024, 2026 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * The Universal Permissive License (UPL), Version 1.0
4141package com .oracle .graal .python .builtins .objects .type .slots ;
4242
4343import static com .oracle .graal .python .builtins .PythonBuiltinClassType .TypeError ;
44+ import static com .oracle .graal .python .nodes .SpecialMethodNames .J___BOOL__ ;
4445import static com .oracle .graal .python .nodes .SpecialMethodNames .T___BOOL__ ;
4546
47+ import com .oracle .graal .python .PythonLanguage ;
4648import com .oracle .graal .python .builtins .objects .cext .capi .ExternalFunctionNodes .CheckInquiryResultNode ;
4749import com .oracle .graal .python .builtins .objects .cext .capi .ExternalFunctionNodes .ExternalFunctionInvokeNode ;
4850import com .oracle .graal .python .builtins .objects .cext .capi .ExternalFunctionNodes .PExternalFunctionWrapper ;
4951import com .oracle .graal .python .builtins .objects .cext .capi .transitions .CApiTiming ;
5052import com .oracle .graal .python .builtins .objects .cext .capi .transitions .CApiTransitions .PythonToNativeNode ;
53+ import com .oracle .graal .python .builtins .objects .function .PArguments ;
5154import com .oracle .graal .python .builtins .objects .type .slots .PythonDispatchers .UnaryPythonSlotDispatcherNode ;
55+ import com .oracle .graal .python .builtins .objects .type .slots .TpSlot .TpSlotBuiltinBase ;
5256import com .oracle .graal .python .builtins .objects .type .slots .TpSlot .TpSlotNative ;
5357import com .oracle .graal .python .builtins .objects .type .slots .TpSlot .TpSlotPythonSingle ;
54- import com .oracle .graal .python .builtins .objects .type .slots .TpSlot .TpSlotSimpleBuiltinBase ;
5558import com .oracle .graal .python .lib .PyBoolCheckNode ;
5659import com .oracle .graal .python .lib .PyObjectIsTrueNode ;
5760import com .oracle .graal .python .nodes .ErrorMessages ;
5861import com .oracle .graal .python .nodes .PRaiseNode ;
62+ import com .oracle .graal .python .nodes .call .CallDispatchers ;
5963import com .oracle .graal .python .nodes .function .builtins .PythonUnaryBuiltinNode ;
6064import com .oracle .graal .python .runtime .PythonContext ;
6165import com .oracle .graal .python .runtime .PythonContext .GetThreadStateNode ;
6266import com .oracle .graal .python .runtime .PythonContext .PythonThreadState ;
67+ import com .oracle .truffle .api .HostCompilerDirectives .InliningCutoff ;
68+ import com .oracle .truffle .api .RootCallTarget ;
6369import com .oracle .truffle .api .dsl .Bind ;
6470import com .oracle .truffle .api .dsl .Cached ;
6571import com .oracle .truffle .api .dsl .GenerateCached ;
@@ -74,16 +80,44 @@ public abstract class TpSlotInquiry {
7480 private TpSlotInquiry () {
7581 }
7682
77- public abstract static class TpSlotInquiryBuiltin <T extends InquiryBuiltinNode > extends TpSlotSimpleBuiltinBase <T > {
83+ public abstract static sealed class TpSlotInquiryBuiltin <T extends InquiryBuiltinNode > extends
84+ TpSlotBuiltinBase <T > permits TpSlotInquiryBuiltinSimple , TpSlotInquiryBuiltinComplex {
85+ static final BuiltinSlotWrapperSignature SIGNATURE = BuiltinSlotWrapperSignature .UNARY ;
86+
7887 protected TpSlotInquiryBuiltin (NodeFactory <T > nodeFactory ) {
79- super (nodeFactory , BuiltinSlotWrapperSignature . UNARY , PExternalFunctionWrapper .INQUIRY );
88+ super (nodeFactory , SIGNATURE , PExternalFunctionWrapper .INQUIRY );
8089 }
8190
8291 final InquiryBuiltinNode createSlotNode () {
8392 return createNode ();
8493 }
94+ }
95+
96+ public abstract static non-sealed class TpSlotInquiryBuiltinSimple <T extends InquiryBuiltinNode > extends TpSlotInquiryBuiltin <T > {
97+ protected TpSlotInquiryBuiltinSimple (NodeFactory <T > nodeFactory ) {
98+ super (nodeFactory );
99+ }
85100
86101 protected abstract boolean executeUncached (Object self );
102+
103+ @ Override
104+ public final void initialize (PythonLanguage language ) {
105+ // nop
106+ }
107+ }
108+
109+ public abstract static non-sealed class TpSlotInquiryBuiltinComplex <T extends InquiryBuiltinNode > extends TpSlotInquiryBuiltin <T > {
110+ private final int callTargetIndex = TpSlotBuiltinCallTargetRegistry .getNextCallTargetIndex ();
111+
112+ protected TpSlotInquiryBuiltinComplex (NodeFactory <T > nodeFactory ) {
113+ super (nodeFactory );
114+ }
115+
116+ @ Override
117+ public final void initialize (PythonLanguage language ) {
118+ RootCallTarget callTarget = createSlotCallTarget (language , SIGNATURE , getNodeFactory (), J___BOOL__ );
119+ language .setBuiltinSlotCallTarget (callTargetIndex , callTarget );
120+ }
87121 }
88122
89123 @ GenerateInline (value = false , inherit = true )
@@ -116,13 +150,6 @@ static boolean callCachedBuiltin(VirtualFrame frame, @SuppressWarnings("unused")
116150 return slotNode .executeBool (frame , self );
117151 }
118152
119- @ Specialization (replaces = "callCachedBuiltin" )
120- static boolean callGenericSimpleBuiltin (TpSlotInquiryBuiltin slot , Object self ) {
121- // All nb_bool builtins are known to be simple enough to not require PE for good
122- // performance, so we call them uncached
123- return slot .executeUncached (self );
124- }
125-
126153 @ Specialization
127154 static boolean callPython (VirtualFrame frame , TpSlotPythonSingle slot , Object self ,
128155 @ Cached (inline = false ) CallNbBoolPythonNode callSlotNode ) {
@@ -140,6 +167,23 @@ static boolean callNative(VirtualFrame frame, Node inliningTarget, TpSlotNative
140167 Object result = externalInvokeNode .call (frame , inliningTarget , threadState , C_API_TIMING , T___BOOL__ , slot .callable , toNativeNode .execute (self ));
141168 return checkResultNode .executeBool (threadState , T___BOOL__ , result );
142169 }
170+
171+ @ Specialization (replaces = "callCachedBuiltin" )
172+ static boolean callGenericSimpleBuiltin (TpSlotInquiryBuiltinSimple <?> slot , Object self ) {
173+ // Most nb_bool builtins are known to be simple enough to not require PE for good
174+ // performance, so we call them uncached
175+ return slot .executeUncached (self );
176+ }
177+
178+ @ Specialization (replaces = "callCachedBuiltin" )
179+ @ InliningCutoff
180+ static boolean callGenericComplexBuiltin (VirtualFrame frame , Node inliningTarget , TpSlotInquiryBuiltinComplex <?> slot , Object self ,
181+ @ Cached CallDispatchers .SimpleIndirectInvokeNode invoke ) {
182+ Object [] arguments = PArguments .create (1 );
183+ PArguments .setArgument (arguments , 0 , self );
184+ RootCallTarget callTarget = PythonLanguage .get (inliningTarget ).getBuiltinSlotCallTarget (slot .callTargetIndex );
185+ return (boolean ) invoke .execute (frame , inliningTarget , callTarget , arguments );
186+ }
143187 }
144188
145189 @ GenerateUncached
0 commit comments