Dynamic scripting languages offer programmers increased flexibility by allowing properties of programs to be defined at run-time. Typically, program execution begins with an interpreter where type checks are implemented using conditional statements. Recent JIT compilers have begun removing run-time checks by specializing native code to program properties discovered at JIT time.This paper presents a novel intermediate representation for scripting languages that explicitly encodes types of variables. The dynamic representation is a flow graph, where each node is a specialized virtual instruction and each edge directs program flow based on control and type changes in the program. The interpreter thus performs specialized execution of whole programs. We present techniques for the efficient interpretation of our representation showing speedups of greater than 2x over static interpretation, with an average speedup of approximately 1.3x. MotivationScripting language virtual machines (VMs) typically compile high-level source code into an array of low-level opcodes (bytecodes). They then use a standard interpretation loop to execute the array of opcodes. Run-time type checks are implemented with either conditional statements or switch statements. Performing these type checks forms a significant portion of program execution. These costs seem unnecessary especially when we realize the same variable types are inevitably rechecked as loop iterations repeat the execution of the same block of code.Recent research has shown the advantages of type specialization in JIT compilation [19,10]. However, little research exists on the specialization of interpreters for scripting languages. We propose a scripting language representation and interpretation technique that performs specialized execution of dynamic code. We present a dynamic intermediate representation (DIR) which explicitly encodes the types of variables at each point of execution. The DIR is a flow graph, where each node is a specialized virtual instruction and each edge directs program flow based on control and type changes in the program. The proposed DIR therefore has a specialized path in the graph for every sequence of control and type changes found during execution.In this paper we present the initial development of our prototype implementation in the Lua Virtual Machine [12,13]. We present the design of our dynamic representation as well as the techniques used for its efficient interpretation. We illustrate our representation with a motivating example and present our plans for future interpreter optimizations. We compare the interpretation of our representation to the standard Lua implementation and show early speedups reaching a max of 2.13x and an average of 1.3x. We present reductions in the total number of instructions executed including reductions in conditional branches (used in interpreter type checking) as well as decreases in data and instruction cache accesses.
Virtual machines (VMs) are commonly used to implement programming languages such as Java, Python and Lua. VMs are typically implemented using an interpreter, a JIT compiler, or some combination of the two. A long-standing question in the design of VM interpreters is whether it is worthwhile to reorder the cases in the main interpreter loop to improve code locality. We investigate this phenomenon using an iterative, feedback-directed approach. We show that the ordering of the cases in the interpreter loop has a significant impact on performance on recent processors. Using hardware performance counters, we demonstrate that the performance improvement is primarily the result of indirect branch prediction, not instruction cache locality. We propose a number of strategies to achieve better orderings, and evaluate these strategies in the Python and Lua virtual machine interpreters. We show speedups of up to 40%.
Indirect jump instructions are used to implement multiway branch statements and virtual function calls in object-oriented languages. Branch behavior can have significant impact on program performance, but fortunately hardware predictors can alleviate much of the risk. Modern processors include indirect branch predictors which use part of the target address to update a global history. We present a code generation technique to maximize the branch history information available to the predictor. We implement our optimization as an assembly language transformation, and evaluate it for SPEC benchmarks and interpreters using simulated and real hardware, showing indirect branch misprediction decreases.
scite is a Brooklyn-based organization that helps researchers better discover and understand research articles through Smart Citations–citations that display the context of the citation and describe whether the article provides supporting or contrasting evidence. scite is used by students and researchers from around the world and is funded in part by the National Science Foundation and the National Institute on Drug Abuse of the National Institutes of Health.
customersupport@researchsolutions.com
10624 S. Eastern Ave., Ste. A-614
Henderson, NV 89052, USA
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
Copyright © 2024 scite LLC. All rights reserved.
Made with 💙 for researchers
Part of the Research Solutions Family.