4 Prepack Concepts
Nikolai Tillmann edited this page 2018-06-13 13:09:51 -07:00

Prepack Concepts

Add examples.

Residual code

By default, Prepack only attempts to analyze and optimize the global code. All referenced functions, e.g. callbacks that get installed, are called "residual function". Prepack does not attempt to analyze and optimize them by default. Prepack simply carries them over into the prepacked code, only doing some simple replacements/renamings in their bodies to reflect changes in the optimized code.

If you want to avoid that Prepack analyzes and optimizes code in an otherwise analyzed and optimized code block, use __residual or __residual_unsafe.

Abstract value

Besides concrete values, Prepack can keep track of abstract values. An abstract value is a value that is not fully known at prepack time.

More information:

Create abstract values from interpreted code via __abstract, __abstractOrNull, __abstractOrNullOrUndefined, __abstractOrUndefined. Use __isAbstract to check if a value is abstract. __assumeDataProperty

Simple object

A simple object has no property getters or setters. When unknown properties of a simple abstract object are accesses, Prepack returns fresh abstract values.

More information:

Use __makeSimple to make an object simple.

Partial object

Prepack raises an error when accessing absent properties on objects marked as partial.

More information:

Use __makePartial to make an object partial.

Final object

Any attempt to perform mutations on a final object is an error. This is similar to a frozen object, but doesn't generate an actual Object.freeze call.

Use __makeFinal to make an object final.

Pure scope

JavaScript is a very dynamic language, and it is generally difficult to statically predict what side effects some JavaScript code might have.

Prepack can evaluate code in a special mode, a "pure scope", where it makes some optimistic assumptions (see Compiler assumptions).

Code evaluated in a "pure scope" can have side effects, as long as Prepack can directly discover them by interpreting the known code.

Invoke via __evaluatePureFunction; optimized functions are also evaluated in a pure scope.

Leaking and havocing

When an abstract function is invoked, Prepack doesn't know what side effects that function might have. In general, Prepack make one significant assumption: the abstract function may not mutate any built-ins (Objects provided by, or reachable only via, the global object.)

Currently, Prepack does one of two things:

  • In a "pure scope", Prepack considers all bindings and objects reachable from the immediate call arguments as "leaked", and Prepack "havocs" them. This means that Prepack allows the function to mutate bindings and reachable objects, and any subsequent reads will have unknown values, and Prepack will generate code that reads the latest value from memory. When generating code, Prepack will also ensure that all leaking bindings and objects have the values as they were at the time of the call.
  • Otherwise, Prepack insists that the arguments of the function are frozen if they are objects. In any case, Prepack assumes that no objects known to Prepack are mutated by the function call.

Optimized function

By default, Prepack only optimizes the global code. You can instruct Prepack to optimize particular functions. Prepack evaluates those function in a "pure scope", making certain assumptions about the function's behavior, and assuming that the state of all built-ins at the time when the optimized function gets called is exactly the same state as it was at the end of global code evaluation.

More information:

Use __optimize in analyzed code to instruct Prepack to optimize a function.

Effects

“Effects” is an internal data-structure that encodes anything a piece of JavaScript code (an AST node) could have done.

More information: