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.