18 research outputs found

    Uniform Representation of Data Types in Polymorphic C.

    Full text link

    Call Graphs for Languages with Parametric Polymorphism

    Get PDF
    The performance of contemporary object oriented languages depends on optimizations such as devirtualization, inlining, and specialization, and these in turn depend on precise call graph analysis. Existing call graph analyses do not take advantage of the information provided by the rich type systems of contemporary languages, in particular generic type arguments. Many existing approaches analyze Java bytecode, in which generic types have been erased. This paper shows that this discarded information is actually very useful as the context in a context-sensitive analysis, where it significantly improves precision and keeps the running time small. Specifically, we propose and evaluate call graph construction algorithms in which the contexts of a method are (i) the type arguments passed to its type parameters, and (ii) the static types of the arguments passed to its term parameters. The use of static types from the caller as context is effective because it allows more precise dispatch of call sites inside the callee. Our evaluation indicates that the average number of contexts required per method is small. We implement the analysis in the Dotty compiler for Scala, and evaluate it on programs that use the type-parametric Scala collections library and on the Dotty compiler itself. The context-sensitive analysis runs 1.4x faster than a context-insensitive one and discovers 20\% more monomorphic call sites at the same time. When applied to method specialization, the imprecision in a context-insensitive call graph would require the average method to be cloned 22 times, whereas the context-sensitive call graph indicates a much more practical 1.00 to 1.50 clones per method

    Interoperation between Miniboxing and Other Generics Translations

    Get PDF
    Generics allow programmers to design algorithms and data structures that operate in the same way regardless of the data used by abstracting over data types. Generics are useful as they improve the programmer鈥檚 productivity by raising the level of abstraction, which in turn leads to reducing code duplication and uniform interfaces. However, as data on the low-level comes in different shapes and sizes, it is not a trivial job of compiler to bridge the gap between the uniform interface and the non-uniform low level implementation. Different approaches are used for generics translation and all of them can be categorized either into homogeneous or heterogeneous group. The characteristic of homogeneous translations is that all different data representations are transformed into an identical representation and use the same low-level code for this purpose. In the heterogeneous translations, code is duplicated and adapted for each incompatible data type. From a programmer鈥檚 point of view, there should be no difference between a generic method or class compiled using some homogeneous or heterogeneous translation. Therefore, the programmer can combine different types of translations together on different parts of the code and the program has to be correct. But, as different generics translations are implemented in different ways, interoperation between them introduces noticeable slowdowns as values need to be converted to the foreign object鈥檚 desired representation, incurring significant performance losses. In this thesis, it will be explored why slowdowns happen when different translations interact together and proposed the ways how they can interoperate more efficiently. Proposed approaches are implemented and their effectiveness is presented by benchmarking the implementation

    Late Data Layout: Unifying Data Representation Transformations

    Get PDF
    Values need to be represented differently when interacting with certain language features. For example, an integer has to take an object-based representation when interacting with erased generics, although, for performance reasons, the stack-based value representation is better. To abstract over these implementation details, some programming languages choose to expose a unified high-level concept (the integer) and let the compiler choose its exact representation and insert coercions where necessary. This pattern appears in multiple language features such as value classes, specialization and multi-stage programming: they all expose a unified concept which they later refine into multiple representations. Yet, the underlying compiler implementations typically entangle the core mechanism with assumptions about the alternative representations and their interaction with other language features. In this paper we present the Late Data Layout mechanism, a simple but versatile type-driven generalization that subsumes and improves the state-of-the-art representation transformations. In doing so, we make two key observations: (1) annotated types conveniently capture the semantics of using multiple representations and (2) local type inference can be used to consistently and optimally introduce coercions. We validated our approach by implementing three language features as Scala compiler extensions: value classes, specialization (using the miniboxing representation) and a simplified multi-stage programming mechanism

    Contribuci贸n al estudio de sistemas de identificaci贸n en bovinos basados en identificaci贸n electr贸nica y ADN para su aplicaci贸n a la trazabilidad y a la gesti贸n de sistemas ganaderos

    Get PDF
    La presente tesis tiene por objetivo general contribuir al desarrollo de un sistema de identificaci贸n del ganado bovino en un sistema pastoril de producci贸n, para ser aplicado a la gesti贸n del sistema de producci贸n y a la trazabilidad, basado en el uso conjunto de la identificaci贸n electr贸nica por radiofrecuencia y de marcadores moleculares. Se plante贸 evaluar el funcionamiento de distintos tipos de identificadores electr贸nicos y de lectores de radiofrecuencia en condiciones de trabajo extensivo, desarrollar un sistema para transferir marcadores moleculares como c贸digo de identificaci贸n indeleble de cada animal a identificadores electr贸nicos y dise帽ar e implementar un sistema de aplicaci贸n pr谩ctica para la captura y el tr谩fico autom谩tico de datos, generando informaci贸n para la gesti贸n del proceso de producci贸n. Se evaluaron y compararon las p茅rdidas de dispositivos identificatorios. Se evalu贸 el funcionamiento de un lector fijo, determinando el posicionamiento 贸ptimo de la antena para maximizar la eficiencia de lectura de las distintas presentaciones de identificadores. Se program贸 un lector port谩til para registrar los eventos relevantes de ocurrencia con los animales libres en el campo. Se desarroll贸 un programa que permite grabar en un identificador electr贸nico determinados marcadores moleculares de un individuo, generando as铆 una identificaci贸n gen贸mica del mismo. Se desarroll贸 un software que interact煤a con identificadores, lectores, y otros instrumentos de trabajo generando informaci贸n para la gesti贸n del sistema productivo. Los dispositivos de identificaci贸n y los lectores podr铆an ser utilizados en los animales en condiciones de producci贸n de la Argentina. Se demostr贸 la posibilidad de uso de un lector port谩til, si bien con algunas restricciones, con animales libres en el campo registrando los eventos relevantes para la gesti贸n y trazabilidad. Se desarroll贸 un software espec铆fico para generar informaci贸n que permita lograr este objetivo.Facultad de Ciencias Veterinaria

    Compiling Scala for Performance

    Get PDF
    Scala is a new programming language bringing together object-oriented and functional programming. Its defining features are uniformity and extensibility. Scala offers great flexibility for programmers, allowing them to grow the language through libraries. Oftentimes what seems like a language feature is in fact implemented in a library, effectively giving programmers the power of language designers. The downside of this flexibility is that familiar looking code may hide unexpected performance costs. It is important for Scala compilers to bring down this cost as much as possible. We identify several areas of impact for Scala performance: higher-order functions and closures, and generic containers used with primitive types. We present two complementary approaches for improving performance in these areas: optimizations and specialization. Compiler optimization can bring down the cost through a combination of aggressive inlining of higher-order functions, an extended version of copy-propagation and dead-code elimination. Both anonymous functions and boxing can be eliminated by this approach. We show on a number of benchmarks that these language features can be up to 5 times faster when properly optimized, on current day JVMs. We propose a new approach to compiling parametric polymorphism for performance at primitive types. We mix a homogeneous translation scheme with user-directed specialization for primitive types. Type parameters may be annotated to require specialization of code depending on them. We propose definition-site specialization for primitive types, achieving separate compilation and no boxing when both the definition and call site are specialized. Specialized classes are compatible with unspecialized code, and specialization agnostic code can work with specialized instances, meaning that specialization is opportunistic. We present a formalism of a small subset of Scala with specialization and prove that specialization preserves types. We implemented this translation in the Scala compiler and report on improvements on a set of benchmarks, showing that specialization can make programs more than two times faster

    Delivering the benefits of persistence to system construction and execution

    Get PDF
    In an orthogonally persistent programming system the longevity of data is independent of its other attributes. The advantages of persistence may be seen primarily in the areas of data modelling and protection resulting from simpler semantics and reduced complexity. These have been verified by the first implementations of persistent languages, typically consisting of a persistent store, a run-time system and a compiler that produces programs that may access and manipulate the persistent environment. This thesis demonstrates that persistence can deliver many further benefits to the programming process when applied to software construction and execution. To support the thesis, a persistent environment has been extended with all the components necessary to support program construction and execution entirely within the persistent environment. This is the first known example of a strongly-typed integrated persistent programming environment. The keystone of this work is the construction of a compiler that operates entirely within the persistent environment. During its construction, persistence has been exploited in the development of a new methodology for the construction of applications from components and in the optimisation of the widespread use of type information throughout the environment. Further enhancements to software construction and execution have been developed that can only be supported within an integrated persistent programming environment. It is shown how persistence forms the basis of a new methodology for dynamic optimisation of code and data. In addition, new interfaces to the compiler are described that offer increased functionality over traditional compilers. Extended by the ability to manipulate structured values within the persistent environment, the interfaces increase the simplicity, flexibility and efficiency of software construction and execution. Reflective and hyper-programming techniques are also supported. The methodologies and compilation facilities evolved together as the compiler was developed and so the first uses of both were applied to one another. It is these applications that have been described in this thesis as examples of its validity. However, the methodologies and the compilation facilities need not be inter-twined. The benefits derived from each of them are general and they may be used in many areas of the persistent environment

    Design and implementation of an optimizing type-centric compiler for a high-level language

    Get PDF
    Production compilers for programming languages face multiple requirements. They should be correct, as we rely on them to produce code. They should be fast, in order to provide a good developer experience. They should also be easy to maintain and evolve. This thesis shows how an expressive high level type system can be used to simplify the development of a compiler and demonstrates this on a compiler for Scala. First, it shows how expressive types of high level languages can be used to build internal data structures that provide a statically checked API, ensuring that important properties hold at compile time. Second, we also show how high level language features can be used to abstract the components of a compiler. We demonstrate this by introducing a type-safe layer on top of the bytecode emission phase. This makes it possible to abstract away the implementation details of the compiler frontend and run the same bytecode emission phase in two different Scala compilers. Third, it presents MiniPhases, a novel way to organize transformation passes in a compiler. MiniPhases impose constraints on the organization of passes that are beneficial for maintainability, performance, and testability. We include a detailed performance evaluation of MiniPhases which indicates that their speedup is due to improved cache friendliness and to a lower rate of promotions of objects into the old generations of garbage collectors. Finally, we demonstrate how the expressive type system of the language being compiled can be used for static analysis. We present a novel call graph construction algorithm which uses the typing context for context sensitivity. The resulting algorithm is both substantially faster and more precise than existing alternatives. We demonstrate the applicability of this analysis by extending common subexpression elimination to idempotent expression elimination

    On the integration of concurrency, distribution and persistence

    Get PDF
    The principal tenet of the persistence model is that it abstracts over all the physical properties of data such as how long it is stored, where it is stored, how it is stored, what form it is kept in and who is using it. Experience with programming systems which support orthogonal persistence has shown that the simpler semantics and reduced complexity can often lead to a significant reduction in software production costs. Persistent systems are relatively new and it is not yet clear which of the many models of concurrency and distribution best suit the persistence paradigm. Previous work in this area has tended to build one chosen model into the system which may then only be applicable to a particular set of problems. This thesis challenges the orthodoxy by designing a persistent framework in which all models of concurrency and distribution can be integrated in an add-on fashion. The provision of such a framework is complicated by a tension between the conceptual ideas of persistence and the intrinsics of concurrency and distribution. The approach taken is to integrate the spectra of concurrency and distribution abstractions into the persistence model in a manner that does not prevent the user from being able to reason about program behaviour. As examples of the reference model a number of different styles of concurrency and distribution have been designed and incorporated into the persistent programming system Napier88. A detailed treatment of these models and their implementations is given

    Types and polymorphism in persistent programming systems

    Get PDF
    corecore