Make all the simple readers and predicates XS template xs-attr-template
gfx [Fri, 10 Jul 2009 08:57:03 +0000 (17:57 +0900)]
About 3% faster.

12 files changed:
lib/Class/MOP/Attribute.pm
lib/Class/MOP/Class.pm
lib/Class/MOP/Instance.pm
lib/Class/MOP/Method.pm
mop.c
mop.h
xs/Attribute.xs
xs/Class.xs
xs/Instance.xs [new file with mode: 0755]
xs/MOP.xs
xs/Method.xs
xs/Package.xs

index 3e41652..da4de78 100644 (file)
@@ -155,30 +155,30 @@ sub _set_initial_slot_value {
 # the next bunch of methods will get bootstrapped
 # away in the Class::MOP bootstrapping section
 
-sub associated_class   { $_[0]->{'associated_class'}   }
-sub associated_methods { $_[0]->{'associated_methods'} }
-
-sub has_accessor    { defined($_[0]->{'accessor'}) }
-sub has_reader      { defined($_[0]->{'reader'}) }
-sub has_writer      { defined($_[0]->{'writer'}) }
-sub has_predicate   { defined($_[0]->{'predicate'}) }
-sub has_clearer     { defined($_[0]->{'clearer'}) }
-sub has_builder     { defined($_[0]->{'builder'}) }
-sub has_init_arg    { defined($_[0]->{'init_arg'}) }
-sub has_default     { defined($_[0]->{'default'}) }
-sub has_initializer { defined($_[0]->{'initializer'}) }
-sub has_insertion_order { defined($_[0]->{'insertion_order'}) }
-
-sub accessor           { $_[0]->{'accessor'}    }
-sub reader             { $_[0]->{'reader'}      }
-sub writer             { $_[0]->{'writer'}      }
-sub predicate          { $_[0]->{'predicate'}   }
-sub clearer            { $_[0]->{'clearer'}     }
-sub builder            { $_[0]->{'builder'}     }
-sub init_arg           { $_[0]->{'init_arg'}    }
-sub initializer        { $_[0]->{'initializer'} }
-sub definition_context { $_[0]->{'definition_context'} }
-sub insertion_order    { $_[0]->{'insertion_order'} }
+#sub associated_class   { $_[0]->{'associated_class'}   }
+#sub associated_methods { $_[0]->{'associated_methods'} }
+
+#sub has_accessor    { defined($_[0]->{'accessor'}) }
+#sub has_reader      { defined($_[0]->{'reader'}) }
+#sub has_writer      { defined($_[0]->{'writer'}) }
+#sub has_predicate   { defined($_[0]->{'predicate'}) }
+#sub has_clearer     { defined($_[0]->{'clearer'}) }
+#sub has_builder     { defined($_[0]->{'builder'}) }
+#sub has_init_arg    { defined($_[0]->{'init_arg'}) }
+#sub has_default     { defined($_[0]->{'default'}) }
+#sub has_initializer { defined($_[0]->{'initializer'}) }
+#sub has_insertion_order { defined($_[0]->{'insertion_order'}) }
+
+#sub accessor           { $_[0]->{'accessor'}    }
+#sub reader             { $_[0]->{'reader'}      }
+#sub writer             { $_[0]->{'writer'}      }
+#sub predicate          { $_[0]->{'predicate'}   }
+#sub clearer            { $_[0]->{'clearer'}     }
+#sub builder            { $_[0]->{'builder'}     }
+#sub init_arg           { $_[0]->{'init_arg'}    }
+#sub initializer        { $_[0]->{'initializer'} }
+#sub definition_context { $_[0]->{'definition_context'} }
+#sub insertion_order    { $_[0]->{'insertion_order'} }
 sub _set_insertion_order { $_[0]->{'insertion_order'} = $_[1] }
 
 # end bootstrapped away method section.
index 8810338..7fb3622 100644 (file)
@@ -337,15 +337,15 @@ sub create {
 # all these attribute readers will be bootstrapped
 # away in the Class::MOP bootstrap section
 
-sub get_attribute_map        { $_[0]->{'attributes'}                  }
-sub attribute_metaclass      { $_[0]->{'attribute_metaclass'}         }
-sub method_metaclass         { $_[0]->{'method_metaclass'}            }
-sub wrapped_method_metaclass { $_[0]->{'wrapped_method_metaclass'}    }
-sub instance_metaclass       { $_[0]->{'instance_metaclass'}          }
-sub immutable_trait          { $_[0]->{'immutable_trait'}             }
-sub constructor_class        { $_[0]->{'constructor_class'}           }
-sub constructor_name         { $_[0]->{'constructor_name'}            }
-sub destructor_class         { $_[0]->{'destructor_class'}            }
+#sub get_attribute_map        { $_[0]->{'attributes'}                  }
+#sub attribute_metaclass      { $_[0]->{'attribute_metaclass'}         }
+#sub method_metaclass         { $_[0]->{'method_metaclass'}            }
+#sub wrapped_method_metaclass { $_[0]->{'wrapped_method_metaclass'}    }
+#sub instance_metaclass       { $_[0]->{'instance_metaclass'}          }
+#sub immutable_trait          { $_[0]->{'immutable_trait'}             }
+#sub constructor_class        { $_[0]->{'constructor_class'}           }
+#sub constructor_name         { $_[0]->{'constructor_name'}            }
+#sub destructor_class         { $_[0]->{'destructor_class'}            }
 
 # Instance Construction & Cloning
 
index 8643e3e..39c0270 100644 (file)
@@ -66,7 +66,7 @@ sub _new {
 
 sub _class_name { $_[0]->{_class_name} ||= $_[0]->associated_metaclass->name }
 
-sub associated_metaclass { $_[0]{'associated_metaclass'} }
+#sub associated_metaclass { $_[0]{'associated_metaclass'} }
 
 sub create_instance {
     my $self = shift;
index ea580ab..4f65c62 100644 (file)
@@ -55,7 +55,7 @@ sub _new {
 
 ## accessors
 
-sub associated_metaclass { shift->{'associated_metaclass'} }
+#sub associated_metaclass { shift->{'associated_metaclass'} }
 
 sub attach_to_class {
     my ( $self, $class ) = @_;
@@ -73,7 +73,7 @@ sub fully_qualified_name {
     $self->package_name . '::' . $self->name;
 }
 
-sub original_method { (shift)->{'original_method'} }
+#sub original_method { (shift)->{'original_method'} }
 
 sub _set_original_method { $_[0]->{'original_method'} = $_[1] }
 
diff --git a/mop.c b/mop.c
index 0fc1be1..963b8b5 100644 (file)
--- a/mop.c
+++ b/mop.c
@@ -9,7 +9,7 @@ mop_call_xs (pTHX_ XSPROTO(subaddr), CV *cv, SV **mark)
     PUTBACK;
 }
 
-#if PERL_VERSION >= 10
+#if PERL_BCDVERSION >= 0x5010000
 UV
 mop_check_package_cache_flag (pTHX_ HV *stash)
 {
@@ -132,7 +132,6 @@ mop_get_package_symbols (HV *stash, type_filter_t filter, get_package_symbols_cb
         char *key;
         STRLEN keylen;
         char *package;
-        SV *fq;
 
         switch( SvTYPE(gv) ) {
 #ifndef SVt_RV
@@ -145,6 +144,7 @@ mop_get_package_symbols (HV *stash, type_filter_t filter, get_package_symbols_cb
                  * return CODE symbols */
                 if (filter == TYPE_FILTER_CODE) {
                     if (SvROK(gv)) {
+                        SV* fq;
                         /* we don't really care about the length,
                            but that's the API */
                         key = HePV(he, keylen);
@@ -202,59 +202,40 @@ mop_get_all_package_symbols (HV *stash, type_filter_t filter)
     return ret;
 }
 
-#define DECLARE_KEY(name)                    { #name, #name, NULL, 0 }
-#define DECLARE_KEY_WITH_VALUE(name, value)  { #name, value, NULL, 0 }
-
-/* the order of these has to match with those in mop.h */
-static struct {
-    const char *name;
-    const char *value;
-    SV *key;
-    U32 hash;
-} prehashed_keys[key_last] = {
-    DECLARE_KEY(name),
-    DECLARE_KEY(package),
-    DECLARE_KEY(package_name),
-    DECLARE_KEY(body),
-    DECLARE_KEY_WITH_VALUE(package_cache_flag, "_package_cache_flag"),
-    DECLARE_KEY(methods),
-    DECLARE_KEY(VERSION),
-    DECLARE_KEY(ISA)
-};
+static MGVTBL mop_accessor_vtbl; /* the MAGIC identity */
 
-SV *
-mop_prehashed_key_for (mop_prehashed_key_t key)
-{
-    return prehashed_keys[key].key;
-}
+void
+mop_install_simple_reader(const char* const fq_name, const char* const key, const int accessor_type){
+    CV* const xsub  = newXS((char*)fq_name, mop_xs_simple_reader, __FILE__);
+    SV* const keysv = newSVpvn_share(key, strlen(key), 0U);
 
-U32
-mop_prehashed_hash_for (mop_prehashed_key_t key)
-{
-    return prehashed_keys[key].hash;
+    sv_magicext((SV*)xsub, keysv, PERL_MAGIC_ext, &mop_accessor_vtbl, NULL, 0);
+    SvREFCNT_dec(keysv); /* sv_magicext() increases refcnt in mg_obj */
+
+    CvXSUBANY(xsub).any_i32 = accessor_type;
 }
 
-void
-mop_prehash_keys ()
-{
-    int i;
-    for (i = 0; i < key_last; i++) {
-        const char *value = prehashed_keys[i].value;
-        prehashed_keys[i].key = newSVpv(value, strlen(value));
-        PERL_HASH(prehashed_keys[i].hash, value, strlen(value));
+static MAGIC*
+mop_mg_find_by_vtbl(SV* const sv, const MGVTBL* const vtbl){
+    MAGIC* mg;
+
+    assert(sv != NULL);
+    for(mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic){
+        if(mg->mg_virtual == vtbl){
+            break;
+        }
     }
+    return mg;
 }
 
 XS(mop_xs_simple_reader)
 {
-#ifdef dVAR
     dVAR; dXSARGS;
-#else
-    dXSARGS;
-#endif
+    MAGIC* const mg = mop_mg_find_by_vtbl((SV*)cv, &mop_accessor_vtbl);
+    SV* const key   = mg->mg_obj;
     register HE *he;
-    mop_prehashed_key_t key = (mop_prehashed_key_t)CvXSUBANY(cv).any_i32;
     SV *self;
+    SV *retval;
 
     if (items != 1) {
         croak("expected exactly one argument");
@@ -263,20 +244,30 @@ XS(mop_xs_simple_reader)
     self = ST(0);
 
     if (!SvROK(self)) {
-        croak("can't call %s as a class method", prehashed_keys[key].name);
+        croak("can't call %s as a class method", GvNAME(CvGV(cv)));
     }
 
     if (SvTYPE(SvRV(self)) != SVt_PVHV) {
         croak("object is not a hashref");
     }
 
-    if ((he = hv_fetch_ent((HV *)SvRV(self), prehashed_keys[key].key, 0, prehashed_keys[key].hash))) {
-        ST(0) = HeVAL(he);
+    if ((he = hv_fetch_ent((HV *)SvRV(self), key, 0, 0U))) {
+        switch(XSANY.any_i32){
+        case SIMPLE_READER:
+            retval = HeVAL(he);
+            break;
+        case SIMPLE_PREDICATE:
+            retval = boolSV(SvOK(HeVAL(he)));
+            break;
+        default:
+            croak("panic: not reached");
+            retval = NULL; /* -W */
+        }
     }
     else {
-        ST(0) = &PL_sv_undef;
+        retval = &PL_sv_undef;
     }
 
+    ST(0) = retval;
     XSRETURN(1);
 }
-
diff --git a/mop.h b/mop.h
index 288c8ad..849ad1d 100644 (file)
--- a/mop.h
+++ b/mop.h
 
 void mop_call_xs (pTHX_ XSPROTO(subaddr), CV *cv, SV **mark);
 
-typedef enum {
-    KEY_name,
-    KEY_package,
-    KEY_package_name,
-    KEY_body,
-    KEY_package_cache_flag,
-    KEY_methods,
-    KEY_VERSION,
-    KEY_ISA,
-    key_last,
-} mop_prehashed_key_t;
-
-#define KEY_FOR(name)  mop_prehashed_key_for(KEY_ ##name)
-#define HASH_FOR(name) mop_prehashed_hash_for(KEY_ ##name)
-
-void mop_prehash_keys (void);
-SV *mop_prehashed_key_for (mop_prehashed_key_t key);
-U32 mop_prehashed_hash_for (mop_prehashed_key_t key);
+
+#define MAKE_KEYSV(name) newSVpvn_share(#name, sizeof(#name)-1, 0U)
+
+void mop_install_simple_reader(const char* const fq_name, const char* const key, const int accessor_type);
+
+#define SIMPLE_READER    1
+#define SIMPLE_PREDICATE 2
 
 #define INSTALL_SIMPLE_READER(klass, name)  INSTALL_SIMPLE_READER_WITH_KEY(klass, name, name)
-#define INSTALL_SIMPLE_READER_WITH_KEY(klass, name, key) \
-    { \
-        CV *cv = newXS("Class::MOP::" #klass "::" #name, mop_xs_simple_reader, __FILE__); \
-        CvXSUBANY(cv).any_i32 = KEY_ ##key; \
-    }
+#define INSTALL_SIMPLE_READER_WITH_KEY(klass, name, key) mop_install_simple_reader("Class::MOP::" #klass "::" #name, #key, SIMPLE_READER)
+
+#define INSTALL_SIMPLE_PREDICATE(klass, name)  INSTALL_SIMPLE_PREDICATE_WITH_KEY(klass, name, name)
+#define INSTALL_SIMPLE_PREDICATE_WITH_KEY(klass, name, key) mop_install_simple_reader("Class::MOP::" #klass "::has_" #name, #key, SIMPLE_PREDICATE)
+
 
 XS(mop_xs_simple_reader);
 
 extern SV *mop_method_metaclass;
 extern SV *mop_associated_metaclass;
 extern SV *mop_wrap;
+extern SV *mop_methods;
+extern SV *mop_name;
+extern SV *mop_body;
+extern SV *mop_package;
+extern SV *mop_package_name;
+extern SV *mop_package_cache_flag;
+extern SV *mop_VERSION;
+extern SV *mop_ISA;
 
 UV mop_check_package_cache_flag(pTHX_ HV *stash);
 int mop_get_code_info (SV *coderef, char **pkg, char **name);
index 0375cb4..6097b7c 100644 (file)
@@ -6,3 +6,25 @@ PROTOTYPES: DISABLE
 
 BOOT:
     INSTALL_SIMPLE_READER(Attribute, name);
+    INSTALL_SIMPLE_READER(Attribute, associated_class);
+    INSTALL_SIMPLE_READER(Attribute, associated_methods);
+    INSTALL_SIMPLE_READER(Attribute, accessor);
+    INSTALL_SIMPLE_READER(Attribute, reader);
+    INSTALL_SIMPLE_READER(Attribute, writer);
+    INSTALL_SIMPLE_READER(Attribute, predicate);
+    INSTALL_SIMPLE_READER(Attribute, clearer);
+    INSTALL_SIMPLE_READER(Attribute, builder);
+    INSTALL_SIMPLE_READER(Attribute, init_arg);
+    INSTALL_SIMPLE_READER(Attribute, initializer);
+    INSTALL_SIMPLE_READER(Attribute, insertion_order);
+    INSTALL_SIMPLE_READER(Attribute, definition_context);
+
+    INSTALL_SIMPLE_PREDICATE(Attribute, accessor);
+    INSTALL_SIMPLE_PREDICATE(Attribute, reader);
+    INSTALL_SIMPLE_PREDICATE(Attribute, writer);
+    INSTALL_SIMPLE_PREDICATE(Attribute, predicate);
+    INSTALL_SIMPLE_PREDICATE(Attribute, clearer);
+    INSTALL_SIMPLE_PREDICATE(Attribute, builder);
+    INSTALL_SIMPLE_PREDICATE(Attribute, init_arg);
+    INSTALL_SIMPLE_PREDICATE(Attribute, initializer);
+    INSTALL_SIMPLE_PREDICATE(Attribute, default);
index e187b4d..d779683 100644 (file)
@@ -34,7 +34,7 @@ mop_update_method_map(pTHX_ SV *const self, SV *const class_name, HV *const stas
 
         method_slot = *hv_fetch(map, method_name, method_name_len, TRUE);
         if ( SvOK(method_slot) ) {
-            SV *const body = mop_call0(aTHX_ method_slot, KEY_FOR(body)); /* $method_object->body() */
+            SV *const body = mop_call0(aTHX_ method_slot, mop_body); /* $method_object->body() */
             if ( SvROK(body) && ((CV *) SvRV(body)) == cv ) {
                 continue;
             }
@@ -59,9 +59,9 @@ mop_update_method_map(pTHX_ SV *const self, SV *const class_name, HV *const stas
         mPUSHs(newRV_inc((SV *)cv));
         PUSHs(mop_associated_metaclass);
         PUSHs(self);
-        PUSHs(KEY_FOR(package_name));
+        PUSHs(mop_package_name);
         PUSHs(class_name);
-        PUSHs(KEY_FOR(name));
+        PUSHs(mop_name);
         mPUSHs(newSVpv(method_name, method_name_len));
         PUTBACK;
 
@@ -79,6 +79,19 @@ mop_update_method_map(pTHX_ SV *const self, SV *const class_name, HV *const stas
 
 MODULE = Class::MOP::Class    PACKAGE = Class::MOP::Class
 
+BOOT:
+    INSTALL_SIMPLE_READER_WITH_KEY(Class, get_attribute_map, attributes);
+    /* INSTALL_SIMPLE_READER_WITH_KEY(Class, _method_map, methods); */
+    INSTALL_SIMPLE_READER(Class, attribute_metaclass);
+    INSTALL_SIMPLE_READER(Class, method_metaclass);
+    INSTALL_SIMPLE_READER(Class, wrapped_method_metaclass);
+    INSTALL_SIMPLE_READER(Class, instance_metaclass);
+    INSTALL_SIMPLE_READER(Class, immutable_trait);
+    INSTALL_SIMPLE_READER(Class, constructor_name);
+    INSTALL_SIMPLE_READER(Class, constructor_class);
+    INSTALL_SIMPLE_READER(Class, destructor_class);
+
+
 PROTOTYPES: DISABLE
 
 void
@@ -86,7 +99,7 @@ get_method_map(self)
     SV *self
     PREINIT:
         HV *const obj        = (HV *)SvRV(self);
-        SV *const class_name = HeVAL( hv_fetch_ent(obj, KEY_FOR(package), 0, HASH_FOR(package)) );
+        SV *const class_name = HeVAL( hv_fetch_ent(obj, mop_package, 0, 0U) );
         HV *const stash      = gv_stashsv(class_name, 0);
         UV current;
         SV *cache_flag;
@@ -98,8 +111,8 @@ get_method_map(self)
         }
 
         current    = mop_check_package_cache_flag(aTHX_ stash);
-        cache_flag = HeVAL( hv_fetch_ent(obj, KEY_FOR(package_cache_flag), TRUE, HASH_FOR(package_cache_flag)));
-        map_ref    = HeVAL( hv_fetch_ent(obj, KEY_FOR(methods), TRUE, HASH_FOR(methods)));
+        cache_flag = HeVAL( hv_fetch_ent(obj, mop_package_cache_flag, TRUE, 0U));
+        map_ref    = HeVAL( hv_fetch_ent(obj, mop_methods, TRUE, 0U));
 
         /* $self->{methods} does not yet exist (or got deleted) */
         if ( !SvROK(map_ref) || SvTYPE(SvRV(map_ref)) != SVt_PVHV ) {
diff --git a/xs/Instance.xs b/xs/Instance.xs
new file mode 100755 (executable)
index 0000000..ecef003
--- /dev/null
@@ -0,0 +1,8 @@
+#include "mop.h"
+
+MODULE = Class::MOP::Instance  PACKAGE = Class::MOP::Instance
+
+PROTOTYPES: DISABLE
+
+BOOT:
+    INSTALL_SIMPLE_READER(Instance, associated_metaclass);
index 5dfc0cd..fe98956 100644 (file)
--- a/xs/MOP.xs
+++ b/xs/MOP.xs
@@ -3,6 +3,15 @@
 SV *mop_method_metaclass;
 SV *mop_associated_metaclass;
 SV *mop_wrap;
+SV *mop_methods;
+SV *mop_name;
+SV *mop_body;
+SV *mop_package;
+SV *mop_package_name;
+SV *mop_package_cache_flag;
+
+SV *mop_VERSION;
+SV *mop_ISA;
 
 static bool
 find_method (const char *key, STRLEN keylen, SV *val, void *ud)
@@ -19,22 +28,30 @@ EXTERN_C XS(boot_Class__MOP__Package);
 EXTERN_C XS(boot_Class__MOP__Class);
 EXTERN_C XS(boot_Class__MOP__Attribute);
 EXTERN_C XS(boot_Class__MOP__Method);
+EXTERN_C XS(boot_Class__MOP__Instance);
 
 MODULE = Class::MOP   PACKAGE = Class::MOP
 
 PROTOTYPES: DISABLE
 
 BOOT:
-    mop_prehash_keys();
-
-    mop_method_metaclass     = newSVpvs("method_metaclass");
-    mop_wrap                 = newSVpvs("wrap");
-    mop_associated_metaclass = newSVpvs("associated_metaclass");
+    mop_method_metaclass     = MAKE_KEYSV(method_metaclass);
+    mop_wrap                 = MAKE_KEYSV(wrap);
+    mop_associated_metaclass = MAKE_KEYSV(associated_metaclass);
+    mop_methods              = MAKE_KEYSV(methods);
+    mop_name                 = MAKE_KEYSV(name);
+    mop_body                 = MAKE_KEYSV(body);
+    mop_package              = MAKE_KEYSV(package);
+    mop_package_name         = MAKE_KEYSV(package_name);
+    mop_package_cache_flag   = MAKE_KEYSV(_package_cache_flag);
+    mop_VERSION              = MAKE_KEYSV(VERSION);
+    mop_ISA                  = MAKE_KEYSV(ISA);
 
     MOP_CALL_BOOT (boot_Class__MOP__Package);
     MOP_CALL_BOOT (boot_Class__MOP__Class);
     MOP_CALL_BOOT (boot_Class__MOP__Attribute);
     MOP_CALL_BOOT (boot_Class__MOP__Method);
+    MOP_CALL_BOOT (boot_Class__MOP__Instance);
 
 # use prototype here to be compatible with get_code_info from Sub::Identify
 void
@@ -70,8 +87,8 @@ is_class_loaded(klass=&PL_sv_undef)
             XSRETURN_NO;
         }
 
-        if (hv_exists_ent (stash, KEY_FOR(VERSION), HASH_FOR(VERSION))) {
-            HE *version = hv_fetch_ent(stash, KEY_FOR(VERSION), 0, HASH_FOR(VERSION));
+        if (hv_exists_ent (stash, mop_VERSION, 0U)) {
+            HE *version = hv_fetch_ent(stash, mop_VERSION, 0, 0U);
             SV *version_sv;
             if (version && HeVAL(version) && (version_sv = GvSV(HeVAL(version)))) {
                 if (SvROK(version_sv)) {
@@ -87,8 +104,8 @@ is_class_loaded(klass=&PL_sv_undef)
             }
         }
 
-        if (hv_exists_ent (stash, KEY_FOR(ISA), HASH_FOR(ISA))) {
-            HE *isa = hv_fetch_ent(stash, KEY_FOR(ISA), 0, HASH_FOR(ISA));
+        if (hv_exists_ent (stash, mop_ISA, 0U)) {
+            HE *isa = hv_fetch_ent(stash, mop_ISA, 0, 0U);
             if (isa && HeVAL(isa) && GvAV(HeVAL(isa)) && av_len(GvAV(HeVAL(isa))) != -1) {
                 XSRETURN_YES;
             }
index 590cd06..13dcf31 100644 (file)
@@ -8,3 +8,5 @@ BOOT:
     INSTALL_SIMPLE_READER(Method, name);
     INSTALL_SIMPLE_READER(Method, package_name);
     INSTALL_SIMPLE_READER(Method, body);
+    INSTALL_SIMPLE_READER(Method, associated_metaclass);
+    INSTALL_SIMPLE_READER(Method, original_method);
index ce8d390..79d92a2 100644 (file)
@@ -23,7 +23,7 @@ get_all_package_symbols(self, filter=TYPE_FILTER_NONE)
 
         PUTBACK;
 
-        if ( (he = hv_fetch_ent((HV *)SvRV(self), KEY_FOR(package), 0, HASH_FOR(package))) ) {
+        if ( (he = hv_fetch_ent((HV *)SvRV(self), mop_package, 0, 0U)) ) {
             stash = gv_stashsv(HeVAL(he), 0);
         }