:: Enseignements :: Master :: M2 :: 2018-2019 :: Machine Virtuelle (et bazar autour ...) ::
[LOGO]

Lab 3b - JVM Interpreter / Optimization


The aim of this lab is to improve the JVM interpreter written for the previous lab
A source code to boot this lab is available: vm2016-lab3b.zip
A video of Mads Sig Ager (Chrome V8 team) that explains how the JavaScript is optimized in V8 .

Exercice 1 - Hidden Class and getfield

Each JSObject maintains its own HiddenClass and changes it if necessary. We can use that fact to optimize the access to a field.

  1. How the hidden class is computed ?
    When the hidden class change and why ?
    What is the invariant guarantee by the hidden class mechanism ?
  2. Explain why { x = 1, y = 2 } and { y = 2, x = 1 } doesn't share the same HiddenClass ?
  3. Modify the code of RT in order to use the hidden class mechanism to implement an inlining cache to improve the performance of the field access.

Exercice 2 - constant function call

In JavaScript, there are two kinds of function call, the constant function call when the qualified function come from the global object (so it is a constant) and the non-constant call when the qualified function come from the result of a computation on the stack.
In case of a constant function call, obviously, the function call can be optimized by calling the method handle of the JSObject directly. Here the idea is to implement a speculative optimization i.e. to install a guard in front of the call that will check that the function value taken as first argument (the value of the qualifier) will not changed. If the function value doesn't change, the fast patch can call it directly. If the function value change at some point in time, the function can be called in the slow path and the guard removed so all next calls will never check if the function is constant or not.

  1. Modify RT to install a speculative guard that check that the function value is constant.
  2. Does your code works when you call print ?
    Why print is special ?
    How to fix this issue ?
  3. In fact, we know in the Rewriter if the function call is a constant one or not, so instead of doing a speculative optimization, it's better to separate the two kinds of function call by teaching the Rewriter to emit a call to two different bootstrap methods of invokedynamic depending if the function call is constant or not. In that case, the bootstrap method corresponding to the constant function call will do the lookup so the constant function will be available when bootstrapping, avoiding to use a guard to know if the function value is constant or not.
    Note: in case of a non-constant function call, the speculative code can be kept because even if the function value comes from a value from the stack it can be considered as a constant because the code is always called with the same function. By example, this code use a non-constant function call with a function that never change (in this snippet):
      function foo(bar) {
        bar();
      }
    
      function baz() {
        print('baz');
      }
    
      foo(baz);
      foo(baz);