This is not enough!

The time for some shiny new hardware came around. Sat next to me, purring decidedly more quietly that its predecessor, is my new main development machine: a quad core Intel Core i7, pimped out with 16 GB of RAM and a sufficiently generous SSD that it can hold the OS, compiler toolchain and projects I work most actively on. It’s nice having a $dayjob that likes keeping their hackers…er, consultants…well kitted out. :-)

So, the question I had to ask was: how fast can this thing run the Rakudo spectests? I tried, and with –jobs=8 (the sweet spot, it seems) it chugged its way through them in 220s. That’s vastly better than I’d ever been able to do before, and I could immediately see it was going to be a boon for my Rakudo productivity. 3 minutes 40 seconds. Not so long to wait to know a patch is fine to push. But…what if it was less? It’s fast but…this is not enough!

A while ago, moritz++ showed how the nom branch of Rakudo ran mandelbrot 5 times faster than master. This was a fairly nice indicator. Around the time my new hardware arrived, an update was posted on #perl6: mandelbrot was now down to 2 minutes on the same machine the original tests were done. Again, I was happy to see progress in the right direction but I couldn’t help but feel…this is not enough!

So, I took a few days break from bug fixing and features, and decided to see if things could get faster.

Faster Attribute Access

One of the things I’ve had planned for since the early days of working on 6model is being able to look up attributes by index in the single inheritance case, rather than by name. I finally got around to finishing this up (I’d already put in most of the hooks, just not done the final bits). It’s not an entirely trivial thing to make work; at the point we parse an attribute access we don’t know enough about how the eventual memory layout of the object will be, or whether an indexed lookup will even work. Further, we have to involve the representation in the decision, since we can’t assume all types will use the same one. Mostly, it just involves a later stage of the code generation (PAST => POST in this case) having the type object reachable from the AST and asking it for a slot index, if possible.

Since I implemented it at the code-gen level, it meant the improvement was available to both NQP and Rakudo, so we get compiler and runtime performance improvements from it. Furthermore, I was able to improve various places where the VM interface does attribute lookups (for example, invocation of a code object involves grabbing the underlying VM-level thingy that represents an executable thing, and that “grabbing” is done by an attribute access on the code object). Attribute lookups never really showed up that high in the (C-level) profile, but now they’re way, way down the list.

The P6opaque Diet

P6opaque is by far the most common object representation used in NQP and Rakudo. It’s generally pretty smart; it has a header, and then lays out attributes – including natively typed ones – just like a C structure would be laid out in memory. In fact, it mimics C structures well enough that for a couple of parts of the low-level parts of Rakudo we have C struct definitions that let us pretend that full-blown objects are just plain old C structures. We don’t have to compromise on having first class objects in order to write fast low-level code that works against them any more. Of course, you do commit to a representation – but for a handful of built-in types that’s fine.

So, that’s all rainbows and butterflies, so what was the problem? Back last autumn, I thought I knew how implementing mix-ins and multiple inheritance attribute storage was going to look; it involved some attributes going into a “spill hash” if they were added dynamically, or all of them would go there apart from any in a common SI prefix. Come this spring when I actually did it for real, a slightly smarter me realized I could do much better. It involved a level of indirection – apart from that level already existed, so there was actually no added cost at all. Thing is, I’d already put the spill slot in there, and naughtily used the difference between NULL and PMCNULL as the thing that marked out whether the object was a type object or not.

This week, I shuffled that indicator to be a bit in the PMC object header (Parrot makes several such bits available for us to use for things like that). This meant the spill slot in the P6opaque header could go away. Result: every object using the P6opaque representation got 4 (32-bit) or 8 (64-bit) bytes lighter. This has memory usage benefits, but also some speed ones: we get more in the CPU cache for one, and for another we can pack more objects into fixed sized pools, meaning they have less arenas to manage. Win.

Constant Pain

In Perl 6 we have Str objects. Thanks to 6model’s capability to embed a native Parrot string right into an object, these got about three times cheaper in terms of memory already in nom. Well, hopefully. The thing is, there’s a very painful way to shoot yourself in the foot at the implementation level. 6model differentiates coercion (a high level, language sensitive operation) from unboxing (given this object, give me the native thingy inside of it). Coercion costs somewhat more (a method call or two) than unboxing (mostly just some pointer follows). If you manage to generate code that wants a VM-level string, and it just has an object, it’ll end up doing a coercion (since at that level, it doesn’t know the much cheaper unbox is possible/safe). After reading some of the compiler output, I spotted a bunch of cases where this was happening – worst of all, with constant strings in places we could have just emitted VM-level constant strings! Fixing that, and some other unfortunate cases of coercion instead of unbox, meant I could make the join method a load faster. Mandelbrot uses this method heavily, and it was a surprisingly big win. String concatenation had a variant of this kind of issue, so I fixed that up too.

Optimizing Lexical Lookup

We do a lot of lexical lookups. I’m hopeful that at some point we’ll have an optimizer that can deal with this (the analysis is probably quite tricky for full-blown Perl 6; in NQP it’s much more tractable). In the meantime, it’s nice if they can be faster. After a look over profiler output, I found a way to get a win by caching a low-level hash pointer directly in the lexpad rather than looking it up each time. Profilers. They help. :-)

Optimized MRO Compuation

The easiest optimizations for me to do are…the ones somebody else does. Earlier this week, after looking over the output from a higher level profiler that he’s developing for Parrot, mls++ showed up with a patch that optimized a very common path of C3 MRO computation. Curiously, we were spending quite a bit of time at startup doing that. Of course, once we can serialize stuff fully, we won’t have to do it at all, but this patch will still be a win for compile time, or any time we dynamically construct classes by doing meta-programming. A startup time improvement gets magnified by a factor of 450 times over a spectest run (that’s how many files we have), and it ended up being decidedly noticeable. Again, not where I’d have thought to look…profiling wins again.

Multi-dispatch Cache

We do a lot of multiple dispatch in Perl 6. While I expect an optimizer, with enough type information to hand, will be able to decide a bunch of them at compile time, we’ll always still need to do some at runtime, and they need to be fast. While we’ve cached the sorted candidate list for ages, it still takes a time to walk through it to find the best one. When I was doing the 6model on CLR work, I came up with a design for a multi-dispatch cache that seemed quite reasonable (of note, it does zero heap allocations in order to do a lookup and has decent cache properties). I ported this to C and…it caused loads of test failures. After an hour of frustration, I slept on it, then fixed the issue within 10 minutes the next morning. Guess sleep helps as well as profilers. Naturally, it was a big speed win.

Don’t Do Stuff Twice

Somehow, in the switch over to the nom branch, I’d managed to miss setting the flag that causes us not to do type checks in the binder if the multi-dispatcher already calculated they’d succeed. Since the multi-dispatch cache, when it gets a hit, can tell us that much faster than actually doing the checks, not re-doing them is a fairly notable win.

Results

After all of this, I now have a spectest run in just short of 170 seconds (for running 14267 tests). That’s solidly under the three minute mark, down 50s on earlier on this week. And if it’s that much of a win for me on this hardware, I expect it’s going to amount to an improvement measured in some minutes for some of our other contributors.

And what of mandelbrot? Earlier on today, moritz reported a time of 51 seconds. The best we ever got it to do in the previous generation of Rakudo was 16 minutes 14 seconds, making for a 19 times performance improvement for this benchmark.

This is not enough!

Of course, these are welcome improvements, and will make the upcoming first release of Rakudo from this new “nom” development branch nicer for our users. But it’s just one step on the way. These changes make Rakudo faster – but there’s still plenty to be done yet. And note that this work doesn’t deliver any of the “big ticket” items I mentioned in my previous post, which should also give us some good wins. Plus there’s parsing performance improvements in the pipeline – but I’ll leave those for pmichaud++ to tell you about as they land. :-)

Posted in Uncategorized | 3 Comments

What’s coming up in September/October

So, YAPC has come, been great, gone and been recovered from, I’m done with my summer visiting, the $dayjob speaking trip has taken place, I’ve shaken off the obligatory start of autumn cold and it’s time to get back to hacking on stuff. Actually, I’ve no more workshops or other trips until November and I’ve got Perl 6 time marked in my schedule, so all being well there should be plenty of time to Get Stuff Done. :-) So what have I got planned for the next couple of months?

Ship a ”nom”-based Release

This is the current priority. Day by day, we’re fixing up test files we lost in the refactor. This weekend I got most of the missing bits of parametric role support back in place (and I’m overall happy with the resulting factoring; it’s a massive amount better than what we had before). Our biggest remaining holes are in the regex and grammar handling, which pmichaud++ is on with (I’m quite excited about what’s coming here). Other than that, it’s little bits here and there. We’re getting there. :-)

A Basic Rakudo Optimizer

I’ve started playing with this a bit, in a branch. Nothing interesting to see yet, other than an optimizer that only knows one optimization, makes a few things a little faster and regresses a couple of spectests (so, some weird bug in the analysis or transform somewhere). The good news is that it does successfully make it through applying that optimization to CORE.setting. This is an important part of developing the optimizer: if we’re going to write our built-ins in Perl 6, we really want an optimizer to go over them too. My aim is to teach this a couple more things and have it in the October release.

A Basic NQP Optimizer

NQP is the subset of Perl 6 that we write most of the compiler in. We also implement the various built-in meta-objects in it (so we want it to be fast here, and of course we want faster compiles!) It currently has no optimizer, a situation I plan to change. NQP has many restrictions that full-blown Perl 6 does not have, and as a result we’ll be able to do some more aggressive optimizations, or be able to apply them with far simpler analysis. My goal is to have some form of basic optimizer in NQP by the October release. Of course, since NQP is bootstrapped, NQP’s optimizer can be used to optimize NQP itself (yes, it can optimize the optimizer…) “So we just keep running NQP on itself until it runs crazy fast?” Er, no, sorry, it doesn’t work like that. :-)

Bounded Serialization

Currently, as we compile programs, we build up a complete “model” of the runtime environment (for example, we build Signature/Parameter objects, meta-objects to represent classes, and so forth). If we’re going to just run the program, we carry these objects over to runtime and use them. If we’re in compilation mode, like we are with the setting, then we generate a bunch of “deserialization code”. This gets run first of all when we load the setting/module in question. This introduces a couple of problems.

  • It’s a lot of code to generate. In fact, it accounts for a whopping 60% of the lines of PIR in CORE.setting! This probably means that about 60% of the PAST nodes we generate and then have to process into POST and then PIR are also related to this. Assuming we could replace this process with something much faster, we’re looking at cutting compilation time in half for the setting. Note that this only really affects pre-compilation time, not “run immediately” mode.
  • We have to run it all at load time. Now, having it all in one huge blob is decidedly more efficient than the thousands of little loadinit subs we had everywhere in previous generations of Rakudo. But we still have to do it, and it means that loading the setting – something we have to do every time we start Rakudo to compile or run code – pays that cost. We need better startup time.
  • We have to make sure that every single change that gets made gets recorded. We cheat a bit here. This gets in the way of many things, including various optimizations and proper BEGIN time support in pre-compiled modules (note that we don’t re-run BEGIN, but we should maintain effects of it).

The solution is to find a way to efficiently serialize everything we create, and then be able to deserialize it efficiently at load time and do the few needed fixups. While in theory it’s “easy” (keeping iterating over a worklist until you’ve serialized everything, basically), there’s a bunch of really tricky things that also come up (especially any closures that got taken at compile time). I hope to dig into this before the end of the month, and my target is to have it for the November release (October one is a bit ambitious, unless it goes crazily well; in reality, I’d like to land it late October, so we have a couple of weeks before the November release to get it in shape).

Revive the CLR Backend

Running NQP on the CLR got a long, long way. At the time I last touched it, the majority of the non-regex tests in the NQP test suite were passing, and diakopter++ was making progress on the regex ones too. It’s been dormant for a while, but it’s time to get back to work on it. Getting NQP, and then Rakudo, to run on the CLR is now a vastly more tractable task to back then, since:

  • Back then, I was in the process of designing 6model and doing an NQP port and working out what NQP on 6model would look like. Now I only have to worry about one of those things, not all three at the same time.
  • NQP itself is 6model based now. Thus there won’t be a need for the “JnthnNQP” fork (NQP itself ended up looking much more like JnthnNQP anyway, which was the idea). If I do need tweaks that I can’t immediately reconcile with NQP on Parrot, they can be done just by subclassing NQP::Actions or so and overriding the things in question. Either way, it’ll be the same – or a slightly twiddled – version of NQP, not a vastly different one.
  • Rakudo itself is now mostly written in NQP and Perl 6. We used to have a bunch of PIR builtins, but they’re long gone (along with various ugly issues they caused, like not having proper Perl 6 signatures and so forth). I’d guesstimate that about 5% – at most 10% – of the Rakudo code is backend specific. Some of it will be tricky, but a lot of it is – at least if you’re familiar with it – pretty mundane.

Of course, some problems I chose to ignore will need to be dealt with (like, how to best harness the way to CLR thinks of types in order to implement 6model representations more efficiently, and how to support gather/take). It’ll need generating IL rather than C#. And…plenty more. I’m not going to set any targets for this just yet; I’ll just dig in, have fun, and we’ll see where things land up in a month or two. I found it great fun to work on this last time – the CLR is a nice VM and well tuned – so it shouldn’t be hard to get a round tuit. :-)

Other Bits

Of course, there’s still bits of the Perl 6 spec that needs implementing, and things in module space. Amongst things I’d like to hack on soon are big integer support (so we can do Int right), natively typed operators and teaching NativeCall to handle structures.

Other 6model Bits

I want to vastly improve the state of 6model’s documentation. Taking a moment to look further ahead than the next couple of months, once the updated CLR implementation of it comes together, and when some other language’s object systems have been shown to be buildable on 6model, I also want to think about declaring a “6model API v1″ or so. This is so that if/when Parrot integrates 6model, or others implementations show up that I won’t have a close hand in, there’s a clear idea of what it’s expected to look like from the outside, and what are implementation details (and thus can be done in whatever way is appropriate). I also expect further extensions, refinements, and so forth, and I think it’d be best to give folks who implement 6model – myself included! – some coarser grained way of saying “we support this set of things” than just listing off implemented features. This is some way off, though I do already have a slowly forming picture of what I’d like to tackle in the area of meta-model design in the future.

So, that’s what I’ve got in mind. Oh, and I should be sure to blog as I work on this stuff! Feel free to prod me if I forget. :-)

Posted in Uncategorized | 1 Comment

My YAPC::EU talks

I had a wonderful time at YAPC::EU in Riga this year. Riga is a very beautiful city – there’s many nice things to look at, not to mention the excellent food and a wide range of beer at sensible prices. Once place I went had over 30 types of beer on tap! That’s the city, but then there was the YAPC itself: smooth running, well organized, nice venue, all breaks and lunches on site, and a great conference dinner. I’ve had the fortune to be at many events where Andrew Shitov has led the organization (I just checked and I think this must have been the 9th one!), and I knew he could do something excellent for YAPC::EU. He did, and was a very deserving recipient of a White Camel award this year. So, congrats to Andrew, and many thanks for the steady stream of excuses to travel to East Europe and talk about Perl. :-)

I gave a couple of talks.

So, another year, another great YAPC. And now, it’s back to work on Rakudo!

Posted in Uncategorized | Leave a comment

A hint of meta-programming

After a few patches to deal with some meta-circularity issues, I’ve got to the point where I have at least a very basic example of a custom meta-class working in the nom branch of Rakudo. All this does is print out the name of each method that gets looked up, before deferring to the normal handling of method dispatch. However, I’m sure that now that I’m at this point, much more interesting things are already very possible, though no doubt there’s some rough edges I still need to deal with.

Anyways, to the code! Here’s a module, LoggedDispatch.pm.

my class LoggedDispatch is Metamodel::ClassHOW is Mu {
    method find_method($obj, $name) {
        note "Looking up method $name";
        nextsame;
    }
    
    method publish_method_cache($obj) {
        # Suppress this, so we always hit find_method.
    }
}

# Export this as the meta-class for the "class" package declarator.
my module EXPORTHOW { }
EXPORTHOW.WHO.<class> = LoggedDispatch;

Taking it from the top, we inherit from Metamodel::ClassHOW, which is the default implementation of Perl 6 classes. There’s actually no requirement to do this – in some future posts I’ll show you how you can easily piece together meta-classes from the ground up – but in this case all we really want to do is a small tweak to the existing behavior. For now, we also inherit from Mu. (Aside: at the moment, since ClassHOW is what defines classes, it falls “outside” of the Perl 6 type hierarchy. That’s in some ways understandable but also in some ways very awkward. I’ve more than one approach to dealing with this, but need to think more on the problem.)

Now, on to the meat of the problem. Conceptually, every method dispatch on an object gets that object’s meta-object and calls “find_method” on it, passing in the method name to find. Therefore, in order to intercept this, we need to override “find_method” – which is what we do. We simply print the name of the method to STDERR using “note”, then use “nextsame” to defer to the actual method lookup algorithm. Pretty easy. However, there’s a twist.

As you might imagine, dispatching methods is a hot-path. If we have to call a method in order to work out what method to call – and if that had to do the same in turn – things would get really very slow indeed. Thus, it’s possible to publish a method cache, which is dead fast to look in. However, it’s also going to mean that find_method never gets called – which is where we’re going to put our logging stuff. While for an optimized version of this we could compute a bunch of closures to do the logging and populate a cache with those, for now we just suppress generation of the cache.

That gets us down to the last bit. There’s a (lexical) EXPORT package for exporting symbols, but we want to do something a bit different here: we want to tell the compiler that when this module is used, it should use our meta-class whenever the user writes a class (that is, uses the package declarator “class”). For now (note, API liable to change) that’s done by installing an entry in an EXPORTHOW module.

And with that, we’re done. Here’s an example program.

use LoggedDispatch;

class A {
    method m1() { say 42 }
    method m2() { say 99 }
}

for 1..2 {
    A.m1;
    A.m2;
}

And here’s the output:

Looking up method BUILD
Looking up method m1
42
Looking up method m2
99
Looking up method m1
42
Looking up method m2
99

The first line of this may be a little surprising – something goes looking for a BUILD method at some point. But it’s maybe not such a surprise: it’s a method with special meaning to object construction, and we can imagine that at some stage during the class composition, something got interested in whether the class had one (in this case, it’s the bit of code that creates a build plan, in order to optimize object instantiation).

At the start of the post, I used the term meta-circularity. If you weren’t sure what it meant, you’re now in a position to understand it. Here, we wrote a Perl 6 class to extend the meaning of Perl 6 classes. Meta-circularity is very simply the property of being able to use a language to extend itself, rather than having to do so by going and writing some other special or lower-level language to do so. And I’m really happy that I’ve been able to tie up the last few loose ends so that we can start to do that in the nom branch now.

Posted in Uncategorized | 1 Comment

July: Beijing Perl Workshop, vacation and hacking

It’s been an interesting month. I started it over in Beijing, for the Beijing Perl Workshop. It’s the first Perl event that I’d been to in China, and it was a great experience. People were very friendly and welcoming, the venue was nice and cool (good job, since I had a hard time coping with the Beijing summer heat), I had a good audience and good response to my talks, and the meals before and after it were great too. I gave two full-length talks, plus a lightning talk:

I got to see various things in Beijing. I avoided a couple of the most famous attractions – I saw them last time I was in Beijing, and they’re incredibly crowded mid-summer – and instead enjoyed some of the still wonderful, but maybe slightly lesser known ones. I managed to get a decent bit of hacking in too, mostly because I simply can’t handle being outside for too long in high temperature and humidity. Happily, I had a hotel that provided both wired and wireless internet with the room, and a couple of free beers a day too!

Anyway, that was my fun conference trip of the month. This was also the month where I took my one totally laptop-free vacation of the year. That was just the mental and physical break I needed from the hacking, though of course I couldn’t totally break away from things and ended up reading The Art of the Metaobject Protocol on the journey there and back. I’d read a couple of extracts from it before, but this was the first time through the whole book. It was decidedly worthwhile, though it shows its age a little at times too! ;-)

Amongst the trips, I’ve got some decent work in on the “nom” branch. It’s going well – a look at the excellent new compiler features page shows that there’s not too many areas left where we lack things (at least on that list) that master has. On some features, we’ve decidedly pulled ahead of master too. I’ll write up some more detailed news soon, but overall, we’re making good progress.

Excitingly, YAPC::Europe is now not far off too! Last year I had one talk, so it was relatively relaxing. This year, I’ve two talks, but also a full day teaching class on OOP in Perl 6. So, I’m busily preparing for all of that too, and of course very much looking forward to seeing lots of familiar – and new – faces there. :-)

Anyways, my patches for today are pushed, and my beer glass is empty, so I guess it’s time to take a little rest.

Posted in Uncategorized | 1 Comment

Another little nom update

I was gearing up to blog a bit about the progress we’re making on the nom branch of Rakudo, when pmichaud++ swooped in with a great post about that. It nicely captures how much we’re getting done putting Rakudo back together on top of 6model. Along the way, we’re also dealing with various other deeper issues, which will let us close a bunch of tickets in RT when the branch lands. Overall, the code base is now a lot more pleasant to work with, and the factoring of the OO features is far superior to what we had in master. Another really nice thing is that lexical symbol installation is far, far neater; it sounds like a small thing, but it’s made hacking on Rakudo far more pleasant.

It’s also exciting that we’ve started to get native types in place now. I’ll warn you up front: don’t expect a speed win from them yet. We’re building towards that, but it’s non-trivial and not a priority for the nom branch; it’ll come later. On the other hand, if it’s memory savings you’re after then having tens of thousands of objects having attributes that are native ints will be way cheaper than if they had been boxed ones. That said, the boxed ones consume about a third of the memory they do in master, not to mention being three times less work for the GC. So you’ll win plenty over master even without using the natives, or any type annotations at all.

The nom branch will deliver direct performance improvements as well as lay the foundations for writing a much-needed optimizer. Even without that optimizer in place, we’re getting some nice wins. In pmichaud’s post he talked about for loops being 80% faster. Here’s a couple more little micro-benchmarks. The program:

my $i = 0;
while $i < 1000000 {
    $i = $i + 1; 
}
say $i

Runs in about 25% of the time that master takes (thus 4 times faster). And we do way better on a floating point version of this due to far better handling of numeric literals. This:

my $i = 0;
my $a = 0.0e1;
while $i < 1000000 {
    $i = $i + 1;
    $a = $a + 0.25e1
}
say $i;
say $a;

Runs in 4.5% of the time master does it in, or over 20 times faster.

Now, these improvements themselves aren’t that impressive, but they are just the ones that fall out of using the new object model, better handling of literals, various block and variable setup improvements and so forth. The exciting part will be when we start using the extra information we now have available at compile time in order to do things like compile-time resolution of multi candidates, inlining and type inference. Glancing the profiles to see where we spend time, I expect these will give us another order of magnitude improvement.

That’s all for now – time for me to get some rest. Tomorrow I’ll be flying to Beijing, to give some talks at the Beijing Perl Workshop and no doubt take in many of the wonderful attractions the Chinese capital has to offer, not least the awesome food. I have so many fond memories of when I spent a month backpacking around China, and I didn’t leave much time for Beijing then, so it’ll be nice to see the many things I didn’t have time for. And no, I won’t be vanishing from Rakudo hacking for a week; keen to look around as I’ll be, I suspect the cold-weather-loving me will probably also be keen to sit inside and hack a bit when the temperatures hit 35C or so. :-)

Posted in Uncategorized | Leave a comment

The Rakudo “nom” hacking marathon

Here in Sweden they have these things called “red days”. They’re basically days off, and June has a load of them. When I first heard the term, I wondered if it was some socialist connection, but got the much more boring answer: “it’s because they’re in red on the calendar”. :-) Anyway, with Thursday and today being red days, and Wednesday somewhat being one too, and a free weekend, there was only one thing for it: hack loads on the Rakudo “nom” branch!

The “nom” branch – short for “new object model” – is where I’m re-building a bunch of Rakudo things on top of 6model. Last time I gave an update of it here, I’d barely got going: the build procedure was updated somewhat and I was digging into a symbol handling refactor and starting to flesh out meta-objects, but there wasn’t anything you could actually take and play with. By now, while there’s still lots to do, things are starting to get interesting. :-)

Over the last 5 days, I’ve made approximately 130 commits to the Rakudo repository, and 20 to the NQP one (mostly 6model core improvements). Happily, others have also been joining in on the fun: moritz++, pmichaud++ and tadzik++ have all committed stuff in the last few days too, and they along with many others have provided useful feedback and comments. Here’s a selection of the things we now have working in the “nom” branch:

  • String and integer literals. Unlike in master, we don’t re-build boxed objects every time we need them; instead we build them once at compile time and then just reference them from the serialization context (which, amongst other things, serves as a kind of constant table).
  • Signatures. They’re not as complete as in master yet. However, a critical difference is that we build them at compile time now. In master, we build them at load time, and the compiler just keeps its own representation of them that is just enough for code generation. This change means the compiler is now dealing with the real thing, so if it wants to analyze them to do optimizations, it can just as happily work with ones from other compilation units as well as the current ones. This will be important  for implementing a wide range of optimizations in the future.
  • Class declarations work along with inheritance, method declaration and attribute declaration. The “.” sigil and rw trait for accessor generation also work.
  • Multiple dispatch of subs and methods, using the new proto semantics that master never caught up with. At the moment, declaring a proto is mandatory, but we’ll relax that before the branch lands.
  • The :U and :D type-modifiers for dispatching by definedness are now implemented (never had these in master)
  • Traits on classes and attributes. Unlike in master, we really do dispatch these at BEGIN time, using multi-dispatch now. In master, they are deferred to INIT time.  Thus we only handle the “is repr” trait in the compiler now, and none of the rest are magical any more.
  • Many basic operators for Int, Num and Str, as well as a few methods. These were mostly filled out by moritz++ and tadzik++. They’re defined using the new multis and box/unbox with 6model primitives. Note that those three types are also far more memory efficient and GC-friendly than in master.
  • Scalar binding and assignment. The setting up of containers is now rather more efficient. Binds and assigns to lexicals and attributes are type-checked at runtime; we have a primitive in place (though don’t use it yet) for a type-based optimizer to short-circuit type checks that it can prove are not needed. Note that unlike in master, binding is now a cheap operation (though assign is also decidedly cheaper, and we’ve plenty of scope for improvement on it). Note that some semantic issues with binding in master are also resolved.
  • if/unless/while and probably others that I didn’t check – we didn’t start over from scratch, so a lot of stuff we just get from it having already worked in master, or can fix up pretty quickly
  • Closures work. We’ve sometimes had…fun…getting those right in the past, so I decided to try and deal with them early. Thankfully, thanks to pmichaud++’s good ground work in this area in the past, it wasn’t so painful to do. :-)
  • Probably a few other bits that I forgot…

Of course, we’re still missing a load of things and “nom” isn’t ready to start testing anything serious on yet, but it’s exciting that so many of the primitives – including some of the tricky ones – are back in place. Of course, some tricky ones are yet to come: parametric type stuff, lists and deferral to name three of the biggies.  Happily, my supply of hacking time is looking to continue to be good for the week ahead, and others are joining in with the hacking, so I’m looking forward to another exciting week ahead. :-)

Posted in Uncategorized | Leave a comment