SearcharxivSearch

arXiv subjects

Hidehiko Masuhara

Publications and source records attributed to Hidehiko Masuhara.

11 recordsLinked to original sources

A Lightweight Method for Generating Multi-Tier JIT Compilation Virtual Machine in a Meta-Tracing Compiler Framework

Meta-compiler frameworks, such as RPython and Graal/Truffle, generate high-performance virtual machines (VMs) from interpreter definitions. Although they generate VMs with high-quality just-in-time (JIT) compilers, they still lack an important feature that dedicated VMs (i.e., VMs that are developed for specific languages) have, namely \emph{multi-tier compilation}. Multi-tier compilation uses light-weight compilers at early stages and highly-optimizing compilers at later stages in order to balance between compilation overheads and code quality. We propose a novel approach to enabling multi-tier compilation in the VMs generated by a meta-compiler framework. Instead of extending the JIT compiler backend of the framework, our approach drives an existing (heavyweight) compiler backend in the framework to quickly generate unoptimized native code by merely embedding directives and compile-time operations into interpreter definitions. As a validation of the approach, we developed 2SOM, a Simple Object Machine with a two-tier JIT compiler based on RPython. 2SOM first applies the tier-1 threaded code generator that is generated by our proposed technique, then, to the loops that exceed a threshold, applies the tier-2 tracing JIT compiler that is generated by the original RPython framework. Our performance evaluation that runs a program with a realistic workload showed that 2SOM improved, when compared against an RPython-based VM, warm-up performance by 15\%, with merely a 5\% reduction in peak performance.

cs.PL

Consistent Distributed Reactive Programming with Retroactive Computation

Context: Many systems require receiving data from multiple information sources, which act as distributed network devices that asynchronously send the latest data at their own pace to generalize various kinds of devices and connections, known as the Internet of Things (IoT). These systems often perform computations both **reactively** and **retroactively** on information received from the sources for monitoring and analytical purposes, respectively. Inquiry: It is challenging to design a programming language that can describe such systems at a high level of abstraction for two reasons: (1) reactive and retroactive computations in these systems are performed alongside the execution of other application logic; and (2) information sources may be distributed, and data from these sources may arrive late or be lost entirely. Addressing these difficulties is our fundamental problem. Approach: We propose a programming language that supports the following features. First, our language incorporates reactive time-varying values (also known as signals) embedded within an imperative language. Second, it supports multiple information sources that are distributed and represented as signals, meaning they can be declaratively composed to form other time-varying values. Finally, it allows computation over past values collected from information sources and recovery from inconsistency caused by packet loss. To address the aforementioned difficulties, we develop a core calculus for this proposed language. Knowledge: This calculus is a hybrid of reactive/retroactive computations and imperative ones. Because of this hybrid nature, the calculus is inherently complex; however, we have simplified it as much as possible. First, its semantics are modeled as a simple, single-threaded abstraction based on typeless object calculus. Meanwhile, reactive computations that execute in parallel are modeled using a simple process calculus and are integrated with the object calculus, ensuring that the computation results are always serialized. Specifically, we show that time consistency is guaranteed in the calculus; in other words, consistency can be recovered at any checkpoint. Grounding: This work is supported by formally stating and proving theorems regarding time consistency. We also conducted a microbenchmarking experiment to demonstrate that the implemented recovery process is feasible in our assumed application scenarios. Importance: The ensured time consistency provides a rigorous foundation for performing analytics on computation results obtained from distributed information sources, even when these sources experience delays or packet loss.

cs.PL

Evolution Language Framework for Persistent Objects

Context: Multi-schema-version data management (MSVDM) is the database technology that simultaneously supports multiple schema versions of one database. With the technology, multiple versions of one software system can co-exist and exchange data even when the system's data structure evolves along with versions. Inquiry: While there have been developed MSVDM theories and implementations for relational databases, they are not directly applicable to persistent objects. Since persistent objects are commonly implemented by means of object-relational mapping (OR-mapping), we need a right level of abstraction in order to describe evolution of data structures and translate data accesses in between different versions. Approach: We propose a new evolution language consisting of a set of evolution operations, each denoting a modification of the source code and implicitly defining the corresponding modification to the database schema. Given the existence of multiple mapping mechanisms from persistent objects to databases, we designed the evolution language at two levels. At the abstract level, it handles scenarios such as refactoring and adding classes and fields. At the concrete level, we provide definitions for different mapping mechanisms separately, leveraging the existing database evolution language that supports MSVDM. Knowledge: Our evolution language is designed to support existing evolution operations proposed in prior work. Additionally, it introduces support for operations related to class hierarchy changes, which are not covered by previous approaches. Using our proposal, two concrete mapping mechanisms, namely, a JPA-like mapping and signal classes, can be provided separately. Furthermore, our evolution language preserves program behavior and covers common evolution operations in practice. Grounding: This work is supported by the formal definition of both the target abstract core language and the proposed evolution language, the formulation of several theorems demonstrating the soundness of our proposals, and the proofs of these theorems. Additionally, an empirical study was conducted to investigate the evolution histories of three open-source projects. Importance: To the best of our knowledge, our proposal is the first evolution language for persistent objects that supports MSVDM. Moreover, it is the first evolution language defined at an abstract level. By defining mappings separately, we can apply it to a wide range of persistent object mechanisms built on top of SQL.

cs.PL

Compilation Semantics for a Programming Language with Versions

Programming with versions is a paradigm that allows a program to use multiple versions of a module so that the programmer can selectively use functions from both older and newer versions of a single module. Previous work formalized $λ_{\mathrm{VL}}$, a core calculus for programming with versions, but it has not been integrated into practical programming languages. In this paper, we propose VL, a Haskell-subset surface language for $λ_{\mathrm{VL}}$ along with its compilation method. We formally describe the core part of the VL compiler, which translates from the surface language to the core language by leveraging Girard's translation, soundly infers the consistent version of expressions along with their types, and generates a multi-version interface by bundling specific-version interfaces. We conduct a case study to show how VL supports practical software evolution scenarios and discuss the method's scalability.

cs.PL

A Systematic Literature Review on the Impact of Formatting Elements on Code Legibility

Context: Software programs can be written in different but functionally equivalent ways. Even though previous research has compared specific formatting elements to find out which alternatives affect code legibility, seeing the bigger picture of what makes code more or less legible is challenging. Goal: We aim to find which formatting elements have been investigated in empirical studies and which alternatives were found to be more legible for human subjects. Method: We conducted a systematic literature review and identified 15 papers containing human-centric studies that directly compared alternative formatting elements. We analyzed and organized these formatting elements using a card-sorting method. Results: We identified 13 formatting elements (e.g., indentation) and 33 levels of formatting elements (e.g., two-space indentation), which are about formatting styles, spacing, block delimiters, long or complex code lines, and word boundary styles. While some levels were found to be statistically better than other equivalent ones in terms of code legibility, e.g., appropriate use of indentation with blocks, others were not, e.g., formatting layout. For identifier style, we found divergent results, where one study found a significant difference in favor of camel case, while another study found a positive result in favor of snake case. Conclusion: The number of identified papers, some of which are outdated, and the many null and contradictory results emphasize the relative lack of work in this area and underline the importance of more research. There is much to be understood about how formatting elements influence code legibility before the creation of guidelines and automated aids to help developers make their code more legible.

cs.SE

Two-level Just-in-Time Compilation with One Interpreter and One Engine

Modern, powerful virtual machines such as those running Java or JavaScript support multi-tier JIT compilation and optimization features to achieve their high performance. However, implementing and maintaining several compilers/optimizers that interact with each other requires hard-working VM developers. In this paper, we propose a technique to realize two-level JIT compilation in RPython without implementing several interpreters or compilers from scratch. As a preliminary realization, we created adaptive RPython, which performs both baseline JIT compilation based on threaded code and tracing JIT compilation. We also implemented a small programming language with it. Furthermore, we preliminarily evaluated the performance of that small language, and our baseline JIT compilation ran 1.77x faster than the interpreter-only execution. Furthermore, we observed that when we apply an optimal JIT compilation for different target methods, the performance was mostly the same as the one optimizing JIT compilation strategy, saving about 40 % of the compilation code size.

cs.PL

Threaded Code Generation with a Meta-Tracing JIT Compiler

Language implementation frameworks, e.g., RPython and Truffle/Graal, are practical tools for creating efficient virtual machines, including a well-functioning just-in-time (JIT) compiler. It is demanding to support multitier JIT compilation in such a framework for language developers. This paper presents an idea to generate threaded code by reusing an existing meta-tracing JIT compiler, as well as an interpreter design for it. Our approach does not largely modify RPython itself but constructs an effective interpreter definition to enable threaded code generation in RPython. We expect our system to be extended to support multilevel JIT compilation in the RPython framework. We measured the potential performance of our threaded code generation by simulating its behavior in PyPy. We confirmed that our approach reduced code sizes by 80 \% and compilation times by 60 \% compared to PyPy's JIT compiler on average, and ran about 7 \% faster than the interpreter-only execution.

cs.PL

A Functional Programming Language with Versions

While modern software development heavily uses versioned packages, programming languages rarely support the concept of versions in their semantics, which makes software updates more bulky and unsafe. This paper proposes a programming language that intrinsically supports versions. The main goals are to design core language features to support multiple versions in one program and establish a proper notion of type safety with those features. The proposed core calculus, called Lambda VL, has versioned values, each containing different values under different versions. We show the construction of the type system as an extension of coeffect calculus by mapping versions to computational resources. The type system guarantees the existence of a valid combination of versions for a program. The calculus enables programming languages to use multiple versions of a package within a program. It will serve as a basis for designing advanced language features like module systems and semantic versioning.

cs.PL

Amalgamating Different JIT Compilations in a Meta-tracing JIT Compiler Framework

Many modern virtual machines, such as JVMs, .NET Framework, and V8, employ a just-in-time (JIT) compiler to achieve their high-performance. There are two major compilation strategies; trace-based compilation and method-based compilation. They have their own advantages and disadvantages, so we presume that applying suitable strategies for different program parts is essential for faster execution. This paper proposes a new approach called the meta-hybrid JIT compiler framework, which combined the two strategies in a single meta-JIT compiler framework. We implemented the BacCaml framework for proof-of-concept. We also report that some programs actually ran faster by the hybrid compilation in our experiments.

cs.PL

DynaSOAr: A Parallel Memory Allocator for Object-oriented Programming on GPUs with Efficient Memory Access

Object-oriented programming has long been regarded as too inefficient for SIMD high-performance computing, despite the fact that many important HPC applications have an inherent object structure. On SIMD accelerators, including GPUs, this is mainly due to performance problems with memory allocation and memory access: There are a few libraries that support parallel memory allocation directly on accelerator devices, but all of them suffer from uncoalesed memory accesses. We discovered a broad class of object-oriented programs with many important real-world applications that can be implemented efficiently on massively parallel SIMD accelerators. We call this class Single-Method Multiple-Objects (SMMO), because parallelism is expressed by running a method on all objects of a type. To make fast GPU programming available to average programmers, we developed DynaSOAr, a CUDA framework for SMMO applications. DynaSOAr consists of (1) a fully-parallel, lock-free, dynamic memory allocator, (2) a data layout DSL and (3) an efficient, parallel do-all operation. DynaSOAr achieves performance superior to state-of-the-art GPU memory allocators by controlling both memory allocation and memory access. DynaSOAr improves the usage of allocated memory with a Structure of Arrays data layout and achieves low memory fragmentation through efficient management of free and allocated memory blocks with lock-free, hierarchical bitmaps. Contrary to other allocators, our design is heavily based on atomic operations, trading raw (de)allocation performance for better overall application performance. In our benchmarks, DynaSOAr achieves a speedup of application code of up to 3x over state-of-the-art allocators. Moreover, DynaSOAr manages heap memory more efficiently than other allocators, allowing programmers to run up to 2x larger problem sizes with the same amount of memory.

cs.PL

Proactive Empirical Assessment of New Language Feature Adoption via Automated Refactoring: The Case of Java 8 Default Methods

Programming languages and platforms improve over time, sometimes resulting in new language features that offer many benefits. However, despite these benefits, developers may not always be willing to adopt them in their projects for various reasons. In this paper, we describe an empirical study where we assess the adoption of a particular new language feature. Studying how developers use (or do not use) new language features is important in programming language research and engineering because it gives designers insight into the usability of the language to create meaning programs in that language. This knowledge, in turn, can drive future innovations in the area. Here, we explore Java 8 default methods, which allow interfaces to contain (instance) method implementations. Default methods can ease interface evolution, make certain ubiquitous design patterns redundant, and improve both modularity and maintainability. A focus of this work is to discover, through a scientific approach and a novel technique, situations where developers found these constructs useful and where they did not, and the reasons for each. Although several studies center around assessing new language features, to the best of our knowledge, this kind of construct has not been previously considered. Despite their benefits, we found that developers did not adopt default methods in all situations. Our study consisted of submitting pull requests introducing the language feature to 19 real-world, open source Java projects without altering original program semantics. This novel assessment technique is proactive in that the adoption was driven by an automatic refactoring approach rather than waiting for developers to discover and integrate the feature themselves. In this way, we set forth best practices and patterns of using the language feature effectively earlier rather than later and are able to possibly guide (near) future language evolution. We foresee this technique to be useful in assessing other new language features, design patterns, and other programming idioms.

cs.PL