4242
4343import static com .oracle .graal .python .builtins .PythonBuiltinClassType .OverflowError ;
4444import static com .oracle .graal .python .builtins .PythonBuiltinClassType .ValueError ;
45+ import static com .oracle .graal .python .nodes .SpecialMethodNames .J___LEN__ ;
4546import static com .oracle .graal .python .nodes .SpecialMethodNames .T___LEN__ ;
4647
48+ import com .oracle .graal .python .PythonLanguage ;
4749import com .oracle .graal .python .builtins .objects .cext .capi .ExternalFunctionNodes .CheckPrimitiveFunctionResultNode ;
4850import com .oracle .graal .python .builtins .objects .cext .capi .ExternalFunctionNodes .ExternalFunctionInvokeNode ;
4951import com .oracle .graal .python .builtins .objects .cext .capi .ExternalFunctionNodes .PExternalFunctionWrapper ;
5052import com .oracle .graal .python .builtins .objects .cext .capi .transitions .CApiTiming ;
5153import com .oracle .graal .python .builtins .objects .cext .capi .transitions .CApiTransitions .PythonToNativeNode ;
54+ import com .oracle .graal .python .builtins .objects .function .PArguments ;
5255import com .oracle .graal .python .builtins .objects .ints .PInt ;
5356import com .oracle .graal .python .builtins .objects .type .slots .HPyDispatchers .UnaryHPySlotDispatcherNode ;
5457import com .oracle .graal .python .builtins .objects .type .slots .PythonDispatchers .UnaryPythonSlotDispatcherNode ;
58+ import com .oracle .graal .python .builtins .objects .type .slots .TpSlot .TpSlotBuiltinBase ;
5559import com .oracle .graal .python .builtins .objects .type .slots .TpSlot .TpSlotNative ;
5660import com .oracle .graal .python .builtins .objects .type .slots .TpSlot .TpSlotPythonSingle ;
57- import com .oracle .graal .python .builtins .objects .type .slots .TpSlot .TpSlotSimpleBuiltinBase ;
5861import com .oracle .graal .python .lib .PyNumberAsSizeNode ;
5962import com .oracle .graal .python .lib .PyNumberIndexNode ;
6063import com .oracle .graal .python .nodes .ErrorMessages ;
6366import com .oracle .graal .python .nodes .PRaiseNode .Lazy ;
6467import com .oracle .graal .python .nodes .function .builtins .PythonUnaryBuiltinNode ;
6568import com .oracle .graal .python .nodes .util .CastToJavaIntLossyNode ;
69+ import com .oracle .graal .python .runtime .ExecutionContext .CallContext ;
6670import com .oracle .graal .python .runtime .PythonContext ;
6771import com .oracle .graal .python .runtime .PythonContext .GetThreadStateNode ;
6872import com .oracle .graal .python .runtime .PythonContext .PythonThreadState ;
6973import com .oracle .graal .python .runtime .exception .PException ;
7074import com .oracle .truffle .api .HostCompilerDirectives .InliningCutoff ;
75+ import com .oracle .truffle .api .RootCallTarget ;
7176import com .oracle .truffle .api .dsl .Bind ;
7277import com .oracle .truffle .api .dsl .Cached ;
7378import com .oracle .truffle .api .dsl .GenerateCached ;
7681import com .oracle .truffle .api .dsl .NodeFactory ;
7782import com .oracle .truffle .api .dsl .Specialization ;
7883import com .oracle .truffle .api .frame .VirtualFrame ;
84+ import com .oracle .truffle .api .nodes .IndirectCallNode ;
7985import com .oracle .truffle .api .nodes .Node ;
8086import com .oracle .truffle .api .nodes .UnexpectedResultException ;
8187import com .oracle .truffle .api .profiles .InlinedBranchProfile ;
88+ import com .oracle .truffle .api .profiles .InlinedConditionProfile ;
8289
8390public abstract class TpSlotLen {
8491 private TpSlotLen () {
@@ -88,16 +95,44 @@ private TpSlotLen() {
8895 // the BCI interpreter. For the time being we do what GraalPy used to do before slots were
8996 // introduced: raise overflow error if native code returns number larger than INT_MAX
9097
91- public abstract static class TpSlotLenBuiltin <T extends LenBuiltinNode > extends TpSlotSimpleBuiltinBase <T > {
98+ public abstract static sealed class TpSlotLenBuiltin <T extends LenBuiltinNode >
99+ extends TpSlotBuiltinBase <T > permits TpSlotLenBuiltinSimple , TpSlotLenBuiltinComplex {
100+ static final BuiltinSlotWrapperSignature SIGNATURE = BuiltinSlotWrapperSignature .UNARY ;
101+
92102 protected TpSlotLenBuiltin (NodeFactory <T > nodeFactory ) {
93- super (nodeFactory , BuiltinSlotWrapperSignature . UNARY , PExternalFunctionWrapper .LENFUNC );
103+ super (nodeFactory , SIGNATURE , PExternalFunctionWrapper .LENFUNC );
94104 }
95105
96106 final LenBuiltinNode createSlotNode () {
97107 return createNode ();
98108 }
109+ }
110+
111+ public abstract static non-sealed class TpSlotLenBuiltinSimple <T extends LenBuiltinNode > extends TpSlotLenBuiltin <T > {
112+ protected TpSlotLenBuiltinSimple (NodeFactory <T > nodeFactory ) {
113+ super (nodeFactory );
114+ }
99115
100116 protected abstract int executeUncached (Object self );
117+
118+ @ Override
119+ public final void initialize (PythonLanguage language ) {
120+ // nop
121+ }
122+ }
123+
124+ public abstract static non-sealed class TpSlotLenBuiltinComplex <T extends LenBuiltinNode > extends TpSlotLenBuiltin <T > {
125+ private final int callTargetIndex = TpSlotBuiltinCallTargetRegistry .getNextCallTargetIndex ();
126+
127+ protected TpSlotLenBuiltinComplex (NodeFactory <T > nodeFactory ) {
128+ super (nodeFactory );
129+ }
130+
131+ @ Override
132+ public final void initialize (PythonLanguage language ) {
133+ RootCallTarget callTarget = createBuiltinCallTarget (language , SIGNATURE , getNodeFactory (), J___LEN__ );
134+ language .setBuiltinSlotCallTarget (callTargetIndex , callTarget );
135+ }
101136 }
102137
103138 @ GenerateInline (value = false , inherit = true )
@@ -125,12 +160,6 @@ static int callCachedBuiltin(VirtualFrame frame, @SuppressWarnings("unused") TpS
125160 return slotNode .executeInt (frame , self );
126161 }
127162
128- @ Specialization (replaces = "callCachedBuiltin" )
129- static int callGenericSimpleBuiltin (TpSlotLenBuiltin <?> slot , Object self ) {
130- // Assumption: all len builtins don't need a frame and PE
131- return slot .executeUncached (self );
132- }
133-
134163 @ Specialization
135164 static int callPython (VirtualFrame frame , TpSlotPythonSingle slot , Object self ,
136165 @ Cached (inline = false ) CallSlotLenPythonNode callSlotNode ) {
@@ -155,6 +184,22 @@ static int callNative(VirtualFrame frame, Node inliningTarget, TpSlotNative slot
155184 return (int ) l ;
156185 }
157186
187+ @ Specialization (replaces = "callCachedBuiltin" )
188+ static int callGenericSimpleBuiltin (TpSlotLenBuiltinSimple <?> slot , Object self ) {
189+ return slot .executeUncached (self );
190+ }
191+
192+ @ Specialization (replaces = "callCachedBuiltin" )
193+ @ InliningCutoff
194+ static int callGenericComplexBuiltin (VirtualFrame frame , Node inliningTarget , TpSlotLenBuiltinComplex <?> slot , Object self ,
195+ @ Cached (inline = false ) CallContext callContext ,
196+ @ Cached InlinedConditionProfile isNullFrameProfile ,
197+ @ Cached (inline = false ) IndirectCallNode indirectCallNode ) {
198+ Object [] arguments = PArguments .create (1 );
199+ PArguments .setArgument (arguments , 0 , self );
200+ return (int ) BuiltinDispatchers .callGenericBuiltin (frame , inliningTarget , slot .callTargetIndex , arguments , callContext , isNullFrameProfile , indirectCallNode );
201+ }
202+
158203 // @Specialization(guards = "slot.isHPySlot()")
159204 // @InliningCutoff
160205 @ SuppressWarnings ("unused" )
0 commit comments