@@ -3674,31 +3674,6 @@ Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope scope, CallattrRe
3674
3674
3675
3675
int npassed_args = argspec.totalPassed ();
3676
3676
3677
- if (rewrite_args && !rewrite_args->args_guarded ) {
3678
- // TODO duplication with runtime_call
3679
- // TODO should know which args don't need to be guarded, ex if we're guaranteed that they
3680
- // already fit, either since the type inferencer could determine that,
3681
- // or because they only need to fit into an UNKNOWN slot.
3682
-
3683
- if (npassed_args >= 1 )
3684
- rewrite_args->arg1 ->addAttrGuard (offsetof (Box, cls), (intptr_t )arg1->cls );
3685
- if (npassed_args >= 2 )
3686
- rewrite_args->arg2 ->addAttrGuard (offsetof (Box, cls), (intptr_t )arg2->cls );
3687
- if (npassed_args >= 3 )
3688
- rewrite_args->arg3 ->addAttrGuard (offsetof (Box, cls), (intptr_t )arg3->cls );
3689
-
3690
- if (npassed_args > 3 ) {
3691
- for (int i = 3 ; i < npassed_args; i++) {
3692
- // TODO if there are a lot of args (>16), might be better to increment a pointer
3693
- // rather index them directly?
3694
- RewriterVar* v = rewrite_args->args ->getAttr ((i - 3 ) * sizeof (Box*), Location::any ());
3695
- v->addAttrGuard (offsetof (Box, cls), (intptr_t )args[i - 3 ]->cls );
3696
- }
3697
- }
3698
-
3699
- rewrite_args->args_guarded = true ;
3700
- }
3701
-
3702
3677
// right now I don't think this is ever called with INST_ONLY?
3703
3678
assert (scope != INST_ONLY);
3704
3679
@@ -5083,6 +5058,36 @@ const char* PyEval_GetFuncDesc(PyObject* func) noexcept {
5083
5058
}
5084
5059
}
5085
5060
5061
+ static void addArgGuards (CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
5062
+ Box** args) {
5063
+ // TODO should know which args don't need to be guarded, ex if we're guaranteed that they
5064
+ // already fit, either since the type inferencer could determine that,
5065
+ // or because they only need to fit into an UNKNOWN slot.
5066
+
5067
+ int kwargs_index = -1 ;
5068
+ if (argspec.has_kwargs )
5069
+ kwargs_index = argspec.kwargsIndex ();
5070
+
5071
+ for (int i = 0 ; i < argspec.totalPassed (); i++) {
5072
+ Box* v = getArg (i, arg1, arg2, arg3, args);
5073
+
5074
+ if (i == kwargs_index) {
5075
+ if (v == NULL ) {
5076
+ // I don't think this case should ever get hit currently -- the only places
5077
+ // we offer rewriting are places that don't have the ability to pass a NULL
5078
+ // kwargs.
5079
+ getArg (i, rewrite_args)->addGuard (0 );
5080
+ } else {
5081
+ getArg (i, rewrite_args)->addAttrGuard (offsetof (Box, cls), (intptr_t )v->cls );
5082
+ }
5083
+ } else {
5084
+ assert (v);
5085
+ getArg (i, rewrite_args)->addAttrGuard (offsetof (Box, cls), (intptr_t )v->cls );
5086
+ }
5087
+ }
5088
+ rewrite_args->args_guarded = true ;
5089
+ }
5090
+
5086
5091
5087
5092
template <ExceptionStyle S, Rewritable rewritable>
5088
5093
Box* runtimeCallInternal (Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
@@ -5173,65 +5178,46 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
5173
5178
return rtn;
5174
5179
}
5175
5180
5176
- if (rewrite_args) {
5177
- if (!rewrite_args->args_guarded ) {
5178
- // TODO should know which args don't need to be guarded, ex if we're guaranteed that they
5179
- // already fit, either since the type inferencer could determine that,
5180
- // or because they only need to fit into an UNKNOWN slot.
5181
-
5182
- int kwargs_index = -1 ;
5183
- if (argspec.has_kwargs )
5184
- kwargs_index = argspec.kwargsIndex ();
5185
-
5186
- for (int i = 0 ; i < npassed_args; i++) {
5187
- Box* v = getArg (i, arg1, arg2, arg3, args);
5188
-
5189
- if (i == kwargs_index) {
5190
- if (v == NULL ) {
5191
- // I don't think this case should ever get hit currently -- the only places
5192
- // we offer rewriting are places that don't have the ability to pass a NULL
5193
- // kwargs.
5194
- getArg (i, rewrite_args)->addGuard (0 );
5195
- } else {
5196
- getArg (i, rewrite_args)->addAttrGuard (offsetof (Box, cls), (intptr_t )v->cls );
5197
- }
5198
- } else {
5199
- assert (v);
5200
- getArg (i, rewrite_args)->addAttrGuard (offsetof (Box, cls), (intptr_t )v->cls );
5201
- }
5202
- }
5203
- rewrite_args->args_guarded = true ;
5204
- }
5205
- }
5206
5181
5207
5182
if (obj->cls == function_cls || obj->cls == builtin_function_or_method_cls) {
5208
5183
BoxedFunctionBase* f = static_cast <BoxedFunctionBase*>(obj);
5209
-
5210
- if (rewrite_args && !rewrite_args->func_guarded ) {
5211
- rewrite_args->obj ->addGuard ((intptr_t )f);
5212
- rewrite_args->func_guarded = true ;
5213
- rewrite_args->rewriter ->addDependenceOn (f->dependent_ics );
5214
- }
5184
+ auto md = f->md ;
5215
5185
5216
5186
// Some functions are sufficiently important that we want them to be able to patchpoint themselves;
5217
5187
// they can do this by setting the "internal_callable" field:
5218
- auto callable = f->md ->internal_callable .get <S>();
5219
-
5188
+ auto callable = md->internal_callable .get <S>();
5220
5189
if (S == CAPI)
5221
- assert ((bool (f-> md ->internal_callable .get (CXX)) == bool (callable))
5190
+ assert ((bool (md->internal_callable .get (CXX)) == bool (callable))
5222
5191
&& " too many opportunities for mistakes unless both CXX and CAPI versions are implemented" );
5223
5192
else
5224
- assert ((bool (f-> md ->internal_callable .get (CAPI)) == bool (callable))
5193
+ assert ((bool (md->internal_callable .get (CAPI)) == bool (callable))
5225
5194
&& " too many opportunities for mistake unless both CXX and CAPI versions are implementeds" );
5226
5195
5227
5196
if (callable == NULL ) {
5228
5197
callable = callFunc<S>;
5229
5198
}
5230
5199
5200
+ if (rewrite_args && !rewrite_args->args_guarded ) {
5201
+ bool does_not_need_guards = callable == &callFunc<S> && md->always_use_version ;
5202
+ if (!does_not_need_guards)
5203
+ addArgGuards (rewrite_args, argspec, arg1, arg2, arg3, args);
5204
+ }
5205
+
5206
+ if (rewrite_args && !rewrite_args->func_guarded ) {
5207
+ rewrite_args->obj ->addGuard ((intptr_t )f);
5208
+ rewrite_args->func_guarded = true ;
5209
+ // callFunc will add the invalidator
5210
+ if (callable != &callFunc<S>)
5211
+ rewrite_args->rewriter ->addDependenceOn (f->dependent_ics );
5212
+ }
5213
+
5231
5214
KEEP_ALIVE (f);
5232
5215
Box* res = callable (f, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
5233
5216
return res;
5234
5217
} else if (obj->cls == instancemethod_cls) {
5218
+ if (rewrite_args && !rewrite_args->args_guarded )
5219
+ addArgGuards (rewrite_args, argspec, arg1, arg2, arg3, args);
5220
+
5235
5221
BoxedInstanceMethod* im = static_cast <BoxedInstanceMethod*>(obj);
5236
5222
5237
5223
RewriterVar* r_im_func = NULL ;
0 commit comments