PSA: JSC interface is changed from passing ExecState* to passing lexical JSGlobalObject*

# Yusuke Suzuki (14 hours ago)

Hello WebKittens,

We did long-wanted refactoring: JSC runtime functions start getting lexical realm JSGlobalObject instead of ExecState. Since this slightly changes how we interact with JSC, we would like to show what is changed.

This refactoring involves several changes.

  1. JSC interface starts getting JSGlobalObject instead of ExecState.
  2. ExecState is consistently renamed to CallFrame. And it is used only when CallFrame is actually required (accessing arguments etc.) And the name `ExecState` is removed from the tree.

Previously we are using ExecState*. But this caused multiple problems so far. Here is the motivation behind this change.

  1. Fix so many bugs in JSC, and makes JSC’s inlining finally sane

ExecState is simply wrong in various cases. We are getting lexical JSGlobalObject by calling ExecState::lexicalGlobalObject(). But it returns wrong value if the current function is inlined in DFG/FTL. ExecState is pointing the whole function’s CallFrame. And returned JSGlobalObject* is lexical JSGlobalObject of top-most function. If inlined function has different lexical JSGlobalObject from the top-most one, we are getting wrong JSGlobalObject. Getting `CodeBlock` from ExecState is also wrong. We had multiple places that is getting CodeBlock to get strict-mode flag, and this code does not consider about inlining. Instead, we pass lexical JSGlobalObject explicitly. This change makes fixing these issues very easy.

  1. Clear separation between CallFrame and JSGlobalObject, making API clean

CallFrame is only used when we actually want to access CallFrame (to get arguments etc.). Previously, we are using CallFrame as an useful abstraction to offer an access to various things including lexical JSGlobalObject. But since this is CallFrame, it exist only after executing some JS code. So if we want to call JSC C++ runtime functions without JS code (calling JS runtime things directly from C++ world), we do not have ExecState at all at that time. To make it OK, we invented globalExec(), which is saying CallFrame, but in fact, it was not a CallFrame. It exists only for calling these C++ runtime functions when CallFrame does not exist yet. This is ugly and we really wanted to remove this. It is now finally removed in 99% of code. Through this refactoring, we found multiple places that is accessing |thisValue| etc. while it should not have any CallFrame. So they are accessing wrong thing because CallFrame offers the way to access the wrong thing. We should not offer such a wrong abstraction. And now, we can pass lexical JSGlobalObject explicitly. Previously, we do not have a good way to create ExecState conveniently. So we just randomly pass accessible ExecState to C++ runtime functions. This looks working, but it is wrong when we consider about lexical JSGlobalObject carefully. Now interface explicitly requires lexical JSGlobalObject, so we can pass the correct JSGlobalObject* explicitly.

  1. Steps towards putting all JSCells into IsoSubspace

JSC had very fancy hack: all callable JS cells must be small enough (it can be allocated in MarkedBlock). This was originally required to make ExecState::vm() function super fast. We are calling this so frequently and we needed to keep it fast. And we can make it fast if we have such a weird guarantee. But it turned out that this assumption is not good one for the world putting all JSCells into IsoSubspace. We would like to introduce some optimizations to IsoSubspace to make it scalable to various JSCell types. But this optimization requires that the above assumption is discarded. To make it work, we do this refactoring and now we get VM& from JSGlobalObject instead of ExecState.

I’m now doing some follow-up work which makes things more solid. And I’m planning to do some minor refactoring, like, naming things consistently etc. I’m also planning to fix various bugs found while doing this refactoring. And…, this change paves the way to (3), which I’m currently focusing on :)

Best

Contact us to advertise here

Want more features?

Request early access to our private beta of readable email premium.