/* compile time state of %^H. See the comment in op.c for how this is
used to recreate a hash to return from caller. */
COPHH * cop_hints_hash;
+ /* for now just a bitmask stored here.
+ If we get sufficient features this may become a pointer.
+ How these flags are stored is subject to change without
+ notice. Use the macros to test for features.
+ */
+ U32 cop_features;
};
#ifdef USE_ITHREADS
#define HINT_FEATURE_SHIFT 26
+#define FEATURE_BITWISE_BIT 0x0001
+#define FEATURE___SUB___BIT 0x0002
+#define FEATURE_MYREF_BIT 0x0004
+#define FEATURE_EVALBYTES_BIT 0x0008
+#define FEATURE_FC_BIT 0x0010
+#define FEATURE_POSTDEREF_QQ_BIT 0x0020
+#define FEATURE_REFALIASING_BIT 0x0040
+#define FEATURE_SAY_BIT 0x0080
+#define FEATURE_SIGNATURES_BIT 0x0100
+#define FEATURE_STATE_BIT 0x0200
+#define FEATURE_SWITCH_BIT 0x0400
+#define FEATURE_UNIEVAL_BIT 0x0800
+#define FEATURE_UNICODE_BIT 0x1000
+
#define FEATURE_BUNDLE_DEFAULT 0
#define FEATURE_BUNDLE_510 1
#define FEATURE_BUNDLE_511 2
((CURRENT_HINTS \
& HINT_LOCALIZE_HH) \
? Perl_feature_is_enabled(aTHX_ STR_WITH_LEN(name)) : FALSE)
+
+#define FEATURE_IS_ENABLED_MASK(mask) \
+ ((CURRENT_HINTS & HINT_LOCALIZE_HH) \
+ ? (PL_curcop->cop_features & (mask)) : FALSE)
+
/* The longest string we pass in. */
#define MAX_FEATURE_LEN (sizeof("postderef_qq")-1)
(CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_515 && \
CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_527) \
|| (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
- FEATURE_IS_ENABLED("fc")) \
+ FEATURE_IS_ENABLED_MASK(FEATURE_FC_BIT)) \
)
#define FEATURE_SAY_IS_ENABLED \
(CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_510 && \
CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_527) \
|| (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
- FEATURE_IS_ENABLED("say")) \
+ FEATURE_IS_ENABLED_MASK(FEATURE_SAY_BIT)) \
)
#define FEATURE_STATE_IS_ENABLED \
(CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_510 && \
CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_527) \
|| (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
- FEATURE_IS_ENABLED("state")) \
+ FEATURE_IS_ENABLED_MASK(FEATURE_STATE_BIT)) \
)
#define FEATURE_SWITCH_IS_ENABLED \
(CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_510 && \
CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_527) \
|| (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
- FEATURE_IS_ENABLED("switch")) \
+ FEATURE_IS_ENABLED_MASK(FEATURE_SWITCH_BIT)) \
)
#define FEATURE_BITWISE_IS_ENABLED \
( \
CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_527 \
|| (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
- FEATURE_IS_ENABLED("bitwise")) \
+ FEATURE_IS_ENABLED_MASK(FEATURE_BITWISE_BIT)) \
)
#define FEATURE_EVALBYTES_IS_ENABLED \
(CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_515 && \
CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_527) \
|| (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
- FEATURE_IS_ENABLED("evalbytes")) \
+ FEATURE_IS_ENABLED_MASK(FEATURE_EVALBYTES_BIT)) \
)
#define FEATURE_SIGNATURES_IS_ENABLED \
( \
CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
- FEATURE_IS_ENABLED("signatures") \
+ FEATURE_IS_ENABLED_MASK(FEATURE_SIGNATURES_BIT) \
)
#define FEATURE___SUB___IS_ENABLED \
(CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_515 && \
CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_527) \
|| (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
- FEATURE_IS_ENABLED("__SUB__")) \
+ FEATURE_IS_ENABLED_MASK(FEATURE___SUB___BIT)) \
)
#define FEATURE_REFALIASING_IS_ENABLED \
( \
CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
- FEATURE_IS_ENABLED("refaliasing") \
+ FEATURE_IS_ENABLED_MASK(FEATURE_REFALIASING_BIT) \
)
#define FEATURE_POSTDEREF_QQ_IS_ENABLED \
(CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_523 && \
CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_527) \
|| (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
- FEATURE_IS_ENABLED("postderef_qq")) \
+ FEATURE_IS_ENABLED_MASK(FEATURE_POSTDEREF_QQ_BIT)) \
)
#define FEATURE_UNIEVAL_IS_ENABLED \
(CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_515 && \
CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_527) \
|| (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
- FEATURE_IS_ENABLED("unieval")) \
+ FEATURE_IS_ENABLED_MASK(FEATURE_UNIEVAL_BIT)) \
)
#define FEATURE_MYREF_IS_ENABLED \
( \
CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
- FEATURE_IS_ENABLED("myref") \
+ FEATURE_IS_ENABLED_MASK(FEATURE_MYREF_BIT) \
)
#define FEATURE_UNICODE_IS_ENABLED \
(CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_511 && \
CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_527) \
|| (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \
- FEATURE_IS_ENABLED("unicode")) \
+ FEATURE_IS_ENABLED_MASK(FEATURE_UNICODE_BIT)) \
)
+#define SAVEFEATUREBITS() SAVEI32(PL_compiling.cop_features)
+
+#define CLEARFEATUREBITS() (PL_compiling.cop_features = 0)
+
+#define STOREFEATUREBITSHH(hh) \
+ (hv_stores((hh), "feature/bits", newSVuv(PL_compiling.cop_features)))
+
+#define FETCHFEATUREBITSHH(hh) \
+ STMT_START { \
+ SV **fbsv = hv_fetchs((hh), "feature/bits", FALSE); \
+ PL_compiling.cop_features = fbsv ? SvUV(*fbsv) : 0; \
+ } STMT_END
+
#endif /* PERL_CORE or PERL_EXT */
#ifdef PERL_IN_OP_C
if (memEQs(name, len, "\005NCODING"))
goto magicalize;
break;
+ case '\006':
+ if (memEQs(name, len, "\006EATURE_BITS"))
+ goto magicalize;
+ break;
case '\007': /* $^GLOBAL_PHASE */
if (memEQs(name, len, "\007LOBAL_PHASE"))
goto ro_magicalize;
package feature;
-our $VERSION = '1.55';
+our $VERSION = '1.56';
our %feature = (
fc => 'feature_fc',
unicode_strings => 'feature_unicode',
);
+
+my %feature_bits = (
+ bitwise => 0x0001,
+ current_sub => 0x0002,
+ declared_refs => 0x0004,
+ evalbytes => 0x0008,
+ fc => 0x0010,
+ postderef_qq => 0x0020,
+ refaliasing => 0x0040,
+ say => 0x0080,
+ signatures => 0x0100,
+ state => 0x0200,
+ switch => 0x0400,
+ unicode_eval => 0x0800,
+ unicode_strings => 0x1000,
+);
+
our %feature_bundle = (
"5.10" => [qw(say state switch)],
"5.11" => [qw(say state switch unicode_strings)],
my $import = shift;
my $bundle_number = $^H & $hint_mask;
my $features = $bundle_number != $hint_mask
- && $feature_bundle{$hint_bundles[$bundle_number >> $hint_shift]};
+ && $feature_bundle{$hint_bundles[$bundle_number >> $hint_shift]};
+ my $bits = ${^FEATURE_BITS};
if ($features) {
# Features are enabled implicitly via bundle hints.
# Delete any keys that may be left over from last time.
delete @^H{ values(%feature) };
+ $bits = 0;
$^H |= $hint_mask;
for (@$features) {
$^H{$feature{$_}} = 1;
+ $bits |= $feature_bits{$_};
$^H |= $hint_uni8bit if $_ eq 'unicode_strings';
}
}
}
if ($import) {
$^H{$feature{$name}} = 1;
+ $bits |= $feature_bits{$name};
$^H |= $hint_uni8bit if $name eq 'unicode_strings';
} else {
delete $^H{$feature{$name}};
+ $bits &= ~$feature_bits{$name};
$^H &= ~ $hint_uni8bit if $name eq 'unicode_strings';
}
}
+ ${^FEATURE_BITS} = $bits;
}
sub unknown_feature {
break;
case '\006': /* ^F */
- sv_setiv(sv, (IV)PL_maxsysfd);
+ if (nextchar == '\0') {
+ sv_setiv(sv, (IV)PL_maxsysfd);
+ }
+ else if (strEQ(remaining, "EATURE_BITS")) {
+ sv_setuv(sv, PL_compiling.cop_features);
+ }
break;
case '\007': /* ^GLOBAL_PHASE */
if (strEQ(remaining, "LOBAL_PHASE")) {
Perl_croak(aTHX_ "${^ENCODING} is no longer supported");
break;
case '\006': /* ^F */
- PL_maxsysfd = SvIV(sv);
+ if (mg->mg_ptr[1] == '\0') {
+ PL_maxsysfd = SvIV(sv);
+ }
+ else if (strEQ(mg->mg_ptr + 1, "EATURE_BITS")) {
+ PL_compiling.cop_features = SvUV(sv);
+ }
break;
case '\010': /* ^H */
{
if ((PL_hints & HINT_LOCALIZE_HH) != 0
&& !(o->op_private & OPpEVAL_COPHH) && GvHV(PL_hintgv)) {
/* Store a copy of %^H that pp_entereval can pick up. */
- OP *hhop = newSVOP(OP_HINTSEVAL, 0,
- MUTABLE_SV(hv_copy_hints_hv(GvHV(PL_hintgv))));
+ HV *hh = hv_copy_hints_hv(GvHV(PL_hintgv));
+ OP *hhop;
+ STOREFEATUREBITSHH(hh);
+ hhop = newSVOP(OP_HINTSEVAL, 0, MUTABLE_SV(hh));
/* append hhop to only child */
op_sibling_splice(o, cUNOPo->op_first, 0, hhop);
#include "EXTERN.h"
#define PERL_IN_PP_CTL_C
#include "perl.h"
+#include "feature.h"
#define RUN_PP_CATCHABLY(thispp) \
STMT_START { if (CATCH_GET) return docatch(thispp); } STMT_END
if (clear_hints) {
PL_hints = 0;
hv_clear(GvHV(PL_hintgv));
+ CLEARFEATUREBITS();
}
else {
PL_hints = saveop->op_private & OPpEVAL_COPHH
/* SAVEHINTS created a new HV in PL_hintgv, which we need to GC */
SvREFCNT_dec(GvHV(PL_hintgv));
GvHV(PL_hintgv) = hh;
+ FETCHFEATUREBITSHH(hh);
}
}
SAVECOMPILEWARNINGS();
###########################################################################
# More data generated from the above
+if (keys %feature > 32) {
+ die "cop_features only has room for 32 features";
+}
+
+my %feature_bits;
+my $mask = 1;
+for my $feature (sort keys %feature) {
+ $feature_bits{$feature} = $mask;
+ $mask <<= 1;
+}
+
for (keys %feature_bundle) {
next unless /^5\.(\d*[13579])\z/;
$feature_bundle{"5.".($1+1)} ||= $feature_bundle{$_};
}
print $pm ");\n\n";
+print $pm "\nmy %feature_bits = (\n";
+for (sort keys %feature_bits) {
+ printf $pm " %-*s => %#06x,\n", $width, $_, $feature_bits{$_};
+}
+print $pm ");\n\n";
+
print $pm "our %feature_bundle = (\n";
-$width = length longest values %UniqueBundles;
+my $bund_width = length longest values %UniqueBundles;
for( sort { $UniqueBundles{$a} cmp $UniqueBundles{$b} }
keys %UniqueBundles ) {
my $bund = $UniqueBundles{$_};
- print $pm qq' "$bund"' . " "x($width-length $bund)
+ print $pm qq' "$bund"' . " "x($bund_width-length $bund)
. qq' => [qw($_)],\n';
}
print $pm ");\n\n";
EOH
+for (sort keys %feature_bits) {
+ printf $h "#define FEATURE_%s_BIT%*s %#06x\n", uc($feature{$_}),
+ $width-length($feature{$_}), "", $feature_bits{$_};
+}
+print $h "\n";
+
my $count;
for (@HintedBundles) {
(my $key = uc) =~ y/.//d;
((CURRENT_HINTS \
& HINT_LOCALIZE_HH) \
? Perl_feature_is_enabled(aTHX_ STR_WITH_LEN(name)) : FALSE)
+
+#define FEATURE_IS_ENABLED_MASK(mask) \
+ ((CURRENT_HINTS & HINT_LOCALIZE_HH) \
+ ? (PL_curcop->cop_features & (mask)) : FALSE)
+
/* The longest string we pass in. */
EOH
( \\
CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_$last \\
|| (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \\
- FEATURE_IS_ENABLED("$name")) \\
+ FEATURE_ENABLED_MASK(FEATURE_\L$name\E_BIT)) \\
)
EOI
(CURRENT_FEATURE_BUNDLE >= FEATURE_BUNDLE_$first && \\
CURRENT_FEATURE_BUNDLE <= FEATURE_BUNDLE_$last) \\
|| (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \\
- FEATURE_IS_ENABLED("$name")) \\
+ FEATURE_IS_ENABLED_MASK(FEATURE_\U$name\E_BIT)) \\
)
EOH3
( \\
CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_$first \\
|| (CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \\
- FEATURE_IS_ENABLED("$name")) \\
+ FEATURE_IS_ENABLED_MASK(FEATURE_\U$name\E_BIT)) \\
)
EOH4
#define FEATURE_$NAME\_IS_ENABLED \\
( \\
CURRENT_FEATURE_BUNDLE == FEATURE_BUNDLE_CUSTOM && \\
- FEATURE_IS_ENABLED("$name") \\
+ FEATURE_IS_ENABLED_MASK(FEATURE_\U$name\E_BIT) \\
)
EOH5
print $h <<EOH;
+#define SAVEFEATUREBITS() SAVEI32(PL_compiling.cop_features)
+
+#define CLEARFEATUREBITS() (PL_compiling.cop_features = 0)
+
+#define STOREFEATUREBITSHH(hh) \\
+ (hv_stores((hh), "feature/bits", newSVuv(PL_compiling.cop_features)))
+
+#define FETCHFEATUREBITSHH(hh) \\
+ STMT_START { \\
+ SV **fbsv = hv_fetchs((hh), "feature/bits", FALSE); \\
+ PL_compiling.cop_features = fbsv ? SvUV(*fbsv) : 0; \\
+ } STMT_END
+
#endif /* PERL_CORE or PERL_EXT */
#ifdef PERL_IN_OP_C
__END__
package feature;
-our $VERSION = '1.55';
+our $VERSION = '1.56';
FEATURES
my $import = shift;
my $bundle_number = $^H & $hint_mask;
my $features = $bundle_number != $hint_mask
- && $feature_bundle{$hint_bundles[$bundle_number >> $hint_shift]};
+ && $feature_bundle{$hint_bundles[$bundle_number >> $hint_shift]};
+ my $bits = ${^FEATURE_BITS};
if ($features) {
# Features are enabled implicitly via bundle hints.
# Delete any keys that may be left over from last time.
delete @^H{ values(%feature) };
+ $bits = 0;
$^H |= $hint_mask;
for (@$features) {
$^H{$feature{$_}} = 1;
+ $bits |= $feature_bits{$_};
$^H |= $hint_uni8bit if $_ eq 'unicode_strings';
}
}
}
if ($import) {
$^H{$feature{$name}} = 1;
+ $bits |= $feature_bits{$name};
$^H |= $hint_uni8bit if $name eq 'unicode_strings';
} else {
delete $^H{$feature{$name}};
+ $bits &= ~$feature_bits{$name};
$^H &= ~ $hint_uni8bit if $name eq 'unicode_strings';
}
}
+ ${^FEATURE_BITS} = $bits;
}
sub unknown_feature {
#include "EXTERN.h"
#define PERL_IN_SCOPE_C
#include "perl.h"
+#include "feature.h"
SV**
Perl_stack_grow(pTHX_ SV **sp, SV **p, SSize_t n)
save_pushptri32ptr(oldhh, PL_hints, save_cophh, SAVEt_HINTS);
GvHV(PL_hintgv) = NULL; /* in case copying dies */
GvHV(PL_hintgv) = hv_copy_hints_hv(oldhh);
+ SAVEFEATUREBITS();
} else {
save_pushi32ptr(PL_hints, save_cophh, SAVEt_HINTS);
}