Skip to content

Commit b46e009

Browse files
syberiabyn
authored andcommitted
Make OP_METHOD* to be of new class METHOP
Introduce a new opcode class, METHOP, which will hold class/method related info needed at runtime to improve performance of class/object method calls, then change OP_METHOD and OP_METHOD_NAMED from being UNOP/SVOP to being METHOP. Note that because OP_METHOD is a UNOP with an op_first, while OP_METHOD_NAMED is an SVOP, the first field of the METHOP structure is a union holding either op_first or op_sv. This was seen as less messy than having to introduce two new op classes. The new op class's character is '.' Nothing has changed in functionality and/or performance by this commit. It just introduces new structure which will be extended with extra fields and used in later commits. Added METHOP constructors: - newMETHOP() for method ops with dynamic method names. The only optype for this op is OP_METHOD. - newMETHOP_named() for method ops with constant method names. Optypes for this op are: OP_METHOD_NAMED (currently) and (later) OP_METHOD_SUPER, OP_METHOD_REDIR, OP_METHOD_NEXT, OP_METHOD_NEXTCAN, OP_METHOD_MAYBENEXT (This commit includes fixups by davem)
1 parent df96891 commit b46e009

23 files changed

+742
-508
lines changed

dump.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,7 @@ Perl_do_op_dump(pTHX_ I32 level, PerlIO *file, const OP *o)
962962
#ifndef USE_ITHREADS
963963
/* with ITHREADS, consts are stored in the pad, and the right pad
964964
* may not be active here, so skip */
965-
Perl_dump_indent(aTHX_ level, file, "SV = %s\n", SvPEEK(cSVOPo_sv));
965+
Perl_dump_indent(aTHX_ level, file, "SV = %s\n", SvPEEK(cMETHOPx_meth(o)));
966966
#endif
967967
break;
968968
case OP_NEXTSTATE:

embed.fnc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,11 @@ p |char* |find_script |NN const char *scriptname|bool dosearch \
471471
s |OP* |force_list |NULLOK OP* arg|bool nullit
472472
i |OP* |op_integerize |NN OP *o
473473
i |OP* |op_std_init |NN OP *o
474+
#if defined(USE_ITHREADS)
475+
i |void |op_relocate_sv |NN SV** svp|NN PADOFFSET* targp
476+
#endif
477+
i |OP* |newMETHOP_internal |I32 type|I32 flags|NULLOK OP* dynamic_meth \
478+
|NULLOK SV* const_meth
474479
: FIXME
475480
s |OP* |fold_constants |NN OP *o
476481
#endif
@@ -1029,6 +1034,8 @@ Apda |OP* |newWHENOP |NULLOK OP* cond|NN OP* block
10291034
Apda |OP* |newWHILEOP |I32 flags|I32 debuggable|NULLOK LOOP* loop \
10301035
|NULLOK OP* expr|NULLOK OP* block|NULLOK OP* cont \
10311036
|I32 has_my
1037+
Apda |OP* |newMETHOP |I32 type|I32 flags|NN OP* dynamic_meth
1038+
Apda |OP* |newMETHOP_named|I32 type|I32 flags|NN SV* const_meth
10321039
Apd |CV* |rv2cv_op_cv |NN OP *cvop|U32 flags
10331040
Apd |OP* |ck_entersub_args_list|NN OP *entersubop
10341041
Apd |OP* |ck_entersub_args_proto|NN OP *entersubop|NN GV *namegv|NN SV *protosv

embed.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,8 @@
371371
#define newLOGOP(a,b,c,d) Perl_newLOGOP(aTHX_ a,b,c,d)
372372
#define newLOOPEX(a,b) Perl_newLOOPEX(aTHX_ a,b)
373373
#define newLOOPOP(a,b,c,d) Perl_newLOOPOP(aTHX_ a,b,c,d)
374+
#define newMETHOP(a,b,c) Perl_newMETHOP(aTHX_ a,b,c)
375+
#define newMETHOP_named(a,b,c) Perl_newMETHOP_named(aTHX_ a,b,c)
374376
#define newMYSUB(a,b,c,d,e) Perl_newMYSUB(aTHX_ a,b,c,d,e)
375377
#define newNULLLIST() Perl_newNULLLIST(aTHX)
376378
#define newOP(a,b) Perl_newOP(aTHX_ a,b)
@@ -1525,6 +1527,7 @@
15251527
#define my_kid(a,b,c) S_my_kid(aTHX_ a,b,c)
15261528
#define newDEFSVOP() S_newDEFSVOP(aTHX)
15271529
#define newGIVWHENOP(a,b,c,d,e) S_newGIVWHENOP(aTHX_ a,b,c,d,e)
1530+
#define newMETHOP_internal(a,b,c,d) S_newMETHOP_internal(aTHX_ a,b,c,d)
15281531
#define new_logop(a,b,c,d) S_new_logop(aTHX_ a,b,c,d)
15291532
#define no_bareword_allowed(a) S_no_bareword_allowed(aTHX_ a)
15301533
#define no_fh_allowed(a) S_no_fh_allowed(aTHX_ a)
@@ -1543,6 +1546,9 @@
15431546
#define simplify_sort(a) S_simplify_sort(aTHX_ a)
15441547
#define too_few_arguments_pv(a,b,c) S_too_few_arguments_pv(aTHX_ a,b,c)
15451548
#define too_many_arguments_pv(a,b,c) S_too_many_arguments_pv(aTHX_ a,b,c)
1549+
# if defined(USE_ITHREADS)
1550+
#define op_relocate_sv(a,b) S_op_relocate_sv(aTHX_ a,b)
1551+
# endif
15461552
# endif
15471553
# if defined(PERL_IN_OP_C) || defined(PERL_IN_SV_C)
15481554
#define report_redefined_cv(a,b,c) Perl_report_redefined_cv(aTHX_ a,b,c)

ext/B/B.pm

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,11 @@ push @B::EXPORT_OK, (qw(minus_c ppname save_BEGINs
6969
@B::LOOP::ISA = 'B::LISTOP';
7070
@B::PMOP::ISA = 'B::LISTOP';
7171
@B::COP::ISA = 'B::OP';
72+
@B::METHOP::ISA = 'B::OP';
7273

7374
@B::SPECIAL::ISA = 'B::OBJECT';
7475

75-
@B::optype = qw(OP UNOP BINOP LOGOP LISTOP PMOP SVOP PADOP PVOP LOOP COP);
76+
@B::optype = qw(OP UNOP BINOP LOGOP LISTOP PMOP SVOP PADOP PVOP LOOP COP METHOP);
7677
# bytecode.pl contained the following comment:
7778
# Nullsv *must* come first in the following so that the condition
7879
# ($$sv == 0) can continue to be used to test (sv == Nullsv).
@@ -1065,17 +1066,17 @@ information is no longer stored directly in the hash.
10651066
=head2 OP-RELATED CLASSES
10661067
10671068
C<B::OP>, C<B::UNOP>, C<B::BINOP>, C<B::LOGOP>, C<B::LISTOP>, C<B::PMOP>,
1068-
C<B::SVOP>, C<B::PADOP>, C<B::PVOP>, C<B::LOOP>, C<B::COP>.
1069+
C<B::SVOP>, C<B::PADOP>, C<B::PVOP>, C<B::LOOP>, C<B::COP>, C<B::METHOP>.
10691070
10701071
These classes correspond in the obvious way to the underlying C
10711072
structures of similar names. The inheritance hierarchy mimics the
10721073
underlying C "inheritance":
10731074
10741075
B::OP
10751076
|
1076-
+---------------+--------+--------+-------+
1077-
| | | | |
1078-
B::UNOP B::SVOP B::PADOP B::COP B::PVOP
1077+
+----------+---------+--------+-------+---------+
1078+
| | | | | |
1079+
B::UNOP B::SVOP B::PADOP B::COP B::PVOP B::METHOP
10791080
,' `-.
10801081
/ `--.
10811082
B::BINOP B::LOGOP
@@ -1263,6 +1264,16 @@ Since perl 5.17.1
12631264
12641265
=back
12651266
1267+
=head2 B::METHOP Methods (Since Perl 5.22)
1268+
1269+
=over 4
1270+
1271+
=item first
1272+
1273+
=item meth_sv
1274+
1275+
=back
1276+
12661277
=head2 OTHER CLASSES
12671278
12681279
Perl 5.18 introduces a new class, B::PADLIST, returned by B::CV's

ext/B/B.xs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ typedef enum {
6060
OPc_PADOP, /* 8 */
6161
OPc_PVOP, /* 9 */
6262
OPc_LOOP, /* 10 */
63-
OPc_COP /* 11 */
63+
OPc_COP, /* 11 */
64+
OPc_METHOP /* 12 */
6465
} opclass;
6566

6667
static const char* const opclassnames[] = {
@@ -75,7 +76,8 @@ static const char* const opclassnames[] = {
7576
"B::PADOP",
7677
"B::PVOP",
7778
"B::LOOP",
78-
"B::COP"
79+
"B::COP",
80+
"B::METHOP"
7981
};
8082

8183
static const size_t opsizes[] = {
@@ -90,7 +92,8 @@ static const size_t opsizes[] = {
9092
sizeof(PADOP),
9193
sizeof(PVOP),
9294
sizeof(LOOP),
93-
sizeof(COP)
95+
sizeof(COP),
96+
sizeof(METHOP)
9497
};
9598

9699
#define MY_CXT_KEY "B::_guts" XS_VERSION
@@ -232,6 +235,8 @@ cc_opclass(pTHX_ const OP *o)
232235
return OPc_BASEOP;
233236
else
234237
return OPc_PVOP;
238+
case OA_METHOP:
239+
return OPc_METHOP;
235240
}
236241
warn("can't determine class of operator %s, assuming BASEOP\n",
237242
OP_NAME(o));
@@ -586,6 +591,7 @@ typedef PADOP *B__PADOP;
586591
typedef PVOP *B__PVOP;
587592
typedef LOOP *B__LOOP;
588593
typedef COP *B__COP;
594+
typedef METHOP *B__METHOP;
589595

590596
typedef SV *B__SV;
591597
typedef SV *B__IV;
@@ -735,6 +741,10 @@ struct OP_methods {
735741
{ STR_WITH_LEN("parent"), op_offset_special, 0, },/*52*/
736742
# endif
737743
#endif
744+
#if PERL_VERSION >= 21
745+
{ STR_WITH_LEN("first"), op_offset_special, 0, },/*53*/
746+
{ STR_WITH_LEN("meth_sv"), op_offset_special, 0, },/*54*/
747+
#endif
738748
};
739749

740750
#include "const-c.inc"
@@ -1012,6 +1022,8 @@ next(o)
10121022
B::OP::folded = 50
10131023
B::OP::lastsib = 51
10141024
B::OP::parent = 52
1025+
B::METHOP::first = 53
1026+
B::METHOP::meth_sv = 54
10151027
PREINIT:
10161028
SV *ret;
10171029
PPCODE:
@@ -1208,6 +1220,25 @@ next(o)
12081220
case 52: /* B::OP::parent */
12091221
ret = make_op_object(aTHX_ op_parent(o));
12101222
break;
1223+
case 53: /* B::METHOP::first */
1224+
/* METHOP struct has an op_first/op_meth_sv union
1225+
* as its first extra field. How to interpret the
1226+
* union depends on the op type. For the purposes of
1227+
* B, we treat it as a struct with both fields present,
1228+
* where one of the fields always happens to be null
1229+
* (i.e. we return NULL in preference to croaking with
1230+
* 'method not implemented').
1231+
*/
1232+
ret = make_op_object(aTHX_
1233+
o->op_type == OP_METHOD
1234+
? cMETHOPx(o)->op_u.op_first : NULL);
1235+
break;
1236+
case 54: /* B::METHOP::meth_sv */
1237+
/* see comment above about METHOP */
1238+
ret = make_sv_object(aTHX_
1239+
o->op_type == OP_METHOD
1240+
? NULL : cMETHOPx(o)->op_u.op_meth_sv);
1241+
break;
12111242
default:
12121243
croak("method %s not implemented", op_methods[ix].name);
12131244
} else {

ext/B/B/Concise.pm

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use warnings; # uses #3 and #4, since warnings uses Carp
1414

1515
use Exporter (); # use #5
1616

17-
our $VERSION = "0.993";
17+
our $VERSION = "0.994";
1818
our @ISA = qw(Exporter);
1919
our @EXPORT_OK = qw( set_style set_style_standard add_callback
2020
concise_subref concise_cv concise_main
@@ -400,7 +400,8 @@ my $lastnext; # remembers op-chain, used to insert gotos
400400

401401
my %opclass = ('OP' => "0", 'UNOP' => "1", 'BINOP' => "2", 'LOGOP' => "|",
402402
'LISTOP' => "@", 'PMOP' => "/", 'SVOP' => "\$", 'GVOP' => "*",
403-
'PVOP' => '"', 'LOOP' => "{", 'COP' => ";", 'PADOP' => "#");
403+
'PVOP' => '"', 'LOOP' => "{", 'COP' => ";", 'PADOP' => "#",
404+
'METHOP' => '.');
404405

405406
no warnings 'qw'; # "Possible attempt to put comments..."; use #7
406407
my @linenoise =
@@ -891,16 +892,26 @@ sub concise_op {
891892
elsif ($h{class} eq "SVOP" or $h{class} eq "PADOP") {
892893
unless ($h{name} eq 'aelemfast' and $op->flags & OPf_SPECIAL) {
893894
my $idx = ($h{class} eq "SVOP") ? $op->targ : $op->padix;
894-
my $preferpv = $h{name} eq "method_named";
895895
if ($h{class} eq "PADOP" or !${$op->sv}) {
896896
my $sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$idx];
897-
$h{arg} = "[" . concise_sv($sv, \%h, $preferpv) . "]";
897+
$h{arg} = "[" . concise_sv($sv, \%h, 0) . "]";
898898
$h{targarglife} = $h{targarg} = "";
899899
} else {
900-
$h{arg} = "(" . concise_sv($op->sv, \%h, $preferpv) . ")";
900+
$h{arg} = "(" . concise_sv($op->sv, \%h, 0) . ")";
901901
}
902902
}
903903
}
904+
elsif ($h{class} eq "METHOP") {
905+
if ($h{name} eq "method_named") {
906+
if (${$op->meth_sv}) {
907+
$h{arg} = "(" . concise_sv($op->meth_sv, \%h, 1) . ")";
908+
} else {
909+
my $sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$op->targ];
910+
$h{arg} = "[" . concise_sv($sv, \%h, 1) . "]";
911+
$h{targarglife} = $h{targarg} = "";
912+
}
913+
}
914+
}
904915
$h{seq} = $h{hyphseq} = seq($op);
905916
$h{seq} = "" if $h{seq} eq "-";
906917
$h{opt} = $op->opt;
@@ -1379,6 +1390,7 @@ B:: namespace that represents the ops in your Perl code.
13791390
{ LOOP An OP that holds pointers for a loop
13801391
; COP An OP that marks the start of a statement
13811392
# PADOP An OP with a GV on the pad
1393+
. METHOP An OP with method call info
13821394
13831395
=head2 OP flags abbreviations
13841396

0 commit comments

Comments
 (0)