I see, thank you! The array approach is also interesting, though hopefully 
I can avoid it, since it will probably make the code harder to maintain.

On Monday, April 14, 2025 at 10:27:26 PM UTC+3 Ben Noordhuis wrote:

> On Mon, Apr 14, 2025 at 6:06 PM GregRos <work....@gmail.com> wrote:
> >
> > I'm developing a new version of my parser library (https://parjs.org/), 
> so I'm writing kind of low-level CPU-bound code.
> >
> > It's a parser combinator library, so parsers are composed of building 
> blocks and combinators that work like a tree. Each combinator "class" has 
> different logic and properties.
> >
> > However, their external interface is the same, with a single `parse` 
> method that applies whatever logic the class has.
> >
> > A combinator like "many" can potentially apply any parser repeatedly, 
> and so different instances will have different parser inputs. For example, 
> you can have:
> >
> > new Many(new Digit()) parses multiple digits
> > new Many(new String("abc")) parses multiple literals "abc"
> > new Many(new Letter()) parses multiple letters
> >
> > Inside the code of `Many`, you'd have a call like `child.parse(input)`
> >
> > In the previous version, profiling and diagnostics revealed that 
> performance was dominated by function call overhead, and almost all the 
> method calls turned out to be megamorphic because when `child.parse` was 
> called in the same location, `child` was a different type of object.
> >
> > In this new version, I'm trying to figure out if it's possible to avoid 
> that. My idea is to pass around functions instead of objects with methods. 
> By doing this, I'm hoping that method resolution can be avoided, and that 
> the code won't need to be megamorphic because all the objects are 
> sufficiently similar.
> >
> > These functions still need internal parameters, which includes input 
> parser objects.
> >
> > The nicest idea is to use closures.
> > But another solution could be doing something like 
> `parser.parse.bind(parser)` and passing that around.
> >
> > Will something like this allow me to avoid megamorphism? Is there 
> something else I can do?
>
> Yes, closures will work for that. Other approaches that can work (but
> are maybe less robust, more cumbersome, etc.) are:
>
> 1. using arrays instead of objects (indexed vs. named properties) so
> you don't get the "exploding hidden classes" thing; caveat: not 100%
> foolproof, V8 has different array representations
>
> 2. guarding property accesses behind instanceof checks to keep inline
> caches monomorphic: if (obj instanceof Foo) obj.x = 42; else if (obj
> instanceof Bar) obj.x = 42; - the instanceof checks can become
> expensive(ish) though
>

-- 
-- 
v8-users mailing list
v8-users@googlegroups.com
http://groups.google.com/group/v8-users
--- 
You received this message because you are subscribed to the Google Groups 
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-users+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/v8-users/06f5f800-8094-45f3-8af9-6b2ee4336624n%40googlegroups.com.

Reply via email to