Problem Statement

ClojureScript was released with optimizations meant to leverage the capabilities of modern JavaScript engines. Initially ClojureScript keywords and symbols were both represented as strings with unicode prefix characters. This was to allow a small map implementation optimized for JavaScript - ObjMap. However JavaScript engines like JavaScriptCore, V8, and SpiderMonkey have advanced considerably in this time and have largely made the ObjMap optimization irrelevant. In fact ObjMap has since been replaced by ArrayMap and ArrayMap has shown better performance than ObjMap on ever engine than Firefox, and Firefox the performance is competitive.

ClojureScript as an initial step toward the possiblity of self-hosting has moved symbols into a proper type with metadata support. Keywords however remain a challenge. This is because keywords implement IFn. Currently we support this via monkey patching the native JavaScript String object. This has already shown to wreck havoc with JavaScript library interop. We want a real keyword type to remove this problem but we need to consider our avenues.

Possible Solutions

Emit keyword constructors everywhere

Benefits:

simple, and similar to how we already emit Symbols

Tradeoffs

degraded performance due to increased allocations

keywords are extremely common in Clojure

Constant optimization

Benefits

efficient, we get the benefits of the above, but we allocate a keyword only once

consider something as common as `:else`

Tradeoffs

more complex to implement

need to introduce a new equality operator `keyword-identical?` since keywords parsed from EDN will not be identical?

creating a lookup table with string keys is undesirable as this cannot be optimized away via Google Closure

Constant Optimization

At `analyze` in analyzer.clj we can detect constants. Each one should be entered into a map, likely a dynamic var bound to an atom containing a map. This map should map each constant's original form to a unique identifier, possibly some human readable prefix like `cljs$constant$vector$` plus a short ID of some kind. Note many constants will be composed recursively of constants.

alternatively this could be done in the compiler?

In the compiler when we emit we can instead emit a reference to a lookup table that we will generate later

In closure.clj we will emit this table after we emit core.cljs.

Initially this should be an option in order to give time to understand the over ahead this implicit initial allocation for ClojureScript programs.