115 research outputs found
PLACES'10: The 3rd Workshop on Programmng Language Approaches to concurrency and Communication-Centric Software
Paphos, Cyprus. March 201
Generalized Points-to Graphs: A New Abstraction of Memory in the Presence of Pointers
Flow- and context-sensitive points-to analysis is difficult to scale; for
top-down approaches, the problem centers on repeated analysis of the same
procedure; for bottom-up approaches, the abstractions used to represent
procedure summaries have not scaled while preserving precision.
We propose a novel abstraction called the Generalized Points-to Graph (GPG)
which views points-to relations as memory updates and generalizes them using
the counts of indirection levels leaving the unknown pointees implicit. This
allows us to construct GPGs as compact representations of bottom-up procedure
summaries in terms of memory updates and control flow between them. Their
compactness is ensured by the following optimizations: strength reduction
reduces the indirection levels, redundancy elimination removes redundant memory
updates and minimizes control flow (without over-approximating data dependence
between memory updates), and call inlining enhances the opportunities of these
optimizations. We devise novel operations and data flow analyses for these
optimizations.
Our quest for scalability of points-to analysis leads to the following
insight: The real killer of scalability in program analysis is not the amount
of data but the amount of control flow that it may be subjected to in search of
precision. The effectiveness of GPGs lies in the fact that they discard as much
control flow as possible without losing precision (i.e., by preserving data
dependence without over-approximation). This is the reason why the GPGs are
very small even for main procedures that contain the effect of the entire
program. This allows our implementation to scale to 158kLoC for C programs
The semantic marriage of monads and effects
Wadler and Thiemann unified type-and-effect systems with monadic semantics
via a syntactic correspondence and soundness results with respect to an
operational semantics. They conjecture that a general, "coherent" denotational
semantics can be given to unify effect systems with a monadic-style semantics.
We provide such a semantics based on the novel structure of an indexed monad,
which we introduce. We redefine the semantics of Moggi's computational
lambda-calculus in terms of (strong) indexed monads which gives a one-to-one
correspondence between indices of the denotations and the effect annotations of
traditional effect systems. Dually, this approach yields indexed comonads which
gives a unified semantics and effect system to contextual notions of effect
(called coeffects), which we have previously described
Abstract interpretation and optimising transformations for applicative programs
This thesis describes methods for transforming applicative
programs with the aim of improving their efficiency. The general
justification for these techniques is presented via the concept of
abstract interpretation. The work can be seen as providing
mechanisms to optimise applicative programs for sequential von
Neumann machines. The chapters address the following subjects.
Chapter 1 gives an overview and gentle introduction to the
following technical chapters.
Chapter 2 gives an introduction to and motivation for the
concept of abstract interpretation necessary for the detailed
understanding of the rest of the work. It includes certain
theoretical developments, of which I believe the most important is
the incorporation of the concept of partial functions into our
notion of abstract interpretation. This is done by associating
non-standard denotations with functions just as denotational
semantics gives the standard denotations.
Chapter 3 gives an example of the ease with which we can talk
about function objects within abstract interpretive schemes. It
uses this to show how a simple language using call-by-need
semantics can be augmented with a system that annotates places in a
program at which call-by-value can be used without violating the
call-by-need semantics.
Chapter 4 extends the work of chapter 3 by showing that under
some sequentiality restriction, the incorporation of call-by-value
for call-by-need can be made complete in the sense that the
resulting program will only possess strict functions except for the
conditional.
Chapter 5 is an attempt to apply the concepts of abstract
interpretation to a completely different problem, that of
incorporating destructive operators into an applicative program.
We do this in order to increase the efficiency of implementation
without violating the applicative semantics by introducing
destructive operators into our language.
Finally, chapter 6 contains a discussion of the implications of
such techniques for real languages, and in particular presents
arguments whereby applicative languages should be seen as whole
systems and not merely the applicative subset of some larger
language
Extending monads with pattern matching
Sequencing of effectful computations can be neatly captured using monads and elegantly written using do notation. In practice such monads often allow additional ways of composing computations, which have to be written explicitly using combinators. We identify joinads, an abstract notion of computation that is stronger than monads and captures many such ad-hoc extensions. In particular, joinads are monads with three additional operations: one of type m a → m b → m (a, b) captures various forms of parallel composition, one of type m a → m a → m a that is inspired by choice and one of type m a → m (m a) that captures aliasing of computations. Algebraically, the first two operations form a near-semiring with commutative multiplication. We introduce docase notation that can be viewed as a monadic version of case. Joinad laws imply various syntactic equivalences of programs written using docase that are analogous to equiva-lences about case. Examples of joinads that benefit from the nota-tion include speculative parallelism, waiting for a combination of user interface events, but also encoding of validation rules using the intersection of parsers
Recommended from our members
A Unified Model for Context-Sensitive Program Analyses: The Blind Men and the Elephant
Context-sensitive methods of program analysis increase the precision
of interprocedural analysis by achieving the effect of call inlining.
These methods have been defined using different formalisms and hence
appear as algorithms that are very different from each other. Some
methods traverse a call graph top-down whereas some others traverse
it bottom-up first and then top-down. Some define contexts explicitly
whereas some do not. Some of them directly compute data flow values
while some first compute summary functions and then use them to compute
data flow values. Further, different methods place different kinds
of restrictions on the data flow frameworks supported by them. As a
consequence, it is difficult to compare the ideas behind these methods
in spite of the fact that they solve essentially the same problem. We
argue that these incomparable views are similar to those of blind men
describing an
elephant called context sensitivity, and make it difficult for a
non-expert reader to form a coherent picture of context-sensitive data
flow analysis.
We bring out this whole-elephant view of context sensitivity in
program analysis by proposing a unified model of context sensitivity
which provides a clean separation between computation of contexts and
computation of data flow values.
Our model captures the essence of context sensitivity and
defines simple soundness
and precision criteria for context-sensitive methods.
It facilitates declarative
specifications of context-sensitive methods,
insightful comparisons between them,
and reasoning about their soundness and precision.
We demonstrate this by instantiating our model to
many known context-sensitive methods
Galois connecting call-by-value and call-by-name
We establish a general framework for reasoning about the relationship between
call-by-value and call-by-name.
In languages with computational effects, call-by-value and call-by-name
executions of programs often have different, but related, observable
behaviours. For example, if a program might diverge but otherwise has no
effects, then whenever it terminates under call-by-value, it terminates with
the same result under call-by-name. We propose a technique for stating and
proving properties like these. The key ingredient is Levy's call-by-push-value
calculus, which we use as a framework for reasoning about evaluation orders. We
show that the call-by-value and call-by-name translations of expressions into
call-by-push-value have related observable behaviour under certain conditions
on computational effects, which we identify. We then use this fact to construct
maps between the call-by-value and call-by-name interpretations of types, and
identify further properties of effects that imply these maps form a Galois
connection. These properties hold for some computational effects (such as
divergence), but not others (such as mutable state). This gives rise to a
general reasoning principle that relates call-by-value and call-by-name. We
apply the reasoning principle to example computational effects including
divergence and nondeterminism
ParaDox: Eliminating Voltage Margins via Heterogeneous Fault Tolerance.
Providing reliability is becoming a challenge for chip manufacturers, faced with simultaneously trying to improve miniaturization, performance and energy efficiency. This leads to very large margins on voltage and frequency, designed to avoid errors even in the worst case, along with significant hardware expenditure on eliminating voltage spikes and other forms of transient error, causing considerable inefficiency in power consumption and performance. We flip traditional ideas about reliability and performance around, by exploring the use of error resilience for power and performance gains. ParaMedic is a recent architecture that provides a solution for reliability with low overheads via automatic hardware error recovery. It works by splitting up checking onto many small cores in a heterogeneous multicore system with hardware logging support. However, its design is based on the idea that errors are exceptional. We transform ParaMedic into ParaDox, which shows high performance in both error-intensive and scarce-error scenarios, thus allowing correct execution even when undervolted and overclocked. Evaluation within error-intensive simulation environments confirms the error resilience of ParaDox and the low associated recovery cost. We estimate that compared to a non-resilient system with margins, ParaDox can reduce energy-delay product by 15% through undervolting, while completely recovering from any induced errors
A Notation for Comonads
The category-theoretic concept of a monad occurs widely as a design pattern for functional programming with effects. The utility and ubiquity of monads is such that some languages provide syntactic sugar for this pattern, further encouraging its use. We argue that comonads, the dual of monads, similarly provide a useful design pattern, capturing notions of context dependence. However, comonads remain relatively under-used compared to monads—due to a lack of knowledge of the design pattern along with the lack of accompanying simplifying syntax. We propose a lightweight syntax for comonads in Haskell, analogous to the do-notation for monads, and provide examples of its use. Via our notation, we also provide a tutorial on programming with comonads
- …