| 1 | # Bytecode.pm |
| 2 | # |
| 3 | # Copyright (c) 1996-1998 Malcolm Beattie |
| 4 | # |
| 5 | # You may distribute under the terms of either the GNU General Public |
| 6 | # License or the Artistic License, as specified in the README file. |
| 7 | # |
| 8 | package B::Bytecode; |
| 9 | |
| 10 | our $VERSION = '1.00'; |
| 11 | |
| 12 | use strict; |
| 13 | use Carp; |
| 14 | use B qw(main_cv main_root main_start comppadlist |
| 15 | class peekop walkoptree svref_2object cstring walksymtable |
| 16 | init_av begin_av end_av |
| 17 | SVf_POK SVp_POK SVf_IOK SVp_IOK SVf_NOK SVp_NOK |
| 18 | SVf_READONLY GVf_IMPORTED_AV GVf_IMPORTED_CV GVf_IMPORTED_HV |
| 19 | GVf_IMPORTED_SV SVTYPEMASK |
| 20 | ); |
| 21 | use B::Asmdata qw(@optype @specialsv_name); |
| 22 | use B::Assembler qw(newasm endasm assemble); |
| 23 | |
| 24 | my %optype_enum; |
| 25 | my $i; |
| 26 | for ($i = 0; $i < @optype; $i++) { |
| 27 | $optype_enum{$optype[$i]} = $i; |
| 28 | } |
| 29 | |
| 30 | # Following is SVf_POK|SVp_POK |
| 31 | # XXX Shouldn't be hardwired |
| 32 | sub POK () { SVf_POK|SVp_POK } |
| 33 | |
| 34 | # Following is SVf_IOK|SVp_IOK |
| 35 | # XXX Shouldn't be hardwired |
| 36 | sub IOK () { SVf_IOK|SVp_IOK } |
| 37 | |
| 38 | # Following is SVf_NOK|SVp_NOK |
| 39 | # XXX Shouldn't be hardwired |
| 40 | sub NOK () { SVf_NOK|SVp_NOK } |
| 41 | |
| 42 | # nonexistant flags (see B::GV::bytecode for usage) |
| 43 | sub GVf_IMPORTED_IO () { 0; } |
| 44 | sub GVf_IMPORTED_FORM () { 0; } |
| 45 | |
| 46 | my ($verbose, $no_assemble, $debug_bc, $debug_cv); |
| 47 | my @packages; # list of packages to compile |
| 48 | |
| 49 | sub asm (@) { # print replacement that knows about assembling |
| 50 | if ($no_assemble) { |
| 51 | print @_; |
| 52 | } else { |
| 53 | my $buf = join '', @_; |
| 54 | assemble($_) for (split /\n/, $buf); |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | sub asmf (@) { # printf replacement that knows about assembling |
| 59 | if ($no_assemble) { |
| 60 | printf shift(), @_; |
| 61 | } else { |
| 62 | my $format = shift; |
| 63 | my $buf = sprintf $format, @_; |
| 64 | assemble($_) for (split /\n/, $buf); |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | # Optimisation options. On the command line, use hyphens instead of |
| 69 | # underscores for compatibility with gcc-style options. We use |
| 70 | # underscores here because they are OK in (strict) barewords. |
| 71 | my ($compress_nullops, $omit_seq, $bypass_nullops); |
| 72 | my %optimise = (compress_nullops => \$compress_nullops, |
| 73 | omit_sequence_numbers => \$omit_seq, |
| 74 | bypass_nullops => \$bypass_nullops); |
| 75 | |
| 76 | my $strip_syntree; # this is left here in case stripping the |
| 77 | # syntree ever becomes safe again |
| 78 | # -- BKS, June 2000 |
| 79 | |
| 80 | my $nextix = 0; |
| 81 | my %symtable; # maps object addresses to object indices. |
| 82 | # Filled in at allocation (newsv/newop) time. |
| 83 | |
| 84 | my %saved; # maps object addresses (for SVish classes) to "saved yet?" |
| 85 | # flag. Set at FOO::bytecode time usually by SV::bytecode. |
| 86 | # Manipulated via saved(), mark_saved(), unmark_saved(). |
| 87 | |
| 88 | my %strtable; # maps shared strings to object indices |
| 89 | # Filled in at allocation (pvix) time |
| 90 | |
| 91 | my $svix = -1; # we keep track of when the sv register contains an element |
| 92 | # of the object table to avoid unnecessary repeated |
| 93 | # consecutive ldsv instructions. |
| 94 | |
| 95 | my $opix = -1; # Ditto for the op register. |
| 96 | |
| 97 | sub ldsv { |
| 98 | my $ix = shift; |
| 99 | if ($ix != $svix) { |
| 100 | asm "ldsv $ix\n"; |
| 101 | $svix = $ix; |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | sub stsv { |
| 106 | my $ix = shift; |
| 107 | asm "stsv $ix\n"; |
| 108 | $svix = $ix; |
| 109 | } |
| 110 | |
| 111 | sub set_svix { |
| 112 | $svix = shift; |
| 113 | } |
| 114 | |
| 115 | sub ldop { |
| 116 | my $ix = shift; |
| 117 | if ($ix != $opix) { |
| 118 | asm "ldop $ix\n"; |
| 119 | $opix = $ix; |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | sub stop { |
| 124 | my $ix = shift; |
| 125 | asm "stop $ix\n"; |
| 126 | $opix = $ix; |
| 127 | } |
| 128 | |
| 129 | sub set_opix { |
| 130 | $opix = shift; |
| 131 | } |
| 132 | |
| 133 | sub pvstring { |
| 134 | my $str = shift; |
| 135 | if (defined($str)) { |
| 136 | return cstring($str . "\0"); |
| 137 | } else { |
| 138 | return '""'; |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | sub nv { |
| 143 | # print full precision |
| 144 | my $str = sprintf "%.40f", $_[0]; |
| 145 | $str =~ s/0+$//; # remove trailing zeros |
| 146 | $str =~ s/\.$/.0/; |
| 147 | return $str; |
| 148 | } |
| 149 | |
| 150 | sub saved { $saved{${$_[0]}} } |
| 151 | sub mark_saved { $saved{${$_[0]}} = 1 } |
| 152 | sub unmark_saved { $saved{${$_[0]}} = 0 } |
| 153 | |
| 154 | sub debug { $debug_bc = shift } |
| 155 | |
| 156 | sub pvix { # save a shared PV (mainly for COPs) |
| 157 | return $strtable{$_[0]} if defined($strtable{$_[0]}); |
| 158 | asmf "newpv %s\n", pvstring($_[0]); |
| 159 | my $ix = $nextix++; |
| 160 | $strtable{$_[0]} = $ix; |
| 161 | asmf "stpv %d\n", $ix; |
| 162 | return $ix; |
| 163 | } |
| 164 | |
| 165 | sub B::OBJECT::nyi { |
| 166 | my $obj = shift; |
| 167 | warn sprintf("bytecode save method for %s (0x%x) not yet implemented\n", |
| 168 | class($obj), $$obj); |
| 169 | } |
| 170 | |
| 171 | # |
| 172 | # objix may stomp on the op register (for op objects) |
| 173 | # or the sv register (for SV objects) |
| 174 | # |
| 175 | sub B::OBJECT::objix { |
| 176 | my $obj = shift; |
| 177 | my $ix = $symtable{$$obj}; |
| 178 | if (defined($ix)) { |
| 179 | return $ix; |
| 180 | } else { |
| 181 | $obj->newix($nextix); |
| 182 | return $symtable{$$obj} = $nextix++; |
| 183 | } |
| 184 | } |
| 185 | |
| 186 | sub B::SV::newix { |
| 187 | my ($sv, $ix) = @_; |
| 188 | asmf "newsv %d\t# %s\n", $sv->FLAGS & SVTYPEMASK, class($sv); |
| 189 | stsv($ix); |
| 190 | } |
| 191 | |
| 192 | sub B::GV::newix { |
| 193 | my ($gv, $ix) = @_; |
| 194 | my $gvname = $gv->NAME; |
| 195 | my $name = cstring($gv->STASH->NAME . "::" . $gvname); |
| 196 | asm "gv_fetchpv $name\n"; |
| 197 | stsv($ix); |
| 198 | } |
| 199 | |
| 200 | sub B::HV::newix { |
| 201 | my ($hv, $ix) = @_; |
| 202 | my $name = $hv->NAME; |
| 203 | if ($name) { |
| 204 | # It's a stash |
| 205 | asmf "gv_stashpv %s\n", cstring($name); |
| 206 | stsv($ix); |
| 207 | } else { |
| 208 | # It's an ordinary HV. Fall back to ordinary newix method |
| 209 | $hv->B::SV::newix($ix); |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | sub B::SPECIAL::newix { |
| 214 | my ($sv, $ix) = @_; |
| 215 | # Special case. $$sv is not the address of the SV but an |
| 216 | # index into svspecialsv_list. |
| 217 | asmf "ldspecsv $$sv\t# %s\n", $specialsv_name[$$sv]; |
| 218 | stsv($ix); |
| 219 | } |
| 220 | |
| 221 | sub B::OP::newix { |
| 222 | my ($op, $ix) = @_; |
| 223 | my $class = class($op); |
| 224 | my $typenum = $optype_enum{$class}; |
| 225 | croak("OP::newix: can't understand class $class") unless defined($typenum); |
| 226 | asm "newop $typenum\t# $class\n"; |
| 227 | stop($ix); |
| 228 | } |
| 229 | |
| 230 | sub B::OP::walkoptree_debug { |
| 231 | my $op = shift; |
| 232 | warn(sprintf("walkoptree: %s\n", peekop($op))); |
| 233 | } |
| 234 | |
| 235 | sub B::OP::bytecode { |
| 236 | my $op = shift; |
| 237 | my $next = $op->next; |
| 238 | my $nextix; |
| 239 | my $sibix = $op->sibling->objix unless $strip_syntree; |
| 240 | my $ix = $op->objix; |
| 241 | my $type = $op->type; |
| 242 | |
| 243 | if ($bypass_nullops) { |
| 244 | $next = $next->next while $$next && $next->type == 0; |
| 245 | } |
| 246 | $nextix = $next->objix; |
| 247 | |
| 248 | asmf "# %s\n", peekop($op) if $debug_bc; |
| 249 | ldop($ix); |
| 250 | asm "op_next $nextix\n"; |
| 251 | asm "op_sibling $sibix\n" unless $strip_syntree; |
| 252 | asmf "op_type %s\t# %d\n", "pp_" . $op->name, $type; |
| 253 | asmf("op_seq %d\n", $op->seq) unless $omit_seq; |
| 254 | if ($type || !$compress_nullops) { |
| 255 | asmf "op_targ %d\nop_flags 0x%x\nop_private 0x%x\n", |
| 256 | $op->targ, $op->flags, $op->private; |
| 257 | } |
| 258 | } |
| 259 | |
| 260 | sub B::UNOP::bytecode { |
| 261 | my $op = shift; |
| 262 | my $firstix = $op->first->objix unless $strip_syntree; |
| 263 | $op->B::OP::bytecode; |
| 264 | if (($op->type || !$compress_nullops) && !$strip_syntree) { |
| 265 | asm "op_first $firstix\n"; |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | sub B::LOGOP::bytecode { |
| 270 | my $op = shift; |
| 271 | my $otherix = $op->other->objix; |
| 272 | $op->B::UNOP::bytecode; |
| 273 | asm "op_other $otherix\n"; |
| 274 | } |
| 275 | |
| 276 | sub B::SVOP::bytecode { |
| 277 | my $op = shift; |
| 278 | my $sv = $op->sv; |
| 279 | my $svix = $sv->objix; |
| 280 | $op->B::OP::bytecode; |
| 281 | asm "op_sv $svix\n"; |
| 282 | $sv->bytecode; |
| 283 | } |
| 284 | |
| 285 | sub B::PADOP::bytecode { |
| 286 | my $op = shift; |
| 287 | my $padix = $op->padix; |
| 288 | $op->B::OP::bytecode; |
| 289 | asm "op_padix $padix\n"; |
| 290 | } |
| 291 | |
| 292 | sub B::PVOP::bytecode { |
| 293 | my $op = shift; |
| 294 | my $pv = $op->pv; |
| 295 | $op->B::OP::bytecode; |
| 296 | # |
| 297 | # This would be easy except that OP_TRANS uses a PVOP to store an |
| 298 | # endian-dependent array of 256 shorts instead of a plain string. |
| 299 | # |
| 300 | if ($op->name eq "trans") { |
| 301 | my @shorts = unpack("s256", $pv); # assembler handles endianness |
| 302 | asm "op_pv_tr ", join(",", @shorts), "\n"; |
| 303 | } else { |
| 304 | asmf "newpv %s\nop_pv\n", pvstring($pv); |
| 305 | } |
| 306 | } |
| 307 | |
| 308 | sub B::BINOP::bytecode { |
| 309 | my $op = shift; |
| 310 | my $lastix = $op->last->objix unless $strip_syntree; |
| 311 | $op->B::UNOP::bytecode; |
| 312 | if (($op->type || !$compress_nullops) && !$strip_syntree) { |
| 313 | asm "op_last $lastix\n"; |
| 314 | } |
| 315 | } |
| 316 | |
| 317 | sub B::LOOP::bytecode { |
| 318 | my $op = shift; |
| 319 | my $redoopix = $op->redoop->objix; |
| 320 | my $nextopix = $op->nextop->objix; |
| 321 | my $lastopix = $op->lastop->objix; |
| 322 | $op->B::LISTOP::bytecode; |
| 323 | asm "op_redoop $redoopix\nop_nextop $nextopix\nop_lastop $lastopix\n"; |
| 324 | } |
| 325 | |
| 326 | sub B::COP::bytecode { |
| 327 | my $op = shift; |
| 328 | my $file = $op->file; |
| 329 | my $line = $op->line; |
| 330 | if ($debug_bc) { # do this early to aid debugging |
| 331 | asmf "# line %s:%d\n", $file, $line; |
| 332 | } |
| 333 | my $stashpv = $op->stashpv; |
| 334 | my $warnings = $op->warnings; |
| 335 | my $warningsix = $warnings->objix; |
| 336 | my $labelix = pvix($op->label); |
| 337 | my $stashix = pvix($stashpv); |
| 338 | my $fileix = pvix($file); |
| 339 | $warnings->bytecode; |
| 340 | $op->B::OP::bytecode; |
| 341 | asmf <<"EOT", $labelix, $stashix, $op->cop_seq, $fileix, $op->arybase; |
| 342 | cop_label %d |
| 343 | cop_stashpv %d |
| 344 | cop_seq %d |
| 345 | cop_file %d |
| 346 | cop_arybase %d |
| 347 | cop_line $line |
| 348 | cop_warnings $warningsix |
| 349 | EOT |
| 350 | } |
| 351 | |
| 352 | sub B::PMOP::bytecode { |
| 353 | my $op = shift; |
| 354 | my $replroot = $op->pmreplroot; |
| 355 | my $replrootix = $replroot->objix; |
| 356 | my $replstartix = $op->pmreplstart->objix; |
| 357 | my $opname = $op->name; |
| 358 | # pmnext is corrupt in some PMOPs (see misc.t for example) |
| 359 | #my $pmnextix = $op->pmnext->objix; |
| 360 | |
| 361 | if ($$replroot) { |
| 362 | # OP_PUSHRE (a mutated version of OP_MATCH for the regexp |
| 363 | # argument to a split) stores a GV in op_pmreplroot instead |
| 364 | # of a substitution syntax tree. We don't want to walk that... |
| 365 | if ($opname eq "pushre") { |
| 366 | $replroot->bytecode; |
| 367 | } else { |
| 368 | walkoptree($replroot, "bytecode"); |
| 369 | } |
| 370 | } |
| 371 | $op->B::LISTOP::bytecode; |
| 372 | if ($opname eq "pushre") { |
| 373 | asmf "op_pmreplrootgv $replrootix\n"; |
| 374 | } else { |
| 375 | asm "op_pmreplroot $replrootix\nop_pmreplstart $replstartix\n"; |
| 376 | } |
| 377 | my $re = pvstring($op->precomp); |
| 378 | # op_pmnext omitted since a perl bug means it's sometime corrupt |
| 379 | asmf <<"EOT", $op->pmflags, $op->pmpermflags; |
| 380 | op_pmflags 0x%x |
| 381 | op_pmpermflags 0x%x |
| 382 | newpv $re |
| 383 | pregcomp |
| 384 | EOT |
| 385 | } |
| 386 | |
| 387 | sub B::SV::bytecode { |
| 388 | my $sv = shift; |
| 389 | return if saved($sv); |
| 390 | my $ix = $sv->objix; |
| 391 | my $refcnt = $sv->REFCNT; |
| 392 | my $flags = sprintf("0x%x", $sv->FLAGS); |
| 393 | ldsv($ix); |
| 394 | asm "sv_refcnt $refcnt\nsv_flags $flags\n"; |
| 395 | mark_saved($sv); |
| 396 | } |
| 397 | |
| 398 | sub B::PV::bytecode { |
| 399 | my $sv = shift; |
| 400 | return if saved($sv); |
| 401 | $sv->B::SV::bytecode; |
| 402 | asmf("newpv %s\nxpv\n", pvstring($sv->PV)) if $sv->FLAGS & POK; |
| 403 | } |
| 404 | |
| 405 | sub B::IV::bytecode { |
| 406 | my $sv = shift; |
| 407 | return if saved($sv); |
| 408 | my $iv = $sv->IVX; |
| 409 | $sv->B::SV::bytecode; |
| 410 | asmf "%s $iv\n", $sv->needs64bits ? "xiv64" : "xiv32" if $sv->FLAGS & IOK; # could be PVNV |
| 411 | } |
| 412 | |
| 413 | sub B::NV::bytecode { |
| 414 | my $sv = shift; |
| 415 | return if saved($sv); |
| 416 | $sv->B::SV::bytecode; |
| 417 | asmf "xnv %s\n", nv($sv->NVX); |
| 418 | } |
| 419 | |
| 420 | sub B::RV::bytecode { |
| 421 | my $sv = shift; |
| 422 | return if saved($sv); |
| 423 | my $rv = $sv->RV; |
| 424 | my $rvix = $rv->objix; |
| 425 | $rv->bytecode; |
| 426 | $sv->B::SV::bytecode; |
| 427 | asm "xrv $rvix\n"; |
| 428 | } |
| 429 | |
| 430 | sub B::PVIV::bytecode { |
| 431 | my $sv = shift; |
| 432 | return if saved($sv); |
| 433 | my $iv = $sv->IVX; |
| 434 | $sv->B::PV::bytecode; |
| 435 | asmf "%s $iv\n", $sv->needs64bits ? "xiv64" : "xiv32"; |
| 436 | } |
| 437 | |
| 438 | sub B::PVNV::bytecode { |
| 439 | my $sv = shift; |
| 440 | my $flag = shift || 0; |
| 441 | # The $flag argument is passed through PVMG::bytecode by BM::bytecode |
| 442 | # and AV::bytecode and indicates special handling. $flag = 1 is used by |
| 443 | # BM::bytecode and means that we should ensure we save the whole B-M |
| 444 | # table. It consists of 257 bytes (256 char array plus a final \0) |
| 445 | # which follow the ordinary PV+\0 and the 257 bytes are *not* reflected |
| 446 | # in SvCUR. $flag = 2 is used by AV::bytecode and means that we only |
| 447 | # call SV::bytecode instead of saving PV and calling NV::bytecode since |
| 448 | # PV/NV/IV stuff is different for AVs. |
| 449 | return if saved($sv); |
| 450 | if ($flag == 2) { |
| 451 | $sv->B::SV::bytecode; |
| 452 | } else { |
| 453 | my $pv = $sv->PV; |
| 454 | $sv->B::IV::bytecode; |
| 455 | asmf "xnv %s\n", nv($sv->NVX); |
| 456 | if ($flag == 1) { |
| 457 | $pv .= "\0" . $sv->TABLE; |
| 458 | asmf "newpv %s\npv_cur %d\nxpv\n", pvstring($pv),length($pv)-257; |
| 459 | } else { |
| 460 | asmf("newpv %s\nxpv\n", pvstring($pv)) if $sv->FLAGS & POK; |
| 461 | } |
| 462 | } |
| 463 | } |
| 464 | |
| 465 | sub B::PVMG::bytecode { |
| 466 | my ($sv, $flag) = @_; |
| 467 | # See B::PVNV::bytecode for an explanation of $flag. |
| 468 | return if saved($sv); |
| 469 | # XXX We assume SvSTASH is already saved and don't save it later ourselves |
| 470 | my $stashix = $sv->SvSTASH->objix; |
| 471 | my @mgchain = $sv->MAGIC; |
| 472 | my (@mgobjix, $mg); |
| 473 | # |
| 474 | # We need to traverse the magic chain and get objix for each OBJ |
| 475 | # field *before* we do B::PVNV::bytecode since objix overwrites |
| 476 | # the sv register. However, we need to write the magic-saving |
| 477 | # bytecode *after* B::PVNV::bytecode since sv isn't initialised |
| 478 | # to refer to $sv until then. |
| 479 | # |
| 480 | @mgobjix = map($_->OBJ->objix, @mgchain); |
| 481 | $sv->B::PVNV::bytecode($flag); |
| 482 | asm "xmg_stash $stashix\n"; |
| 483 | foreach $mg (@mgchain) { |
| 484 | asmf "sv_magic %s\nmg_obj %d\nnewpv %s\nmg_pv\n", |
| 485 | cstring($mg->TYPE), shift(@mgobjix), pvstring($mg->PTR); |
| 486 | } |
| 487 | } |
| 488 | |
| 489 | sub B::PVLV::bytecode { |
| 490 | my $sv = shift; |
| 491 | return if saved($sv); |
| 492 | $sv->B::PVMG::bytecode; |
| 493 | asmf <<'EOT', $sv->TARGOFF, $sv->TARGLEN, cstring($sv->TYPE); |
| 494 | xlv_targoff %d |
| 495 | xlv_targlen %d |
| 496 | xlv_type %s |
| 497 | EOT |
| 498 | } |
| 499 | |
| 500 | sub B::BM::bytecode { |
| 501 | my $sv = shift; |
| 502 | return if saved($sv); |
| 503 | # See PVNV::bytecode for an explanation of what the argument does |
| 504 | $sv->B::PVMG::bytecode(1); |
| 505 | asmf "xbm_useful %d\nxbm_previous %d\nxbm_rare %d\n", |
| 506 | $sv->USEFUL, $sv->PREVIOUS, $sv->RARE; |
| 507 | } |
| 508 | |
| 509 | sub empty_gv { # is a GV empty except for imported stuff? |
| 510 | my $gv = shift; |
| 511 | |
| 512 | return 0 if ($gv->SV->FLAGS & SVTYPEMASK); # sv not SVt_NULL |
| 513 | my @subfield_names = qw(AV HV CV FORM IO); |
| 514 | @subfield_names = grep {; |
| 515 | no strict 'refs'; |
| 516 | !($gv->GvFLAGS & ${\"GVf_IMPORTED_$_"}->()) && ${$gv->$_()}; |
| 517 | } @subfield_names; |
| 518 | return scalar @subfield_names; |
| 519 | } |
| 520 | |
| 521 | sub B::GV::bytecode { |
| 522 | my $gv = shift; |
| 523 | return if saved($gv); |
| 524 | return unless grep { $_ eq $gv->STASH->NAME; } @packages; |
| 525 | return if $gv->NAME =~ m/^\(/; # ignore overloads - they'll be rebuilt |
| 526 | my $ix = $gv->objix; |
| 527 | mark_saved($gv); |
| 528 | ldsv($ix); |
| 529 | asmf <<"EOT", $gv->FLAGS, $gv->GvFLAGS; |
| 530 | sv_flags 0x%x |
| 531 | xgv_flags 0x%x |
| 532 | EOT |
| 533 | my $refcnt = $gv->REFCNT; |
| 534 | asmf("sv_refcnt_add %d\n", $refcnt - 1) if $refcnt > 1; |
| 535 | return if $gv->is_empty; |
| 536 | asmf <<"EOT", $gv->LINE, pvix($gv->FILE); |
| 537 | gp_line %d |
| 538 | gp_file %d |
| 539 | EOT |
| 540 | my $gvname = $gv->NAME; |
| 541 | my $name = cstring($gv->STASH->NAME . "::" . $gvname); |
| 542 | my $egv = $gv->EGV; |
| 543 | my $egvix = $egv->objix; |
| 544 | my $gvrefcnt = $gv->GvREFCNT; |
| 545 | asmf("gp_refcnt_add %d\n", $gvrefcnt - 1) if $gvrefcnt > 1; |
| 546 | if ($gvrefcnt > 1 && $ix != $egvix) { |
| 547 | asm "gp_share $egvix\n"; |
| 548 | } else { |
| 549 | if ($gvname !~ /^([^A-Za-z]|STDIN|STDOUT|STDERR|ARGV|SIG|ENV)$/) { |
| 550 | my $i; |
| 551 | my @subfield_names = qw(SV AV HV CV FORM IO); |
| 552 | @subfield_names = grep {; |
| 553 | no strict 'refs'; |
| 554 | !($gv->GvFLAGS & ${\"GVf_IMPORTED_$_"}->()); |
| 555 | } @subfield_names; |
| 556 | my @subfields = map($gv->$_(), @subfield_names); |
| 557 | my @ixes = map($_->objix, @subfields); |
| 558 | # Reset sv register for $gv |
| 559 | ldsv($ix); |
| 560 | for ($i = 0; $i < @ixes; $i++) { |
| 561 | asmf "gp_%s %d\n", lc($subfield_names[$i]), $ixes[$i]; |
| 562 | } |
| 563 | # Now save all the subfields |
| 564 | my $sv; |
| 565 | foreach $sv (@subfields) { |
| 566 | $sv->bytecode; |
| 567 | } |
| 568 | } |
| 569 | } |
| 570 | } |
| 571 | |
| 572 | sub B::HV::bytecode { |
| 573 | my $hv = shift; |
| 574 | return if saved($hv); |
| 575 | mark_saved($hv); |
| 576 | my $name = $hv->NAME; |
| 577 | my $ix = $hv->objix; |
| 578 | if (!$name) { |
| 579 | # It's an ordinary HV. Stashes have NAME set and need no further |
| 580 | # saving beyond the gv_stashpv that $hv->objix already ensures. |
| 581 | my @contents = $hv->ARRAY; |
| 582 | my ($i, @ixes); |
| 583 | for ($i = 1; $i < @contents; $i += 2) { |
| 584 | push(@ixes, $contents[$i]->objix); |
| 585 | } |
| 586 | for ($i = 1; $i < @contents; $i += 2) { |
| 587 | $contents[$i]->bytecode; |
| 588 | } |
| 589 | ldsv($ix); |
| 590 | for ($i = 0; $i < @contents; $i += 2) { |
| 591 | asmf("newpv %s\nhv_store %d\n", |
| 592 | pvstring($contents[$i]), $ixes[$i / 2]); |
| 593 | } |
| 594 | asmf "sv_refcnt %d\nsv_flags 0x%x\n", $hv->REFCNT, $hv->FLAGS; |
| 595 | } |
| 596 | } |
| 597 | |
| 598 | sub B::AV::bytecode { |
| 599 | my $av = shift; |
| 600 | return if saved($av); |
| 601 | my $ix = $av->objix; |
| 602 | my $fill = $av->FILL; |
| 603 | my $max = $av->MAX; |
| 604 | my (@array, @ixes); |
| 605 | if ($fill > -1) { |
| 606 | @array = $av->ARRAY; |
| 607 | @ixes = map($_->objix, @array); |
| 608 | my $sv; |
| 609 | foreach $sv (@array) { |
| 610 | $sv->bytecode; |
| 611 | } |
| 612 | } |
| 613 | # See PVNV::bytecode for the meaning of the flag argument of 2. |
| 614 | $av->B::PVMG::bytecode(2); |
| 615 | # Recover sv register and set AvMAX and AvFILL to -1 (since we |
| 616 | # create an AV with NEWSV and SvUPGRADE rather than doing newAV |
| 617 | # which is what sets AvMAX and AvFILL. |
| 618 | ldsv($ix); |
| 619 | asmf "sv_flags 0x%x\n", $av->FLAGS & ~SVf_READONLY; # SvREADONLY_off($av) in case PADCONST |
| 620 | asmf "xav_flags 0x%x\nxav_max -1\nxav_fill -1\n", $av->AvFLAGS; |
| 621 | if ($fill > -1) { |
| 622 | my $elix; |
| 623 | foreach $elix (@ixes) { |
| 624 | asm "av_push $elix\n"; |
| 625 | } |
| 626 | } else { |
| 627 | if ($max > -1) { |
| 628 | asm "av_extend $max\n"; |
| 629 | } |
| 630 | } |
| 631 | asmf "sv_flags 0x%x\n", $av->FLAGS; # restore flags from above |
| 632 | } |
| 633 | |
| 634 | sub B::CV::bytecode { |
| 635 | my $cv = shift; |
| 636 | return if saved($cv); |
| 637 | return if ${$cv->GV} && ($cv->GV->GvFLAGS & GVf_IMPORTED_CV); |
| 638 | my $fileix = pvix($cv->FILE); |
| 639 | my $ix = $cv->objix; |
| 640 | $cv->B::PVMG::bytecode; |
| 641 | my $i; |
| 642 | my @subfield_names = qw(ROOT START STASH GV PADLIST OUTSIDE); |
| 643 | my @subfields = map($cv->$_(), @subfield_names); |
| 644 | my @ixes = map($_->objix, @subfields); |
| 645 | # Save OP tree from CvROOT (first element of @subfields) |
| 646 | my $root = shift @subfields; |
| 647 | if ($$root) { |
| 648 | walkoptree($root, "bytecode"); |
| 649 | } |
| 650 | # Reset sv register for $cv (since above ->objix calls stomped on it) |
| 651 | ldsv($ix); |
| 652 | for ($i = 0; $i < @ixes; $i++) { |
| 653 | asmf "xcv_%s %d\n", lc($subfield_names[$i]), $ixes[$i]; |
| 654 | } |
| 655 | asmf "xcv_depth %d\nxcv_flags 0x%x\n", $cv->DEPTH, $cv->CvFLAGS; |
| 656 | asmf "xcv_file %d\n", $fileix; |
| 657 | # Now save all the subfields (except for CvROOT which was handled |
| 658 | # above) and CvSTART (now the initial element of @subfields). |
| 659 | shift @subfields; # bye-bye CvSTART |
| 660 | my $sv; |
| 661 | foreach $sv (@subfields) { |
| 662 | $sv->bytecode; |
| 663 | } |
| 664 | } |
| 665 | |
| 666 | sub B::IO::bytecode { |
| 667 | my $io = shift; |
| 668 | return if saved($io); |
| 669 | my $ix = $io->objix; |
| 670 | my $top_gv = $io->TOP_GV; |
| 671 | my $top_gvix = $top_gv->objix; |
| 672 | my $fmt_gv = $io->FMT_GV; |
| 673 | my $fmt_gvix = $fmt_gv->objix; |
| 674 | my $bottom_gv = $io->BOTTOM_GV; |
| 675 | my $bottom_gvix = $bottom_gv->objix; |
| 676 | |
| 677 | $io->B::PVMG::bytecode; |
| 678 | ldsv($ix); |
| 679 | asm "xio_top_gv $top_gvix\n"; |
| 680 | asm "xio_fmt_gv $fmt_gvix\n"; |
| 681 | asm "xio_bottom_gv $bottom_gvix\n"; |
| 682 | my $field; |
| 683 | foreach $field (qw(TOP_NAME FMT_NAME BOTTOM_NAME)) { |
| 684 | asmf "newpv %s\nxio_%s\n", pvstring($io->$field()), lc($field); |
| 685 | } |
| 686 | foreach $field (qw(LINES PAGE PAGE_LEN LINES_LEFT SUBPROCESS)) { |
| 687 | asmf "xio_%s %d\n", lc($field), $io->$field(); |
| 688 | } |
| 689 | asmf "xio_type %s\nxio_flags 0x%x\n", cstring($io->IoTYPE), $io->IoFLAGS; |
| 690 | $top_gv->bytecode; |
| 691 | $fmt_gv->bytecode; |
| 692 | $bottom_gv->bytecode; |
| 693 | } |
| 694 | |
| 695 | sub B::SPECIAL::bytecode { |
| 696 | # nothing extra needs doing |
| 697 | } |
| 698 | |
| 699 | sub bytecompile_object { |
| 700 | for my $sv (@_) { |
| 701 | svref_2object($sv)->bytecode; |
| 702 | } |
| 703 | } |
| 704 | |
| 705 | sub B::GV::bytecodecv { |
| 706 | my $gv = shift; |
| 707 | my $cv = $gv->CV; |
| 708 | if ($$cv && !saved($cv) && !($gv->FLAGS & GVf_IMPORTED_CV)) { |
| 709 | if ($debug_cv) { |
| 710 | warn sprintf("saving extra CV &%s::%s (0x%x) from GV 0x%x\n", |
| 711 | $gv->STASH->NAME, $gv->NAME, $$cv, $$gv); |
| 712 | } |
| 713 | $gv->bytecode; |
| 714 | } |
| 715 | } |
| 716 | |
| 717 | sub save_call_queues { |
| 718 | if (begin_av()->isa("B::AV")) { # this is just to save 'use Foo;' calls |
| 719 | for my $cv (begin_av()->ARRAY) { |
| 720 | next unless grep { $_ eq $cv->STASH->NAME; } @packages; |
| 721 | my $op = $cv->START; |
| 722 | OPLOOP: |
| 723 | while ($$op) { |
| 724 | if ($op->name eq 'require') { # save any BEGIN that does a require |
| 725 | $cv->bytecode; |
| 726 | asmf "push_begin %d\n", $cv->objix; |
| 727 | last OPLOOP; |
| 728 | } |
| 729 | $op = $op->next; |
| 730 | } |
| 731 | } |
| 732 | } |
| 733 | if (init_av()->isa("B::AV")) { |
| 734 | for my $cv (init_av()->ARRAY) { |
| 735 | next unless grep { $_ eq $cv->STASH->NAME; } @packages; |
| 736 | $cv->bytecode; |
| 737 | asmf "push_init %d\n", $cv->objix; |
| 738 | } |
| 739 | } |
| 740 | if (end_av()->isa("B::AV")) { |
| 741 | for my $cv (end_av()->ARRAY) { |
| 742 | next unless grep { $_ eq $cv->STASH->NAME; } @packages; |
| 743 | $cv->bytecode; |
| 744 | asmf "push_end %d\n", $cv->objix; |
| 745 | } |
| 746 | } |
| 747 | } |
| 748 | |
| 749 | sub symwalk { |
| 750 | no strict 'refs'; |
| 751 | my $ok = 1 if grep { (my $name = $_[0]) =~ s/::$//; $_ eq $name;} @packages; |
| 752 | if (grep { /^$_[0]/; } @packages) { |
| 753 | walksymtable(\%{"$_[0]"}, "bytecodecv", \&symwalk, $_[0]); |
| 754 | } |
| 755 | warn "considering $_[0] ... " . ($ok ? "accepted\n" : "rejected\n") |
| 756 | if $debug_bc; |
| 757 | $ok; |
| 758 | } |
| 759 | |
| 760 | sub bytecompile_main { |
| 761 | my $curpad = (comppadlist->ARRAY)[1]; |
| 762 | my $curpadix = $curpad->objix; |
| 763 | $curpad->bytecode; |
| 764 | save_call_queues(); |
| 765 | walkoptree(main_root, "bytecode") unless ref(main_root) eq "B::NULL"; |
| 766 | warn "done main program, now walking symbol table\n" if $debug_bc; |
| 767 | if (@packages) { |
| 768 | no strict qw(refs); |
| 769 | walksymtable(\%{"main::"}, "bytecodecv", \&symwalk); |
| 770 | } else { |
| 771 | die "No packages requested for compilation!\n"; |
| 772 | } |
| 773 | asmf "main_root %d\n", main_root->objix; |
| 774 | asmf "main_start %d\n", main_start->objix; |
| 775 | asmf "curpad $curpadix\n"; |
| 776 | # XXX Do min_intro_pending and max_intro_pending matter? |
| 777 | } |
| 778 | |
| 779 | sub compile { |
| 780 | my @options = @_; |
| 781 | my ($option, $opt, $arg); |
| 782 | open(OUT, ">&STDOUT"); |
| 783 | binmode OUT; |
| 784 | select OUT; |
| 785 | OPTION: |
| 786 | while ($option = shift @options) { |
| 787 | if ($option =~ /^-(.)(.*)/) { |
| 788 | $opt = $1; |
| 789 | $arg = $2; |
| 790 | } else { |
| 791 | unshift @options, $option; |
| 792 | last OPTION; |
| 793 | } |
| 794 | if ($opt eq "-" && $arg eq "-") { |
| 795 | shift @options; |
| 796 | last OPTION; |
| 797 | } elsif ($opt eq "o") { |
| 798 | $arg ||= shift @options; |
| 799 | open(OUT, ">$arg") or return "$arg: $!\n"; |
| 800 | binmode OUT; |
| 801 | } elsif ($opt eq "a") { |
| 802 | $arg ||= shift @options; |
| 803 | open(OUT, ">>$arg") or return "$arg: $!\n"; |
| 804 | binmode OUT; |
| 805 | } elsif ($opt eq "D") { |
| 806 | $arg ||= shift @options; |
| 807 | foreach $arg (split(//, $arg)) { |
| 808 | if ($arg eq "b") { |
| 809 | $| = 1; |
| 810 | debug(1); |
| 811 | } elsif ($arg eq "o") { |
| 812 | B->debug(1); |
| 813 | } elsif ($arg eq "a") { |
| 814 | B::Assembler::debug(1); |
| 815 | } elsif ($arg eq "C") { |
| 816 | $debug_cv = 1; |
| 817 | } |
| 818 | } |
| 819 | } elsif ($opt eq "v") { |
| 820 | $verbose = 1; |
| 821 | } elsif ($opt eq "S") { |
| 822 | $no_assemble = 1; |
| 823 | } elsif ($opt eq "f") { |
| 824 | $arg ||= shift @options; |
| 825 | my $value = $arg !~ s/^no-//; |
| 826 | $arg =~ s/-/_/g; |
| 827 | my $ref = $optimise{$arg}; |
| 828 | if (defined($ref)) { |
| 829 | $$ref = $value; |
| 830 | } else { |
| 831 | warn qq(ignoring unknown optimisation option "$arg"\n); |
| 832 | } |
| 833 | } elsif ($opt eq "O") { |
| 834 | $arg = 1 if $arg eq ""; |
| 835 | my $ref; |
| 836 | foreach $ref (values %optimise) { |
| 837 | $$ref = 0; |
| 838 | } |
| 839 | if ($arg >= 2) { |
| 840 | $bypass_nullops = 1; |
| 841 | } |
| 842 | if ($arg >= 1) { |
| 843 | $compress_nullops = 1; |
| 844 | $omit_seq = 1; |
| 845 | } |
| 846 | } elsif ($opt eq "u") { |
| 847 | $arg ||= shift @options; |
| 848 | push @packages, $arg; |
| 849 | } else { |
| 850 | warn qq(ignoring unknown option "$opt$arg"\n); |
| 851 | } |
| 852 | } |
| 853 | if (! @packages) { |
| 854 | warn "No package specified for compilation, assuming main::\n"; |
| 855 | @packages = qw(main); |
| 856 | } |
| 857 | if (@options) { |
| 858 | die "Extraneous options left on B::Bytecode commandline: @options\n"; |
| 859 | } else { |
| 860 | return sub { |
| 861 | newasm(\&apr) unless $no_assemble; |
| 862 | bytecompile_main(); |
| 863 | endasm() unless $no_assemble; |
| 864 | }; |
| 865 | } |
| 866 | } |
| 867 | |
| 868 | sub apr { print @_; } |
| 869 | |
| 870 | 1; |
| 871 | |
| 872 | __END__ |
| 873 | |
| 874 | =head1 NAME |
| 875 | |
| 876 | B::Bytecode - Perl compiler's bytecode backend |
| 877 | |
| 878 | =head1 SYNOPSIS |
| 879 | |
| 880 | perl -MO=Bytecode[,OPTIONS] foo.pl |
| 881 | |
| 882 | =head1 DESCRIPTION |
| 883 | |
| 884 | This compiler backend takes Perl source and generates a |
| 885 | platform-independent bytecode encapsulating code to load the |
| 886 | internal structures perl uses to run your program. When the |
| 887 | generated bytecode is loaded in, your program is ready to run, |
| 888 | reducing the time which perl would have taken to load and parse |
| 889 | your program into its internal semi-compiled form. That means that |
| 890 | compiling with this backend will not help improve the runtime |
| 891 | execution speed of your program but may improve the start-up time. |
| 892 | Depending on the environment in which your program runs this may |
| 893 | or may not be a help. |
| 894 | |
| 895 | The resulting bytecode can be run with a special byteperl executable |
| 896 | or (for non-main programs) be loaded via the C<byteload_fh> function |
| 897 | in the F<B> module. |
| 898 | |
| 899 | =head1 OPTIONS |
| 900 | |
| 901 | If there are any non-option arguments, they are taken to be names of |
| 902 | objects to be saved (probably doesn't work properly yet). Without |
| 903 | extra arguments, it saves the main program. |
| 904 | |
| 905 | =over 4 |
| 906 | |
| 907 | =item B<-ofilename> |
| 908 | |
| 909 | Output to filename instead of STDOUT. |
| 910 | |
| 911 | =item B<-afilename> |
| 912 | |
| 913 | Append output to filename. |
| 914 | |
| 915 | =item B<--> |
| 916 | |
| 917 | Force end of options. |
| 918 | |
| 919 | =item B<-f> |
| 920 | |
| 921 | Force optimisations on or off one at a time. Each can be preceded |
| 922 | by B<no-> to turn the option off (e.g. B<-fno-compress-nullops>). |
| 923 | |
| 924 | =item B<-fcompress-nullops> |
| 925 | |
| 926 | Only fills in the necessary fields of ops which have |
| 927 | been optimised away by perl's internal compiler. |
| 928 | |
| 929 | =item B<-fomit-sequence-numbers> |
| 930 | |
| 931 | Leaves out code to fill in the op_seq field of all ops |
| 932 | which is only used by perl's internal compiler. |
| 933 | |
| 934 | =item B<-fbypass-nullops> |
| 935 | |
| 936 | If op->op_next ever points to a NULLOP, replaces the op_next field |
| 937 | with the first non-NULLOP in the path of execution. |
| 938 | |
| 939 | =item B<-On> |
| 940 | |
| 941 | Optimisation level (n = 0, 1, 2, ...). B<-O> means B<-O1>. |
| 942 | B<-O1> sets B<-fcompress-nullops> B<-fomit-sequence numbers>. |
| 943 | B<-O2> adds B<-fbypass-nullops>. |
| 944 | |
| 945 | =item B<-D> |
| 946 | |
| 947 | Debug options (concatenated or separate flags like C<perl -D>). |
| 948 | |
| 949 | =item B<-Do> |
| 950 | |
| 951 | Prints each OP as it's processed. |
| 952 | |
| 953 | =item B<-Db> |
| 954 | |
| 955 | Print debugging information about bytecompiler progress. |
| 956 | |
| 957 | =item B<-Da> |
| 958 | |
| 959 | Tells the (bytecode) assembler to include source assembler lines |
| 960 | in its output as bytecode comments. |
| 961 | |
| 962 | =item B<-DC> |
| 963 | |
| 964 | Prints each CV taken from the final symbol tree walk. |
| 965 | |
| 966 | =item B<-S> |
| 967 | |
| 968 | Output (bytecode) assembler source rather than piping it |
| 969 | through the assembler and outputting bytecode. |
| 970 | |
| 971 | =item B<-upackage> |
| 972 | |
| 973 | Stores package in the output. |
| 974 | |
| 975 | =back |
| 976 | |
| 977 | =head1 EXAMPLES |
| 978 | |
| 979 | perl -MO=Bytecode,-O6,-ofoo.plc,-umain foo.pl |
| 980 | |
| 981 | perl -MO=Bytecode,-S,-umain foo.pl > foo.S |
| 982 | assemble foo.S > foo.plc |
| 983 | |
| 984 | Note that C<assemble> lives in the C<B> subdirectory of your perl |
| 985 | library directory. The utility called perlcc may also be used to |
| 986 | help make use of this compiler. |
| 987 | |
| 988 | perl -MO=Bytecode,-uFoo,-oFoo.pmc Foo.pm |
| 989 | |
| 990 | =head1 BUGS |
| 991 | |
| 992 | Output is still huge and there are still occasional crashes during |
| 993 | either compilation or ByteLoading. Current status: experimental. |
| 994 | |
| 995 | =head1 AUTHORS |
| 996 | |
| 997 | Malcolm Beattie, C<mbeattie@sable.ox.ac.uk> |
| 998 | Benjamin Stuhl, C<sho_pi@hotmail.com> |
| 999 | |
| 1000 | =cut |