-
Notifications
You must be signed in to change notification settings - Fork 584
class.c: clean up any state if we don't finish the class #22374
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: blead
Are you sure you want to change the base?
Conversation
977ed47
to
177bd8b
Compare
struct xpvhv_aux *aux = HvAUX(stash); | ||
|
||
SvREFCNT_dec(aux->xhv_class_superclass); | ||
aux->xhv_class_superclass = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest lifting the pointers to a C autos, and setting struct field to NULL, then call SvREFCNT_dec
. Analyse if SvREFCNT_dec_NN
is appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
xhv_class_superclass
can be NULL if the class has no base class defined.
I don't think there's any value re-ordering here, since we only write to xhv_class_superclass
after the REFCNT_dec.
I think it's unlikely the cache line will expire - this is a reference to an existing class, so it's just going to reduce the reference count and test it.
class.c
Outdated
if (SvTYPE(entry) == SVt_PVGV | ||
&& (cv = GvCV((GV*)entry)) | ||
&& (CvIsMETHOD(cv) || memEQs(kpv, klen, "new"))) { | ||
SvREFCNT_dec(cv); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add _NN(), cv already proved to be derefable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
else if (SvTYPE(entry) == SVt_PVCV | ||
&& (CvIsMETHOD((CV*)entry) || memEQs(kpv, klen, "new"))) { | ||
(void)hv_delete(stash, kpv, HeUTF8(he) ? -(I32)klen : (I32)klen, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pass the HEK* maybe, or U32 hash. hv_delete_ent() maybe??? XS api is not fully there for exotic with HEK with hash, not fetch, HV operations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hv_delete_ent()
would require making a SV, this would only be efficient for the (I think) atypical case of the key being an SVKEY.
class.c
Outdated
|
||
/* remove any ISA entries */ | ||
SV *isaname = newSVpvf("%" HEKf "::ISA", HvNAME_HEK(stash)); | ||
sv_2mortal(isaname); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sv_2mortal(isaname);
to isaname = sv_2mortal(isaname);
, use the free retval register.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
newSVOP(OP_CONST, 0, (SV *)superaux->xhv_class_initfields_cv), | ||
NULL); | ||
U32 fieldix = PadnameFIELDINFO(pn)->fieldix; | ||
(void)hv_store_ent(fieldix_to_padix, sv_2mortal(newSVuv(fieldix)), newSVuv(padix), 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a better way of doing this other than a trip through SvPV(3args)
's S_uiv_2buf()
, or worse going to libc sprintf with dozens of lock aq/releases, and maybe some kernel calls to the FS. I would just have 4 byte / 8 byte UVs stored straight as raw unprintable binary with SvPOK_on(). Hash algo/perl just sees char strings, vs turning them into longer less dense ascii bytes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code was only re-indented
HE *he; | ||
if((he = hv_fetch_ent(fieldix_to_padix, sv_2mortal(newSVuv(fieldix)), 0, 0)) && | ||
SvOK(HeVAL(he))) { | ||
fieldop->op_targ = SvUV(HeVAL(he)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
factor out HeVAL(he)
, get the SV*. its too many layers deep of derefs in code, and probably does optimize, but its 3 or 4 derefs now from the C auto. if accidents happen with multi eval, they will be smaller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code was only re-indented
fieldop->op_private = op_priv; | ||
|
||
HE *he; | ||
if((he = hv_fetch_ent(fieldix_to_padix, sv_2mortal(newSVuv(fieldix)), 0, 0)) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
idk if this is a loop, but if it is, y not reuse the sv_2mortal(newSVuv()); ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a loop, but this code was only re-indented.
@tonycoz do you have a feeling for whether or not we're going to be able to merge this pull request into blead in this dev cycle or not? If not, then I recommend we label it 'defer-next-dev'. |
It's not going anywhere until @leonerd looks at it |
@leonerd Ping? |
t/class/gh22169.t
Outdated
field $x = "First"; | ||
field $w :reader; | ||
ADJUST { | ||
fail("ADJUST from failed class definition called"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likely wants to be ::fail()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code addition looks fine.
I haven't read in detail the large changes to Perl_class_seal_stash()
but I presume this is mostly just a re-indentation exercise with no change besides invoking the new cleanup function in the failure case.
I have read the new .t
file about four times and I imagine it's supposed to invoke a compiletime error in the eval STR
but I can't see what the error is supposed to be. Could it be made clearer there?
Yes, Except for some re-wrapping it's just indentation, the github diff viewer has an option to ignore whitespace which is handy for changes like this: |
There's no closing |
c4e20ea
to
32bd2da
Compare
Squashed the two commits since it didn't seem worth messing with adding to the first commit and dealing with the conflicts in moving the code to the new function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, that test makes sense now. LGTM
Fixes #22169