Camil Demetrescu  over 8 years ago

Commit id: cb2bc6cf8e018d5fd53c71701afaca1d49c7b416

deletions | additions      

       

Lameed and Hendren~\cite{lameed2013feval} proposed two dynamic techniques for optimizing \feval\ instructions in McVM: {\em JIT-based} and {\em OSR-based} specialization. Both attempt to optimize a function $f$ that contains instructions of the form \feval$(g,...)$, leveraging information about $g$ and the type of its arguments observed at run-time. The optimization produces a specialized version $f'$ where \feval$(g,x,y,z...)$ instructions are replaced with direct calls of the form $g(x,y,z,...)$.   The two approaches differ in the points where code specialization is performed. In JIT-based specialization, $f'$ is generated when $f$ is called. In contrast, the OSR-based method interrupts $f$ as it executes, generates a specialized version $f'$, and resumes from it.Another technical difference, which has substantial performance implications, is the representation level at which optimization occurs. When a function $f$ is first compiled from MATLAB to IIR and then to IR, the functions $g$ it calls via \feval\ are unknown and the type inference engine is unable to infer the types of their returned values. Hence, these values must be kept boxed in heap-allocated objects and handled with slow generic instructions in the IR representation of $f$ (suitable for handling different types). The JIT method works on the IIR representation of $f$ and can resort to the full power of type inference to infer the types of the returned values of $g$, turning the slow generic instructions of $f$ into fast type-specialized instructions in $f'$. On the other hand, OSR-based specialization operates on the IR representation of $f$, which prevents the optimizer from exploting type inference. As a consequence, for $f'$ to be sound, the direct call to $g$ must be guarded by a condition that checks if $g$ and the type of its parameters remain the same as observed at the time when $f$ was interrupted. If the guard fails, the code falls back to executing the original \feval\ instruction.  Another technical difference, which has substantial performance implications, is the representation level at which optimization occurs in the two approaches. When a function $f$ is first compiled from MATLAB to IIR, and then from IIR to IR, the functions $g$ it calls via \feval\ are unknown and the type inference engine is unable to infer the types of their returned values. Hence, these values must be kept boxed in heap-allocated objects and handled with slow generic instructions in the IR representation of $f$ (suitable for handling different types). The JIT method works on the IIR representation of $f$ and can resort to the full power of type inference to infer the types of the returned values of $g$, turning the slow generic instructions of $f$ into fast type-specialized instructions in $f'$. On the other hand, OSR-based specialization operates on the IR representation of $f$, which prevents the optimizer from exploting type inference. As a consequence, for $f'$ to be sound, the direct call to $g$ must be guarded by a condition that checks if $g$ and the type of its parameters remain the same as observed at the time when $f$ was interrupted. If the guard fails, the code falls back to executing the original \feval\ instruction.  JIT-based specialization is less general than OSR-based specialization, as it only works if the \feval\ argument $g$ is one of the parameters of $f$. $f$, but is substantially faster due to the benefits of type inference.  %However, OSR-based specialization is substantially slower for two main reasons: 

%\item Guard computation in $f'$ can be rather expensive, as it may require checking many parameters.  %\end{enumerate}  \noindent Our approach combines the flexibility of OSR-based specialization with the efficiency of JIT-based specialization, answering an open question raised by Lameed and Hendren~\cite{lameed2013feval}. Similarly to OSR-based specialization, it does not place restrictions on the functions that can be optimized. On the other hand, it works at IIR (rather than IR) level as in JIT-based specialization, which makes it possible to perform type inference on the specialized code. Working at IIR level eliminates the two main sources of inefficiency of OSR-based specialization: 1) we can replace generic istructions with specialized instructions, and 2) the types of $g$'s arguments do not need to be cached or guarded as they are statically inferred. %Furthermore, since the dynamic code optimization works at IIR (rather than IR) level, type inference can replace generic istructions with specialized instructions. %, removing the main source of inefficiency of OSR-based specialization.