• Keine Ergebnisse gefunden

Eager versus Lazy Envelope Call Insertion

Chapter 1 Overview

4.3 Optimized Dynamic Aspect Deployment

4.3.1 Eager versus Lazy Envelope Call Insertion

Eager Envelopes. When envelope calls are eagerly inserted into the appli-cation’s code, an additional indirection is introduced into the appliappli-cation’s bytecode. To ensure a high performance of the application, this indirection is optimized away for those envelopes which do not contain any advice.

The baseline compiler provided by the Jikes RVM does not offer the possibility to inline method calls. Consequently, the indirections are not removed from baseline compiled methods. But methods that are hot will be promoted to a higher level of optimization at which envelopes are optimized accordingly. With the exception of the envelope call, the baseline compiler generates the same machine code as it does in the absence of envelopes.

Jikes’ optimizing compiler rewrites the intermediate code in multiple passes. In this prototype, the first pass is enhanced to specially handle en-velopes such that the intermediate code is equivalent to what the unmodified compiler generates. Consequently, subsequent optimizations are carried out the same way in both cases.

The decision whether a method is inlined or not is made by the so-called inliner and depends on several conditions. The inliner uses heuristics—some of them are discussed in the following—to determine whether a methodcallee should be inlined into another method caller. By construction it is ensured that enveloped methods as well as accessor envelopes are always monomor-phic, i.e., can always be inlined into their caller. Although the inliner can

Optimized Dynamic Aspect Deployment

also detect this, some of its heuristics prevent it from always making these decisions. Hence, it is modified to always decide to inline enveloped methods and accessor envelopes. When the inliner decides to inline an envelope, it is further modified to decide that a guard must be applied, to facilitate dy-namic aspect deployment. For the implementation of this prototype, three inlining heuristics are of interest: inline size, inline sequence length andfield analysis.

The inliner considers the size of the called method when deciding whether or not to inline it; the shorter the method the more beneficial is inlining. For envelopes the inliner would make its decision based on the proxy method’s bytecode size. Proxies interfere with size estimates because the proxy itself is small, but it is guaranteed to have a (possibly large) enveloped method inlined into it. Thus, the inliner is modified so that it does not inline a proxy unless it would have inlined the corresponding enveloped method.

Figure 4.3 illustrates why the inline sequence heuristic needs to be modi-fied in the presence of envelopes. It sketches the intermediate code generated by the optimizing JIT compiler when compiling a method m. On the left hand side, the generated code without envelopes is shown. On the right hand side, the code is shown as compiled in the presence of envelopes. The inline sequence begins with the method compiled in the first place, i.e., m in the example. When the compiler reaches the call to o (marked by an asterisk) without envelopes the inline sequence is (m, n) and has the length two. When the same code is compiled with envelopes, the inline sequence at the invocation of o is (m’, m, n’, n) where m’ and n’ are the (renamed) enveloped methods and m and n are their proxy envelopes. Thus, the inline sequence length is now four instead of two. If two is the maximum inlin-ing depth, o would be inlined in the case without envelopes and not inlined with envelopes. In the prototype, proxy methods are optimized away when they do not contain advice. As a consequence, unadvised envelopes do not increase the size of the compiled code and, therefore, the inline sequence length heuristics is adjusted such that they are not counted.

Finally, for values resulting from a field read access the optimizing com-piler applies special analyses on field types which, in turn, are used by the inliner. As field accesses are replaced by calls to accessor methods, the anal-ysis is modified to be also applicable to accessor envelope calls and to lead to the same result as it would have had when applied to the access itself.

The adaptive optimizing system (AOS) also is modified in the prototype.

Before optimization and inlining occur, envelopes execute as explicit method calls which are profiled by the AOS. The existence of a large number of enve-lope calls pollutes the profile data, causing compilation to occur at different times than usual, and delays optimization of some of the application

meth-Optimized Dynamic Aspect Deployment

Inlining without

envelopes Inlining with

envelopes void m() {

n();

}

void n() { }o();

void m() {

m’();

}

void m’() { ...

n();

}...

void n() { n’();

}

void n’() { }o();

Figure 4.3: Inline sequence without and with envelopes.

ods. As a result, startup time is degraded and the application has to run longer before it reaches the fully optimized state.

To cope with this problem, Jikes RVM’s profiling facility is modified so that if an enveloped method is sampled at runtime the sample is credited to the proxy envelope instead. As a result, the proxy is identified as a hot method, re-compiled with optimizations, and the inlining modifications en-sure that the (hot) enveloped method is inlined into the proxy, thus compiled with the same optimizations.

Lazy Envelopes. The approach of eager envelopes requires little infrastruc-ture provided by the virtual machine. It works with any kind of speculative inlining. However, only the final performance is comparable to that of execut-ing an application without envelopes. Avoidexecut-ing the slow start-up due to un-optimized envelopes in baseline compiled code, can be achieved by inserting the envelope indirection lazily: envelopes are created at class loading-time, but are not invoked if they do not contain advice. When the JIT compiler compiles a method call or a field access, it determines if the applicable enve-lope method contains advice. Only in this case, the JIT compiler generates a call to the envelope method. Otherwise, code for directly calling the en-veloped method or accessing the field is generated. Thus, if no aspects have been deployed, the executing program is essentially identical to the original program without envelopes. However, to enable weaving in the envelopes and to let them take effect requires a sophisticated invalidation mechanism.

When advice is deployed at runtime, it is woven into the envelope method that corresponds to the relevant method or field access just like in the eager envelopes approach. But, since envelopes are no longer being called by de-fault, all code performing either a call to the advised method or an access of

Optimized Dynamic Aspect Deployment

the advised field must be dynamically updated to invoke the newly advised envelope instead.

Because the envelope indirection is also missing in the baseline compiled code, both the baseline and optimizing compiler are modified to enable injec-tion of the indirecinjec-tion into the compiled code. Therefore, both compilers have to record dependency information for all compiled calls and field accesses, to identify code to be updated when an advice is deployed.

Lazy envelopes ultimately achieve the same result as eager envelopes, but the lazy approach is operating at a lower level and is manually per-forming a number of tasks handled automatically in the eager approach.

With eager envelopes, the inliner handles the inlining of envelopes, which automatically provides the necessary dependency tracking and invalidation mechanism. However, lazy envelopes are more effective at eliminating the overhead of envelopes, since envelopes are essentially eliminated from the system until needed; no modifications to the inlining heuristics and adaptive optimization system are needed. In addition, the code generated by the base-line compiler no longer contains unnecessary envelope calls, which minimizes overhead during program start-up.