pperl 0.6.22#
2026-10-06 to 2026-10-11, 89 commits.
Language and runtime#
%Config is complete: it has every key perl 5.44’s has, 1,261 of them, where it had 198. The
d_*andi_*answers come from probing the C library and include tree the way Configure does, the type sizes and formats from the build target, the tools fromPATH, and the version, signal and extension keys from the running interpreter.ExtUtils::MakeMakerno longer warns about uninitialized values on everyWriteMakefile,DirHandle,Net::protoentandNet::serventno longer believe their functions are missing, and$Config{PERL_VERSION},$Config{d_readdir},$Config{uidsize}and the rest exist.The library’s data files are in the binary and readable: the files perl’s modules open by path beside themselves, such as
ExtUtils::Manifest’s defaultMANIFEST.SKIPand theunicoretablesUnicode::UCDreads.make distdirno longer copiesMYMETA.*into the distribution directory, andUnicode::UCD’scharblock,charscriptand friends no longer depend on a perl installed on the host.@INCstarts with./pperl-native, the embedded tree’s own entry.The daemon and duplicated output handles: a script run through the daemon with
PPERL_DAEMON=2that duplicatesSTDOUT,STDERRorSTDINwhile it compiles - every script that loadsTest::Moredoes - printed its output only on the first run, and the program reading that first run’s output never saw it end. Each run now writes to its own output and reads its own input.$0 and the environment: assigning a name longer than the command line to
$0no longer destroys the environment that child processes inherit. A program that renamed itself and then ransystem, a backtick orexechad its children start with almost no environment (noHOME, noPATHadditions), while its own%ENVlooked fine.
JIT and parallelization#
Conditional expressions in compiled loops: a
?:whose arm reads an element through a reference ($c ? $x->[$i] : 0) or from a hash ($c ? $h{$k} : 0) no longer makes the loop leave compiled code each time that arm is taken. An arm that is an element of a plain array already stayed compiled.Recursive subs called from compiled loops: a loop such as
for (1 .. $n) { local $_; $sum += fib($k) }died withpanic: pp_iter, type=9once it compiled, when the sub it calls recurses;Benchmark’stimetheseandcountitof a recursive sub died the same way. The compiled loop mistook a deeper recursion level’s frame for its own.A regex run once no longer gets compiled: the regex compiler decided by the size of the string a pattern was matched against, so a pattern used a single time on a large string, as
charnames::viacodeandvianamedo for every lookup over the one-megabyte names table, was compiled for that one match and the compilation cost several times the match. A place in the program that builds a new pattern for every lookup and runs each once now compiles none of them after the first; a loop of a thousand charnames lookups runs in a fifth of the instructions, and a pattern that is reused compiles when it did.Integers past 2^53 in compiled loops: a loop that computes an integer beyond 9007199254740992 and divides by it next, such as the long division inside
Math::BigInton numbers held as floats (Math::BigFloat->new(2)->bpow(240)->broot(9)withMath::BigInt::FastCalc), could get one quotient digit wrong the first time the loop ran on float-typed values after integer-typed ones; later runs were right. The compiled loop had taken a rounded copy of the exact integer perl kept. It now leaves compiled code for that pass, as it does whenever a value cannot be held exactly.$_ in a nested statement-modifier loop: in a compiled loop that contains
EXPR for LO .. HI, where EXPR calls a function and reads$_in its arguments, the first pass of every inner loop saw$_undefined: a “Use of uninitialized value $_” warning, and 0 where the value was wanted, so a range not starting at 0 gave wrong results.
Modules#
Native modules in the release build: the build’s profile-guided optimisation now runs POSIX, Socket, Errno, Config, Time::Piece, Sys::Syslog, IPC::SysV, the DBM modules, Unicode::Normalize, Unicode::UCD, charnames, the Symbol and EBCDIC encodings, the
:encoding,:viaand:mmaplayers, File::Map, Hash::Util, Clone, Memoize, Math::BigInt::FastCalc, B, Opcode, Safe, PadWalker, Devel::Peek, mro, attributes, source filters, EV, Event, Coro’s loop bridges, Peta::Dict, Peta::PCRE2, Peta::XS, Peta::FFI and Peta::LMDB before it decides what is hot. None of these had been run by the build before, so the release binary carried them compiled for size rather than for speed.Errno has every name the host defines:
%!, the constants and@Errno::EXPORT_OKnow come from the errno.h of the machine pperl was built on and the headers it includes, read at build time the way perl’s own Errno.pm is generated.EFTYPE,EFSBADCRCandEFSCORRUPTED, which current kernel headers define and the previous fixed table lacked, exist; on this host the list is identical to perl 5.44’s, all 137 names.The -C switch:
pperl -CSAD scriptand the other forms of perl’s Unicode switch work, alone and at the end of a cluster such as-wCSD; they were refused with “Unknown option: -C”, and onlyPERL_UNICODEin the environment had the effect.Compress::Raw::Bzip2 exists, with
Compress::Raw::Bunzip2and theBZ_*constants, over the system’s libbz2. With itIO::Compress::Bzip2,IO::Uncompress::Bunzip2,IO::Uncompress::AnyUncompressandArchive::Tarread and write bzip2 data,.tbzarchives among it, andstreamzipmakes bzip2 zip entries; they died with “Can’t locate Compress/Raw/Bzip2.pm”.Peta::ReadLine is the name of the readline module;
Term::ReadLine::Gnuis an alias of it, souse Term::ReadLinestill picks it up, a program that tests$term->ReadLine eq "Term::ReadLine::Gnu"(CPAN.pm, the debugger) still passes, andTerm::ReadLine::Gnu::XS::*calls still work.Peta::ReadLine->newreportsPeta::ReadLine, version 0.2.0; the alias reports the name it was asked by.Peta::ReadLine’s function table and keymaps:
get_all_function_nameslists the bindable commands (it returned one name of garbage),get_function_namefinds a function’s name, and$attribs->{executing_keymap}and$attribs->{binding_keymap}areKeymapobjects thatget_keymap_nameand the binding methods accept.import Term::ReadLine::Gnu qw(:keymap_type)and the other export tags work under the alias as they do underPeta::ReadLine.Peta::ReadLine’s ignore_some_completions_function: a completion with
$attribs->{ignore_some_completions_function}set no longer dies with “panic: attempt to copy freed scalar” in the statement that calledcomplete_internalorcall_function.Peta::ReadLine has its own line editor: no readline, history or curses library is loaded any more, so line editing works where none is installed and in the static build. It behaves as GNU Readline 8.3 does - commands, key bindings, the init file, history, completion, signals, and the same screen after every key. In a UTF-8 locale the commands move, delete, change case and search by characters, not bytes. It identifies itself:
$attribs->{library_version}is8.3 (Peta::ReadLine 0.2.0)and$attribs->{gnu_readline_p}is 0.Imager follows Imager 1.037.
getsampleschecks its arguments itself and says inerrstrwhy a call failed (a row outside the image, a channel the image does not have); a failed call returns the empty list, or undef in scalar context. An image too large to allocate failsImager->newwith a message instead of ending the program, andset_out_of_memory_handlerexists.Imager drawing and images:
box,line(plain and anti-aliased) andarcdraw;getscanline,setscanline, the palette rows andsetcolorswork; images convert between 8-bit, 16-bit and double samples and can be compared.open_log,logandclose_logwrite Imager’s log, and colours havered,green,blue,alphaand HSV conversion. Three results changed to what Imager gives: a 16-bit image read as 8-bit colours was one too bright for some values,i_img_info’s fourth value is the channel mask, and the colour count of a direct image is undef.Imager I/O objects:
Imager::IOexists:new_buffer,new_fd,new_fh,new_cbandnew_bufchain(and theio_new_*functions) make an I/O object over a string, a file descriptor, a file handle, Perl callbacks or a file in memory, withread,write,seek,getc,gets,peekn,closeand the rest of the class.io_slurpof an object that is not a memory file dies with a message; under Imager itself it ends the program silently.Imager PNM files: Imager reads and writes PNM files (PBM, PGM and PPM, ASCII and binary, 8 and 16 bit),
read_multiincluded, soImager->new(file => 'x.ppm')and$img->write(type => 'pnm')work.set_file_limits,get_file_limitsandcheck_file_limitsbound what is read, and the format of a file is detected from its first bytes, withadd_file_magicfor signatures of your own.Imager raw files:
readandwritewithtype => 'raw'work: rows of bare 8-bit samples, interleaved by sample or by line, withraw_datachannelsandraw_storechannelschoosing which channels of the file are kept.Imager BMP files: Windows BMP files are read at 1, 4, 8, 16, 24 and 32 bits a pixel, run length encoded and with bit-field masks included, and written uncompressed. A grey image with an alpha channel is written with its own grey; under Imager itself each pixel takes its neighbour’s value as alpha and half the row is garbage.
Imager TGA files: Targa files are read and written: colour-mapped, direct colour and grey, run length encoded or not, at 8, 15, 16, 24 and 32 bits a pixel, with the
compress,wierdpackandidstringoptions.%Imager::formatsnow lists what Imager lists without any library: raw, pnm, bmp, tga and ifs.Imager masked images:
$img->maskedgives a view of part of an image, optionally written through a mask, that can be drawn into, copied and written to a file.setsamplesis available, with its floating point and 16-bit forms, and so aregetsampleswithtype => 'float'andtype => '16bit'. A floating point sample outside 0 to 1 now wraps when stored in an 8- or 16-bit image, as in Imager, andgetmaskon a fresh image is -1.Imager fills:
boxandarctake afill, andImager::Fillmakes solid, hatched, image and opacity fills with the twelve combine modes (normal,multiply,add,darken,hueand the rest).Imager paste and crop:
$img->pastecopies a rectangle of another image in, converting between sample depths and channel counts, and$img->cropcuts one out.Imager circles and flood fill:
circledraws filled anti-aliased circles and, withfilled => 0, outlines, plain or anti-aliased;arcwithfilled => 0draws the outline of an arc.flood_fillfills the region around a point with a colour or a fill, optionally up to abordercolour, andpolybezierdraws a Bezier curve.Imager polygons:
polygonandpolypolygonfill anti-aliased polygons with a colour or a fill, by the even-odd or the non-zero winding rule, andarcwithaa => 1draws an anti-aliased pie slice.Imager rubthrough and compose:
$img->rubthroughlays another image over the image by its alpha channel, and$img->composedoes so with a combine mode, anopacityand optionally amaskimage.Imager fountain fills:
Imager::Fill->new(fountain => ...)makes a gradient fill (linear, bilinear, radial, square, revolution or conical, with repeats, segments and super-sampling), and$img->filter(type => 'fountain')draws one over a whole image.Imager channel operations:
$img->convertmakes a new image by a matrix or a preset (grey,noalpha,rgb,addalphaand the single channels),Imager->combinemakes one from channels of several images,$img->mapruns channels through lookup tables, and$img->flipmirrors the image.Imager quantisation:
$img->to_palettedturns a direct colour image into a paletted one, with the palette from median cut, theaddimethod, a fixed map or your own colours, and the pixels matched by closest colour, perturbation or error diffusion.Imager->make_palette,getcolorcount,getcolorusageandgetcolorusagehashwork.Imager scaling:
$img->scale,scaleXandscaleYreturn a scaled copy, with thenormal,previewandmixingmethods.Imager rotation:
$img->rotateturns an image by quarter turns (right) or by any angle (degrees,radians, withback), and$img->matrix_transformmaps it through a 3 x 3 matrix.Imager trim:
$img->trimandtrim_rectfind and remove the border of an image, by colour ranges (colors,auto) or by transparency (alpha).Imager transform and transform2:
Imager::transform2computes an image from an expression per pixel (rpnexpr, orexprwith Parse::RecDescent), reading up to three input images, and$img->transformmoves pixels by two stack programs.Imager filters:
$img->filterhas every filter Imager has built in:autolevels,autolevels_skew,bumpmap,bumpmap_complex,contrast,gaussian,gaussian2,gradgen,hardinvert,hardinvertall,mosaic,nearest_color,noise,postlevels,radnoise,turbnoise,unsharpmaskandwatermark, besideconvandfountain.$img->differenceandrgb_differenceshow where two images differ.Imager object destructors: calling the
DESTROYof an Imager class on something that is not a reference dies with Imager’s message, “is not a reference”; it named an expected type instead.$Imager::_contextexists.Imager plugin loader:
Imager->load_plugin, which loads filter plugins compiled from C, returns undef and sets$Imager::ERRSTRinstead of dying with “Undefined subroutine”. Such plugins cannot be loaded; Imager has documented that interface as deprecated since 2006.Peta::WebGPU and fork: a process that has opened a device can fork. The child used to hang for ever when it exited; now it ends normally. Using an inherited device, buffer or shader in the child dies with a message that says to open a device there, and the child can do so and compute on it. Where the parent has the
glbackend open, the child’s device comes from the other backends.Peta::WebGPU batches:
$gpu->batch(sub { ... }), or$gpu->beginand$gpu->commit, send any number of dispatches to the card in one go, and$pipeline->bind(\@buffers)gives an objectruntakes in place of the pipeline and its buffer list, so a recurring dispatch no longer binds its buffers each time. Awriteinside a batch takes effect in order with the dispatches around it, and$gpu->timed(sub { ... })returns the nanoseconds the card spent on a batch.$gpu->featuresand$gpu->has_featurename the optional features of the device, which now has half-precision floats in shaders (enable f16;) and timestamp queries wherever the adapter does.Peta::WebGPU buffers:
$buffer->read($offset, $length)reads a part of a buffer, so fetching one number no longer copies the whole buffer back from the card.$buffer->writetakes a PDL ndarray of typefloat,longorulongas well as a byte string.Peta::WebGPU memory: a buffer made with contents no longer takes twice its size on the card until the next dispatch; large contents go up in pieces.
$buffer->destroyfrees a buffer’s memory at once,$gpu->memoryreports what the device has allocated, andDevice->new(memory_limit => 90)turns running out of card memory into anOut of Memoryexception at 90 percent of the driver’s budget. A program that frees buffers and at once makes new ones is no longer told the card is full while the freed memory is still on its way back, and an error message names the first failure, not one that followed from it.Peta::WebGPU on OpenGL:
Device->new(backend => 'gl')opens on the NVIDIA driver, where it failed with “Parent device is lost”. Drawing works there; compute needs OpenGL 4.3 or ES 3.1, and on an older context dies with a message that names thevulkanbackend.Net::SSLeay version constants:
OPENSSL_VERSION_MAJOR,OPENSSL_VERSION_MINOR,OPENSSL_VERSION_PATCHandOPENSSL_VERSION_NUMBERname the OpenSSL that is loaded. They kept the values of the release pperl was built beside, so after a system update to OpenSSL 3.6.5OPENSSL_VERSION_PATCHstill said 4.GD has the rest of GD 2.91: the affine matrices and transforms,
colorReplaceand its variants,convolution,resolution, the transposed, rotated, scaled and blurred copies, animated GIF, HEIF and AVIF, 48 functions in all.GD::VERSION_STRINGis now libgd’s version string andGD::LIBGD_VERSIONits number (2.0303 for libgd 2.3.3), as in GD itself.GD::Image->supportedand thenewFrom<Format>methods follow what the installed libgd can read.GD colorsTotal:
$image->colorsTotalon a truecolor image returnsundef, as in GD itself. It returned 0.Config::config_vars and
-Vprint the way Perl’sprintdoes: to the handleselectchose, through a tiedSTDOUT, and in order with the program’s other output. They wrote to the process’s standard output directly, so a capture saw nothing and, on a pipe, their lines could come out ahead of text printed earlier.Config::compile_dateand the matching line of-VreadCompiled at Oct 8 2026 20:42:44, the layoutConfig::Perl::Vparses; they named the compiler instead.Cairo, Cwd, Term::ReadLine::Gnu:
Cairo::HAS_PS_SURFACE,HAS_PDF_SURFACE,HAS_SVG_SURFACE,HAS_RECORDING_SURFACEandHAS_FT_FONTexist.Cwd::CLONEexists.rl_save_statereturns areadline_state_tPtrobject, which is freed with its last reference and is the only thingrl_restore_stateaccepts.