JavaScript:SpiderMonkey:LongTermPlans

From MozillaWiki
Jump to: navigation, search

The technical plans described below are long-term goals for SpiderMonkey. We aren't necessarily actively working toward completion of any of them. We do try to fix bugs in the short term, in ways that will make these plans easier, or will not get in their way.

If you're interested in any sort of architectural bug-fixing, feel free to work on any of these projects. Some are easier, some are harder and further-reaching, some would have been done already but for their requiring wider-spread changes, without immediate gain. For more details on any of these plans, ask questions in #jsapi.

Object representation

Empower proxies

Proxies right now are highly entangled with the engine. Working with them often requires diving into friend APIs. As we make no promises about friend APIs remaining anything close to stable, this makes it tricky to use them. We want to gradually change the JSAPI so that if you want an object with any sort of "special" behavior, you implement it as a proxy.

As part of this plan, JSClass will gradually die. The idea of classes is in the middle of deprecation in ECMAScript, so this is a natural step to make. We will still support objects with customized property-lookup, property-getting, property-setting, etc. behavior. These will simply be hooks defined as part of the proxy definition interface, not tied to something named JSClass.

Replace the property lookup mechanism with [[GetOwnProperty]]

ECMAScript speaks in terms of properties existing as descriptors, that exist/are owned by a single object. This is similar to, but not quite the same, as the current lookupProperty mechanism. We have a bit of work to do to change things so that when someone requests a property, instead of an opaque pointer, they receive (or have filled in) a property descriptor structure.

Split property/element storage

...

VM

Remove JSContext as a concept

Historically a JSContext included state necessary to run JS code. These days, most such state is instead stored in JSRuntime, and some state is stored per-compartment or per-global object or per-zone. If we can move all such information out of JSContext, we should be able to get rid of it entirely. JSRuntime or global/compartment-centric methods would expose all the same information.

Add a warning mechanism distinct from the error-reporting mechanism

Reporting a warning right now requires creating an error type, an error message reporter, and other inanities. Warnings should be reporting in a distinct manner from exceptions and shouldn't use the same overloaded mechanism.

Remove error reporting, replace it with exception-catching mechanisms

We currently have both error-reporting, and exception-throwing, error mechanisms. Two is too many. We need to come up with a coherent story for how to deal with all of this, that plays naturally to JS semantics. That probably means that errors should be dealt with only in terms of exception objects. And as far as extracting the information currently in a JSErrorReport goes, that should probably be exposed through a method that takes in a value/object and returns the right data if a usable Error object was passed, or some sort of plausible, partial substitute if not.

Remove JSPropertyOp and JSStrictPropertyOp

Having multiple kinds of accessor properties -- the ECMAScript form, and ones with these C++ function-pointer types -- is all sorts of complicated. We should get rid of these types and have all properties be completely understood by, and mappable into, the ECMAScript system. If a property type that's a native C++ function pointer is desired, it should be JSNative -- whose semantics map straightforwardly onto those defined by ECMAScript.

We've largely gotten rid of property op uses in Gecko, but there's still a bit more work to do before we could make this step and remove the idea completely. Particularly, there are a few internal uses of property ops in SpiderMonkey that will require careful work to address, before we can remove property ops completely.

  • bug 570568? - Calling JSPropertyOps against objects not of the corresponding class has bad human factors

JIT

Refactor CodeGenerator to clearly separate architecture-agnostic/specific methods

Cross-backend CodeGenerator methods are implemented in all the separate backends, now (or sometimes in x86-shared backends). These methods are freely intermixed with methods defined only for a single architecture. If we threw some templates, protected inheritance, etc. at this, it should be possible to separate cross-architecture (but possibly defined in architecture-specific files) methods from architecture-specific methods. It's unclear how this could be done. Maybe private inheritance, plus using statements in the architecture-specific CodeGenerator base classes? This problem (of writing a patch, only to find on submission to try that an arch-specific method was mistakenly used) crops up pretty often for new-ish JIT hackers, so it'd be nice to fix it.

JSAPI improvements

Create a clean, fully-C++ API

Most of the JSAPI is old, C-style JS_* functions. These functions' APIs often aren't particularly simple, clean ways to implement those behaviors. A pleasant C++ API that reads more simply, and doesn't necessarily expose operations through hundreds of freestanding methods, would be nice. We've incrementally introduced such APIs at lower levels -- see for example JS::Value -- but we haven't done anything yet at higher levels. Mostly this is a matter of inertia, and of API design being a bunch of hard work that's off the critical path for Firefox. We'd probably welcome help from embedders and the like with special interest and expertise in designing nice, clean C++ APIs for this stuff. (Do note, however, that we still require an exception-safe API -- true/false return values to indicate success will still probably be necessary.)

Replace jschar with char16_t (FIXED)

Recent changes mean that SpiderMonkey's historical jschar type is identical to char16_t (an emulated typedef in older compilers). We should cut out the middle man and just use char16_t directly. This is mostly a large search-and-replace operation on Gecko and JSAPI headers.

Replace const char* with const char16_t*

C string APIs were historically pretty convenient. These days, though, with the recent addition of MOZ_UTF16, it's easy to write UTF-16 strings in source code. APIs that take C strings now, should be converted to take 16-bit-wide strings and lengths. This potentially eliminates an inflate operation and reduces the number of different string types to think about. It also makes non-ASCII strings be handled by the default case, which is good for correctness.

Remove shortids and tinyids (FIXED)

In ECMAScript, properties are referred to by strings, full stop. ES6 and our implementation add some flourishes to this (symbols/property keys, access by uint32_t), but it remains the case that properties have only one name, and that name corresponds to the concept defined by ECMAScript, or a pure transformation of it.

Allowing properties to exist using a different name than the canonical ECMAScript name introduces a fair bit of complexity into SpiderMonkey. (And if there's a part of SpiderMonkey that absolutely can't afford extra complexity, it's our property representation/lookup code paths.) Doing so doesn't appear to have a memory cost, because the extra name fits into what would otherwise be padding. But it's extra work to keep track of it, extra work to preserve it, extra work to distinguish properties that differ only in their shortid -- and all this only for the benefit of users of JSPropertyOp and JSStrictPropertyOp, which as previously noted we want to remove.

Removal of the jsval typedef in favor of JS::Value (FIXED)

jsval and JS::Value are identical. As part of moving more fully to cleaner C++, we should get rid of jsval. Doing so requires cleaning all use of jsval from Gecko -- not hard, but again, just not on anyone's critical path. (Embedders can easily adapt to this by adding typedef JS::Value jsval; to their code as a temporary fix, if needed.)

  • bug 842186 - Replace all use of jsval with JS::Value

JSNative's signature will be changed to accept const JS::CallArgs&

The current arguments to JSNative are pretty error-prone. Passing a single class-based argument, that asserts correctness of use, would be preferable -- for correctness checking for sure, and possibly for greater performance (passing one argument being faster than passing two, potentially). We've introduced a helper structure, JS::CallArgs, for this purpose, that can be created from the arguments passed to a JSNative. It's trivial to create such a structure inside every method, then only interact with the arguments through that. New code should use JS::CallArgs exclusively.

Once all of Gecko has switched to JS::CallArgs, we can consider switching JSNative to use it as a parameter -- probably const CallArgs& -- with a minimum of effort. (Unfortunately this effort will involve touching every function implementing the JSNative signature. At least with every function already working in terms of JS::CallArgs, such a patch won't need to touch function logic when it does so.) This is a prerequisite to any such experimentation, or changes to JSNative.