Andrew W. Appel

dblp:a/AWAppel · DBLP profile ↗
← Back
90ranked-venue papers
37as first author
13since 2021 · last 2025
0000-0001-6009-0325ORCID · verified

Domains — the database's venue-derived domains; a paper can count in several

Software engineering, systems software and programming languages · 68 · 27 first-author · 8 since 2021Theory of computation · 17 · 6 first-author · 7 since 2021Security and privacy · 8 · 3 first-authorArtificial intelligence and machine learning · 7 · 3 first-author · 3 since 2021Systems, architecture and hardware · 4 · 3 first-authorDatabases, data management, data science and information retrieval · 1 · 1 first-author
YearPublicationVenuePosition
2025 A Verified Foreign Function Interface between Coq and C
abstract
One can write dependently typed functional programs in Coq, and prove them correct in Coq; one can write low-level programs in C, and prove them correct with a C verification tool. We demonstrate how to write programs partly in Coq and partly in C, and interface the proofs together. The Verified Foreign Function Interface (VeriFFI) guarantees type safety and correctness of the combined program. It works by translating Coq function types (and constructor types) along with Coq functional models into VST function-specifications; if the user can prove in VST that the C functions satisfy those specs, then the C functions behave according to the user-specified functional models (even though the C implementation might be very different) and the proofs of Coq functions that call the C code can rely on that behavior. To achieve this translation, we employ a novel, hybrid deep/shallow description of Coq dependent types.
Joomy Korkut, Kathrin Stark, Andrew W. Appel
Proc. ACM Program. Lang.3
2024 VCFloat2: Floating-Point Error Analysis in Coq
abstract
The development of sound and efficient tools that automatically perform floating-point round-off error analysis is an active area of research with applications to embedded systems and scientific computing. In this paper we describe VCFloat2, a novel extension to the VCFloat tool for verifying floating-point C programs in Coq. Like VCFloat1, VCFloat2 soundly and automatically computes round-off error bounds on floating-point expressions, but does so to higher accuracy; with better performance; with more generality for nonstandard number formats; with the ability to reason about external (user-defined or library) functions; and with improved modularity for interfacing with other program verification tools in Coq. We evaluate the performance of VCFloat2 using common benchmarks; compared to other state-of-the art tools, VCFloat2 computes competitive error bounds and transparent certificates that require less time for verification.
Andrew W. Appel, Ariel Kellison
CPP1
2024 VST-A: A Foundationally Sound Annotation Verifier
abstract
Program verifiers for imperative languages such as C may be annotation-based , in which assertions and invariants are put into source files and then checked, or tactic-based, where proof scripts separate from programs are interactively developed in a proof assistant such as Coq. Annotation verifiers have been more automated and convenient, but some interactive verifiers have richer assertion languages and formal proofs of soundness. We present VST-A, an annotation verifier that uses the rich assertion language of VST, leverages the formal soundness proof of VST, but allows users to describe functional correctness proofs intuitively by inserting assertions. VST-A analyzes control flow graphs, decomposes every C function into control flow paths between assertions, and reduces program verification problems into corresponding straightline Hoare triples . Compared to existing foundational program verification tools like VST and Iris, in VST-A such decompositions and reductions can nonstructural, which makes VST-A more flexible to use. VST-A’s decomposition and reduction is defined in Coq, proved sound in Coq, and computed call-by-value in Coq. The soundness proof for reduction is totally logical, independent of the complicated semantic model (and soundness proof) of VST’s Hoare triple. Because of the rich assertion language, not all reduced proof goals can be automatically checked, but the system allows users to prove residual proof goals using the full power of the Coq proof assistant.
Litao Zhou 0001, Jianxing Qin, Qinshi Wang, Andrew W. Appel, Qinxiang Cao
Proc. ACM Program. Lang.4
2023 LAProof: A Library of Formal Proofs of Accuracy and Correctness for Linear Algebra Programs
abstract
The LAProof library provides formal machine-checked proofs of the accuracy of basic linear algebra operations: inner product using conventional multiply and add, inner product using fused multiply-add, scaled matrix-vector and matrix-matrix multiplication, and scaled vector and matrix addition. These proofs can connect to concrete implementations of low-level basic linear algebra subprograms; as a proof of concept we present a machine-checked correctness proof of a C function implementing sparse matrix-vector multiplication using the compressed sparse row format. Our accuracy proofs are backward error bounds and mixed backward-forward error bounds that account for underflow, proved subject to no assumptions except a low-level formal model of IEEE-754 arithmetic. We treat low-order error terms concretely, not approximating as $\mathcal{O}\left( {{u^2}} \right)$.
Ariel Kellison, Andrew W. Appel, Mohit Tekriwal, David Bindel
ARITH2
2023 Foundational Verification of Stateful P4 Packet Processing
Qinshi Wang, Mengying Pan, Ryan Doenges, Lennart Beringer, Andrew W. Appel
ITP6
2023 Verified Correctness, Accuracy, and Convergence of a Stationary Iterative Linear Solver: Jacobi Method
Mohit Tekriwal, Andrew W. Appel, Ariel Kellison, David Bindel, Jean-Baptiste Jeannin
CICM2
2023 Efficient Extensional Binary Tries
Andrew W. Appel, Xavier Leroy
J. Autom. Reason.1
2023 A Solver for Arrays with Concatenation
Qinshi Wang, Andrew W. Appel
J. Autom. Reason.2
2022 Verified Erasure Correction in Coq with MathComp and VST
abstract
Abstract Most methods of data transmission and storage are prone to errors, leading to data loss. Forward erasure correction (FEC) is a method to allow data to be recovered in the presence of errors by encoding the data with redundant parity information determined by an error-correcting code. There are dozens of classes of such codes, many based on sophisticated mathematics, making them difficult to verify using automated tools. In this paper, we present a formal, machine-checked proof of a C implementation of FEC based on Reed-Solomon coding. The C code has been actively used in network defenses for over 25 years, but the algorithm it implements was partially unpublished, and it uses certain optimizations whose correctness was unknown even to the code’s authors. We use Coq’s Mathematical Components library to prove the algorithm’s correctness and the Verified Software Toolchain to prove that the C program correctly implements this algorithm, connecting both using a modular, well-encapsulated structure that could easily be used to verify a high-speed, hardware version of this FEC. This is the first end-to-end, formal proof of a real-world FEC implementation; we verified all previously unknown optimizations and found a latent bug in the code.
Joshua M. Cohen, Qinshi Wang, Andrew W. Appel
CAV (2)3
2022 Coq's vibrant ecosystem for verification engineering (invited talk)
abstract
Program verification in the large is not only a matter of mechanizing a program logic to handle the semantics of your programming language. You must reason in the mathematics of your application domain--and there are many application domains, each with their own community of domain experts. So you will need to import mechanized proof theories from many domains, and they must all interoperate. Such an ecosystem is not only a matter of mathematics, it is a matter of software process engineering and social engineering. Coq's ecosystem has been maturing nicely in these senses.
Andrew W. Appel
CPP1
2021 Abstraction and subsumption in modular verification of C programs
Lennart Beringer, Andrew W. Appel
Formal Methods Syst. Des.2
2021 Deriving efficient program transformations from rewrite rules
abstract
An efficient optimizing compiler can perform many cascading rewrites in a single pass, using auxiliary data structures such as variable binding maps, delayed substitutions, and occurrence counts. Such optimizers often perform transformations according to relatively simple rewrite rules, but the subtle interactions between the data structures needed for efficiency make them tricky to write and trickier to prove correct. We present a system for semi-automatically deriving both an efficient program transformation and its correctness proof from a list of rewrite rules and specifications of the auxiliary data structures it requires. Dependent types ensure that the holes left behind by our system (for the user to fill in) are filled in correctly, allowing the user low-level control over the implementation without having to worry about getting it wrong. We implemented our system in Coq (though it could be implemented in other logics as well), and used it to write optimization passes that perform uncurrying, inlining, dead code elimination, and static evaluation of case expressions and record projections. The generated implementations are sometimes faster, and at most 40% slower, than hand-written counterparts on a small set of benchmarks; in some cases, they require significantly less code to write and prove correct.
John M. Li, Andrew W. Appel
Proc. ACM Program. Lang.2
2021 Compositional optimizations for CertiCoq
abstract
Compositional compiler verification is a difficult problem that focuses on separate compilation of program components with possibly different verified compilers. Logical relations are widely used in proving correctness of program transformations in higher-order languages; however, they do not scale to compositional verification of multi-pass compilers due to their lack of transitivity. The only known technique to apply to compositional verification of multi-pass compilers for higher-order languages is parametric inter-language simulations (PILS), which is however significantly more complicated than traditional proof techniques for compiler correctness. In this paper, we present a novel verification framework for lightweight compositional compiler correctness . We demonstrate that by imposing the additional restriction that program components are compiled by pipelines that go through the same sequence of intermediate representations , logical relation proofs can be transitively composed in order to derive an end-to-end compositional specification for multi-pass compiler pipelines. Unlike traditional logical-relation frameworks, our framework supports divergence preservation—even when transformations reduce the number of program steps. We achieve this by parameterizing our logical relations with a pair of relational invariants . We apply this technique to verify a multi-pass, optimizing middle-end pipeline for CertiCoq, a compiler from Gallina (Coq’s specification language) to C. The pipeline optimizes and closure-converts an untyped functional intermediate language (ANF or CPS) to a subset of that language without nested functions, which can be easily code-generated to low-level languages. Notably, our pipeline performs more complex closure-allocation optimizations than the state of the art in verified compilation. Using our novel verification framework, we prove an end-to-end theorem for our pipeline that covers both termination and divergence and applies to whole-program and separate compilation, even when different modules are compiled with different optimizations. Our results are mechanized in the Coq proof assistant.
Zoe Paraskevopoulou, John M. Li, Andrew W. Appel
Proc. ACM Program. Lang.3
2020 Connecting Higher-Order Separation Logic to a First-Order Outside World
abstract
Abstract Separation logic is a useful tool for proving the correctness of programs that manipulate memory, especially when the model of memory includes higher-order state: Step-indexing, predicates in the heap, and higher-order ghost state have been used to reason about function pointers, data structure invariants, and complex concurrency patterns. On the other hand, the behavior of system features (e.g., operating systems) and the external world (e.g., communication between components) is usually specified using first-order formalisms. In principle, the soundness theorem of a separation logic is its interface with first-order theorems, but the soundness theorem may implicitly make assumptions about how other components are specified, limiting its use. In this paper, we show how to extend the higher-order separation logic of the Verified Software Toolchain to interface with a first-order verified operating system, in this case CertiKOS, that mediates its interaction with the outside world. The resulting system allows us to prove the correctness of C programs in separation logic based on the semantics of system calls implemented in CertiKOS. It also demonstrates that the combination of interaction trees + CompCert memories serves well as a lingua franca to interface and compose two quite different styles of program verification.
William Mansky, Wolf Honoré, Andrew W. Appel
ESOP3
2020 Verified sequential Malloc/Free
abstract
We verify the functional correctness of an array-of-bins (segregated free-lists) single-thread malloc/free system with respect to a correctness specification written in separation logic. The memory allocator is written in standard C code compatible with the standard API; the specification is in the Verifiable C program logic, and the proof is done in the Verified Software Toolchain within the Coq proof assistant. Our "resource-aware" specification can guarantee when malloc will successfully return a block, unlike the standard Posix specification that allows malloc to return NULL whenever it wants to. We also prove subsumption (refinement): the resource-aware specification implies a resource-oblivious spec.
Andrew W. Appel, David A. Naumann
ISMM1
2019 Abstraction and Subsumption in Modular Verification of C Programs
Lennart Beringer, Andrew W. Appel
FM2
2019 Closure conversion is safe for space
abstract
We formally prove that closure conversion with flat environments for CPS lambda calculus is correct (preserves semantics) and safe for time and space, meaning that produced code preserves the time and space required for the execution of the source program. We give a cost model to pre- and post-closure-conversion code by formalizing profiling semantics that keep track of the time and space resources needed for the execution of a program, taking garbage collection into account. To show preservation of time and space we set up a general, "garbage-collection compatible", binary logical relation that establishes invariants on resource consumption of the related programs, along with functional correctness. Using this framework, we show semantics preservation and space and time safety for terminating source programs, and divergence preservation and space safety for diverging source programs. We formally prove that closure conversion with flat environments for CPS lambda calculus is correct (preserves semantics) and safe for time and space, meaning that produced code preserves the time and space required for the execution of the source program. We give a cost model to pre- and post-closure-conversion code by formalizing profiling semantics that keep track of the time and space resources needed for the execution of a program, taking garbage collection into account. To show preservation of time and space we set up a general, "garbage-collection compatible", binary logical relation that establishes invariants on resource consumption of the related programs, along with functional correctness. Using this framework, we show semantics preservation and space and time safety for terminating source programs, and divergence preservation and space safety for diverging source programs. This is the first formal proof of space-safety of a closure-conversion transformation. The transformation and the proof are parts of the CertiCoq compiler pipeline from Coq (Gallina) through CompCert Clight to assembly language. Our results are mechanized in the Coq proof assistant.
Zoe Paraskevopoulou, Andrew W. Appel
Proc. ACM Program. Lang.2
2018 VST-Floyd: A Separation Logic Tool to Verify Correctness of C Programs
Qinxiang Cao, Lennart Beringer, Samuel Gruetter, Josiah Dodds, Andrew W. Appel
J. Autom. Reason.5
2017 Bringing Order to the Separation Logic Jungle
Qinxiang Cao, Santiago Cuéllar, Andrew W. Appel
APLAS3
2017 Verified Correctness and Security of mbedTLS HMAC-DRBG
abstract
We have formalized the functional specification of HMAC-DRBG (NIST 800-90A), and we have proved its cryptographic security-that its output is pseudorandom--using a hybrid game-based proof. We have also proved that the mbedTLS implementation (C program) correctly implements this functional specification. That proof composes with an existing C compiler correctness proof to guarantee, end-to-end, that the machine language program gives strong pseudorandomness. All proofs (hybrid games, C program verification, compiler, and their composition) are machine-checked in the Coq proof assistant. Our proofs are modular: the hybrid game proof holds on any implementation of HMAC-DRBG that satisfies our functional specification. Therefore, our functional specification can serve as a high-assurance reference.
Katherine Q. Ye, Matthew Green 0001, Naphat Sanguansin, Lennart Beringer, Adam Petcher, Andrew W. Appel
CCS6
2017 Shrink fast correctly!
abstract
Function inlining, case-folding, projection-folding, and dead-variable elimination are important code transformations in virtually every functional-language compiler. When one of these reductions strictly reduces the size of the program (e.g., when the inlined function has only one applied occurrence), we call it a shrink reduction. Appel and Jim [1] introduced an algorithm to perform all shrink reductions (producing a shrink normal form) in quasilinear time. They proved confluence but not correctness.
Olivier Savary Bélanger, Andrew W. Appel
PPDP2
2017 A verified messaging system
abstract
We present a concurrent-read exclusive-write buffer system with strong correctness and security properties. Our motivating application for this system is the distribution of sensor values in a multicomponent vehicle-control system, where some components are unverified and possibly malicious, and other components are vehicle-control-critical and must be verified. Valid participants are guaranteed correct communication (i.e., the writer is always able to write to an unused buffer, and readers always read the most recently published value), while invalid readers or writers cannot compromise the correctness or liveness of valid participants. There is only one writer, all operations are wait-free, and there is no extra process or thread mediating communication. We prove the correctness of the system with valid participants by formally verifying a C implementation of the system in Coq, using the Verified Software Toolchain extended with an atomic exchange operation. The result is the first C-level mechanized verification of a nonblocking communication protocol.
William Mansky, Andrew W. Appel, Aleksey Nogin
Proc. ACM Program. Lang.2
2016 Modular Verification for Computer Security
abstract
For many software components, it is useful and important to verify their security. This can be done by an analysis of the software itself, or by isolating the software behind a protection mechanism such as an operating system kernel (virtual-memory protection) or cryptographic authentication (don't accepted untrusted inputs). But the protection mechanisms themselves must then be verified not just for safety but for functional correctness. Several recent projects have demonstrated that formal, deductive functional-correctness verification is now possible for kernels, crypto, and compilers. Here I explain some of the modularity principles that make these verifications possible.
Andrew W. Appel
CSF1
2015 Verification of a cryptographic primitive: SHA-256 (abstract)
abstract
A full formal machine-checked verification of a C program: the OpenSSL implementation of SHA-256. This is an interactive proof of functional correctness in the Coq proof assistant, using the Verifiable C program logic. Verifiable C is a separation logic for the C language, proved sound w.r.t. the operational semantics for C, connected to the CompCert verified optimizing C compiler.
Andrew W. Appel
PLDI1
2015 Compositional CompCert
abstract
This paper reports on the development of Compositional CompCert, the first verified separate compiler for C.
Gordon Stewart 0001, Lennart Beringer, Santiago Cuéllar, Andrew W. Appel
POPL4
2015 Verified Correctness and Security of OpenSSL HMAC
Lennart Beringer, Adam Petcher, Katherine Q. Ye, Andrew W. Appel
USENIX Security Symposium4
2015 Verification of a Cryptographic Primitive: SHA-256
abstract
This article presents a full formal machine-checked verification of a C program: the OpenSSL implementation of SHA-256. This is an interactive proof of functional correctness in the Coq proof assistant, using the Verifiable C program logic. Verifiable C is a separation logic for the C language, proved sound with respect to the operational semantics for C, connected to the CompCert verified optimizing C compiler.
Andrew W. Appel
ACM Trans. Program. Lang. Syst.1
2014 Portable Software Fault Isolation
abstract
We present a new technique for architecture portable software fault isolation (SFI), together with a prototype implementation in the Coq proof assistant. Unlike traditional SFI, which relies on analysis of assembly-level programs, we analyze and rewrite programs in a compiler intermediate language, the Cminor language of the Comp Cert C compiler. But like traditional SFI, the compiler remains outside of the trusted computing base. By composing our program transformer with the verified back-end of Comp Cert and leveraging Comp Cert's formally proved preservation of the behavior of safe programs, we can obtain binary modules that satisfy the SFI memory safety policy for any of Comp Cert's supported architectures (currently: Power PC, ARM, and x86-32). This allows the same SFI analysis to be used across multiple architectures, greatly simplifying the most difficult part of deploying trustworthy SFI systems.
Joshua A. Kroll, Gordon Stewart 0001, Andrew W. Appel
CSF3
2014 Verified Compilation for Shared-Memory C
Lennart Beringer, Gordon Stewart 0001, Robert Dockins, Andrew W. Appel
ESOP4
2013 Mostly Sound Type System Improves a Foundational Program Verifier
Josiah Dodds, Andrew W. Appel
CPP2
2012 Verified heap theorem prover by paramodulation
abstract
We present VeriStar, a verified theorem prover for a decidable subset of separation logic. Together with VeriSmall [3], a proved-sound Smallfoot-style program analysis for C minor, VeriStar demonstrates that fully machine-checked static analyses equipped with efficient theorem provers are now within the reach of formal methods. As a pair, VeriStar and VeriSmall represent the first application of the Verified Software Toolchain [4], a tightly integrated collection of machine-verified program logics and compilers giving foundational correctness guarantees.
Gordon Stewart 0001, Lennart Beringer, Andrew W. Appel
ICFP3
2012 A List-Machine Benchmark for Mechanized Metatheory
Andrew W. Appel, Robert Dockins, Xavier Leroy
J. Autom. Reason.1
2011 VeriSmall: Verified Smallfoot Shape Analysis
Andrew W. Appel
CPP1
2011 Verified Software Toolchain - (Invited Talk)
Andrew W. Appel
ESOP1
2011 Security Seals on Voting Machines: A Case Study
abstract
Tamper-evident seals are used by many states’ election officials on voting machines and ballot boxes, either to protect the computer and software from fraudulent modification or to protect paper ballots from fraudulent substitution or stuffing. Physical tamper-indicating seals can usually be easily defeated, given they way they are typically made and used; and the effectiveness of seals depends on the protocol for their application and inspection. The legitimacy of our elections may therefore depend on whether a particular state’s use of seals is effective to prevent, deter, or detect election fraud. This paper is a case study of the use of seals on voting machines by the State of New Jersey. I conclude that New Jersey’s protocols for the use of tamper-evident seals have been not at all effective. I conclude with a discussion of the more general problem of seals in democratic elections.
Andrew W. Appel
ACM Trans. Inf. Syst. Secur.1
2010 A Logical Mix of Approximation and Separation
Aquinas Hobor, Robert Dockins, Andrew W. Appel
APLAS3
2010 Formal Verification of Coalescing Graph-Coloring Register Allocation
Sandrine Blazy, Benoît Robillard, Andrew W. Appel
ESOP3
2010 A theory of indirection via approximation
abstract
Building semantic models that account for various kinds of indirect reference has traditionally been a difficult problem. Indirect reference can appear in many guises, such as heap pointers, higher-order functions, object references, and shared-memory mutexes.
Aquinas Hobor, Robert Dockins, Andrew W. Appel
POPL3
2010 Concurrent Separation Logic for Pipelined Parallelization
Christian J. Bell, Andrew W. Appel, David Walker 0001
SAS2
2010 Semantic foundations for typed assembly languages
abstract
Typed Assembly Languages (TALs) are used to validate the safety of machine-language programs. The Foundational Proof-Carrying Code project seeks to verify the soundness of TALs using the smallest possible set of axioms: the axioms of a suitably expressive logic plus a specification of machine semantics. This article proposes general semantic foundations that permit modular proofs of the soundness of TALs. These semantic foundations include Typed Machine Language (TML), a type theory for specifying properties of low-level data with powerful and orthogonal type constructors, and L c , a compositional logic for specifying properties of machine instructions with simplified reasoning about unstructured control flow. Both of these components, whose semantics we specify using higher-order logic, are useful for proving the soundness of TALs. We demonstrate this by using TML and L c to verify the soundness of a low-level, typed assembly language, LTAL, which is the target of our core-ML-to-sparc compiler. To prove the soundness of the TML type system we have successfully applied a new approach, that of step-indexed logical relations . This approach provides the first semantic model for a type system with updatable references to values of impredicative quantified types. Both impredicative polymorphism and mutable references are essential when representing function closures in compilers with typed closure conversion, or when compiling objects to simpler typed primitives.
Amal Ahmed 0001, Andrew W. Appel, Christopher D. Richards, Kedar N. Swadi, Gang Tan, Daniel C. Wang
ACM Trans. Program. Lang. Syst.2
2009 A Fresh Look at Separation Algebras and Share Accounting
Robert Dockins, Aquinas Hobor, Andrew W. Appel
APLAS3
2008 Oracle Semantics for Concurrent Separation Logic
Aquinas Hobor, Andrew W. Appel, Francesco Zappa Nardelli
ESOP2
2007 A very modal model of a modern, major, general type system
abstract
International audience
Andrew W. Appel, Paul-André Melliès, Christopher D. Richards, Jérôme Vouillon
POPL1
2006 A Compositional Logic for Control Flow
Gang Tan, Andrew W. Appel
VMCAI2
2005 MulVAL: A Logic-based Network Security Analyzer
Xinming Ou, Sudhakar Govindavajhala, Andrew W. Appel
USENIX Security Symposium3
2004 Social processes and proofs of theorems and programs, revisited
abstract
Language-based security is a protection mechanism that allows software components to interact in a shared address space, such that each component is guaranteed to respect its interfaces and not steal or corrupt internal data of other components. This protection mechanism is complicated to implement correctly, so we might want a formal verification of it.But we know by a famous result of DeMillo, Lipton, and Perlis (POPL 1978) that formal verification (1) is not what mathematicians do, (2) can never be practical, and (3) cannot tell us anything truly useful. Is this still true 25 years later?The question is, then, how can we carefully skirt the legitimate objections of DeMillo et al. and successfully use formal verification in a context where it can do some good. I'll talk about Foundational Proof-Carrying Code, a machine-checked soundness proof for a protection mechanism usable in Java-like virtual machines.
Andrew W. Appel
PLDI1
2004 Construction of a Semantic Model for a Typed Assembly Language
Gang Tan, Andrew W. Appel, Kedar N. Swadi, Dinghao Wu
VMCAI2
2004 Dependent types ensure partial correctness of theorem provers
abstract
Static type systems in programming languages allow many errors to be detected at compile time that wouldn't be detected until runtime otherwise. Dependent types are more expressive than the type systems in most programming languages, so languages that have them should allow programmers to detect more errors earlier. In this paper, using the Twelf system, we show that dependent types in the logic programming setting can be used to ensure partial correctness of programs which implement theorem provers, and thus avoid runtime errors in proof search and proof construction. We present two examples: a tactic-style interactive theorem prover and a union-find decision procedure.
Andrew W. Appel, Amy P. Felty
J. Funct. Program.1
2004 Polymorphic Lemmas and Definitions in lambda-Prolog and Twelf
abstract
$\lambda$ Prolog is known to be well-suited for expressing and implementing logics and inference systems. We show that lemmas and definitions in such logics can be implemented with a great economy of expression. We encode a higher-order logic using an encoding that maps both terms and types of the object logic (higher-order logic) to terms of the metalanguage ( $\lambda$ Prolog). We discuss both the Terzo and Teyjus implementations of $\lambda$ Prolog. We also encode the same logic in Twelf and compare the features of these two metalanguages for our purposes.
Andrew W. Appel, Amy P. Felty
Theory Pract. Log. Program.1
2003 A provably sound TAL for back-end optimization
abstract
Typed assembly languages provide a way to generate machine-checkable safety proofs for machine-language programs. But the soundness proofs of most existing typed assembly languages are hand-written and cannot be machine-checked, which is worrisome for such large calculi. We have designed and implemented a low-level typed assembly language (LTAL) with a semantic model and established its soundness from the model. Compared to existing typed assembly languages, LTAL is more scalable and more secure; it has no macro instructions that hinder low-level optimizations such as instruction scheduling; its type constructors are expressive enough to capture dataflow information, support the compiler's choice of data representations and permit typed position-independent code; and its type-checking algorithm is completely syntax-directed.We have built a prototype system, based on Standard ML of New Jersey, that compiles most of core ML to Sparc code. We explain how we were able to make the untyped back end in SML/NJ preserve types during instruction selection and register allocation, without restricting low-level optimizations and without knowledge of any type system pervading the instruction selector and register allocator.
Dinghao Wu, Andrew W. Appel, Hai Fang
PLDI3
2003 Foundational proof checkers with small witnesses
abstract
Proof checkers for proof-carrying code (and similar systems) can suffer from two problems: huge proof witnesses and untrustworthy proof rules. No previous design has addressed both of these problems simultaneously. We show the theory, design, and implementation of a proof-checker that permits small proof witnesses and machine-checkable proofs of the soundness of the system.
Dinghao Wu, Andrew W. Appel, Aaron Stump
PPDP2
2003 Policy-enforced linking of untrusted components
abstract
Article Share on Policy-enforced linking of untrusted components Authors: Eunyoung Lee Princeton University, Princeton, NJ Princeton University, Princeton, NJView Profile , Andrew W. Appe Princeton University, Princeton, NJ Princeton University, Princeton, NJView Profile Authors Info & Claims ESEC/FSE-11: Proceedings of the 9th European software engineering conference held jointly with 11th ACM SIGSOFT international symposium on Foundations of software engineeringSeptember 2003 Pages 371–374https://doi.org/10.1145/940071.940124Online:01 September 2003Publication History 5citation391DownloadsMetricsTotal Citations5Total Downloads391Last 12 Months1Last 6 weeks0 Get Citation AlertsNew Citation Alert added!This alert has been successfully added and will be sent to:You will be notified whenever a record that you have chosen has been cited.To manage your alert preferences, click on the button below.Manage my AlertsNew Citation Alert!Please log in to your account Save to BinderSave to BinderCreate a New BinderNameCancelCreateExport CitationPublisher SiteGet Access
Eunyoung Lee, Andrew W. Appel
ESEC / SIGSOFT FSE2
2003 Using Memory Errors to Attack a Virtual Machine
abstract
We present an experimental study showing that soft memory errors can lead to serious security vulnerabilities in Java and .NET virtual machines, or in any system that relies on type-checking of untrusted programs as a protection mechanism. Our attack works by sending to the JVM a Java program that is designed so that almost any memory error in its address space will allow it to take control of the JVM. All conventional Java and .NET virtual machines are vulnerable to this attack. The technique of the attack is broadly applicable against other language-based security schemes such as proof-carrying code. We measured the attack on two commercial Java virtual machines: Sun's and IBM's. We show that a single-bit error in the Java program's data space can be exploited to execute arbitrary code with a probability of about 70%, and multiple-bit errors with a lower probability. Our attack is particularly relevant against smart cards or tamper-resistant computers, where the user has physical access (to the outside of the computer) and can use various means to induce faults; we have successfully used heat. Fortunately, there are some straightforward defenses against this attack.
Sudhakar Govindavajhala, Andrew W. Appel
S&P2
2003 A Trustworthy Proof Checker
Andrew W. Appel, Neophytos G. Michael, Aaron Stump, Roberto Virga
J. Autom. Reason.1
2003 Mechanisms for secure modular programming in Java
abstract
Abstract We present a new module system for Java that improves upon many of the deficiencies of the Java package system and gives the programmer more control over dynamic linking. Our module system provides explicit interfaces, multiple views of modules based on hierarchical nesting and more flexible name‐space management than the Java package system. Relationships between modules are explicitly specified in module description files. We provide more control over dynamic linking by allowing import statements in module description files to require that imported modules be annotated with certain properties, which we implement by digital signatures. Our module system is compatible enough with standard Java to be implemented as a source‐to‐source and bytecode‐to‐bytecode transformation wrapped around a standard Java compiler, using a standard Java virtual machine (JVM). Copyright © 2003 John Wiley & Sons, Ltd.
Lujo Bauer, Andrew W. Appel, Edward W. Felten
Softw. Pract. Exp.2
2002 A Stratified Semantics of General References A Stratified Semantics of General References
abstract
We demonstrate a semantic model of general references - that is, mutable memory cells that may contain values of any (statically-checked) closed type, including other references. Our model is in terms of execution sequences on a von Neumann machine; thus, it can be used in a Proof-Carrying Code system where the skeptical consumer checks even the proofs of the typing rules. The model allows us to prove a frame-axiom introduction rule that allows locality of specification and reasoning, even in the event of updates to aliased locations. Our proof is machine-checked in the Twelf metalogic.
Amal Ahmed 0001, Andrew W. Appel, Roberto Virga
LICS2
2002 Creating and preserving locality of java applications at allocation and garbage collection times
abstract
The growing gap between processor and memory speeds is motivating the need for optimization strategies that improve data locality. A major challenge is to devise techniques suitable for pointer-intensive applications. This paper presents two techniques aimed at improving the memory behavior of pointer-intensive applications with dynamic memory allocation, such as those written in Java. First, we present an allocation time object placement technique based on the recently introduced notion of prolific (frequently instantiated) types. We attempt to co-locate, at allocation time, objects of prolific types that are connected via object references. Then, we present a novel locality based graph traversal technique. The benefits of this technique, when applied to garbage collection (GC), are twofold: (i) it improves the performance of GC due to better locality during a heap traversal and (ii) it restructures surviving objects in a way that enhances locality. On multiprocessors, this technique can further reduce overhead due to synchronization and false sharing. The experimental results, on a well-known suite of Java benchmarks (SPECjvm98 [26], SPECjbb2000 [27], and jOlden [4]), from an implementation of these techniques in the Jikes RVM [1], are very encouraging. The object co-allocation technique improves application performance by up to 21% (10% on average) in the Jikes RVM configured with a non-copying mark-and-sweep collector. The locality-based traversal technique reduces GC times by up to 20% (10% on average) and improves the performance of applications by up to 14% (6% on average) in the Jikes RVM configured with a copying semi-space collector. Both techniques combined can improve application performance by up to 22% (10% on average) in the Jikes RVM configured with a non-copying mark-and-sweep collector.
Yefim Shuf, Manish Gupta 0002, Hubertus Franke, Andrew W. Appel, Jaswinder Pal Singh
OOPSLA4
2001 Foundational Proof-Carrying Code
abstract
Proof-carrying code is a framework for the mechanical verification of safety properties of machine-language programs, but the problem arises of "quis custodiat ipsos custodes" - i.e. who verifies the verifier itself? Foundational proof-carrying code is verification from the smallest possible set of axioms, using the simplest possible verifier and the smallest possible runtime system. I describe many of the mathematical and engineering problems to be solved in the construction of a foundational proof-carrying code system.
Andrew W. Appel
LICS1
2001 Optimal Spilling for CISC Machines with Few Registers
abstract
Many graph-coloring register-allocation algorithms don't work well for machines with few registers. Heuristics for live-range splitting are complex or suboptimal; heuristics for register assignment rarely factor the presence of fancy addressing modes; these problems are more severe the fewer registers there are to work with. We show how to optimally split live ranges and optimally use addressing modes, where the optimality condition measures dynamically weighted loads and stores but not register-register moves. Our algorithm uses integer linear programming but is much more efficient than previous ILP-based approaches to register allocation. We then show a variant of Park and Moon's optimistic coalescing algorithm that does a very good (though not provably optimal) job of removing the register-register moves. The result is Pentium code that is 9.5% faster than code generated by SSA-based splitting with iterated register coalescing.
Andrew W. Appel, Lal George
PLDI1
2001 Type-preserving garbage collectors
abstract
By combining existing type systems with standard type-based compilation techniques, we describe how to write strongly typed programs that include a function that acts as a t racing garbage collector for the program. Since the garbage collector is an explicit function, we do not need to provide a t rusted garbage collector as a runtime service to manage memory.Since our language is strongly typed, the standard type soundness guarantee "Well typed programs do not go wrong" is extended to include the collector. Our type safety guarantee is non-trivial since not only does it guarantee the type safety of the garbage collector, but it guarantees that the collector preservers the type safety of the program being garbage collected. We describe the technique in detail and report performance measurements for a few microbench-marks as well as sketch the proofs of type soundness for our system.
Daniel C. Wang, Andrew W. Appel
POPL2
2001 An indexed model of recursive types for foundational proof-carrying code
abstract
The proofs of "traditional" proof carrying code (PCC) are type-specialized in the sense that they require axioms about a specific type system. In contrast, the proofs of foundational PCC explicitly define all required types and explicitly prove all the required properties of those types assuming only a fixed foundation of mathematics such as higher-order logic. Foundational PCC is both more flexible and more secure than type-specialized PCC.For foundational PCC we need semantic models of type systems on von Neumann machines. Previous models have been either too weak (lacking general recursive types and first-class function-pointers), too complex (requiring machine-checkable proofs of large bodies of computability theory), or not obviously applicable to von Neumann machines. Our new model is strong, simple, and works either in λ-calculus or on Pentiums.
Andrew W. Appel, David A. McAllester
ACM Trans. Program. Lang. Syst.1
2000 Machine Instruction Syntax and Semantics in Higher Order Logic
Neophytos G. Michael, Andrew W. Appel
CADE2
2000 A Semantic Model of Types and Machine Instructions for Proof-Carrying Code
abstract
Proof-carrying code is a framework for proving the safety of machine-language programs with a machinecheckable proof. Such proofs have previously defined type-checking rules as part of the logic. We show a universal type framework for proof-carrying code that will allow a code producer to choose a programming language, prove the type rules for that language as lemmas in higher-order logic, then use those lemmas to prove the safety of a particular program. We show how to handle traversal, allocation, and initialization of values in a wide variety of types, including functions, records, unions, existentials, and covariant recursive types. 1 Introduction When a host computer runs an untrusted program, the host may want some assurance that the program does no harm: does not access unauthorized resources, read private data, or overwrite valuable data. Proof-carrying code [Nec97] is a technique for providing such assurances. With PCC, the host -- called the "code consumer" -- specifies a sa...
Andrew W. Appel, Amy P. Felty
POPL1
2000 Efficient and safe-for-space closure conversion
abstract
Modern compilers often implement function calls (or returns) in two steps: first, a “closure” environment is properly installed to provide access for free variables in the target program fragment; second, the control is transferred to the target by a “jump with arguments (for results).” Closure conversion—which decides where and how to represent closures at runtime—is a crucial step in the compilation of functional languages. This paper presents a new algorithm that exploits the use of compile-time control and data-flow information to optimize funtion calls. By extensive closure sharing and allocation by 36% and memory fetches for local and global variables by 43%; and improves the already efficient code generated by an earlier version of the Standard ML of New Jersey compiler by about 17% on a DECstation 5000. Moreover, unlike most other approaches, our new closure-allocation scheme the strong safe-for-space-complexity rule, thus achieving good asymptotic space usage.
Zhong Shao 0001, Andrew W. Appel
ACM Trans. Program. Lang. Syst.2
2000 SAFKASI: a security mechanism for language-based systems
abstract
In order to run untrusted code in the same process as trusted code, there must be a mechanism to allow dangerous calls to determine if their caller is authorized to exercise the privilege of using the dangerous routine. Java systems have adopted a technique called stack inspection to address this concern. But its original definition, in terms of searching stack frames, had an unclear relationship to the actual achievement of security, overconstrained the implementation of a Java system, limited many desirable optimizations such as method inlining and tail recursion, and generally interfered with interprocedural optimization. We present a new semantics for stack inspection based on a belief logic and its implementation using the calculus of security-passing style which addresses the concerns of traditional stack inspection. With security-passing style, we can efficiently represent the security context for any method activation, and we can build a new implementation strictly by rewriting the Java bytecodes before they are loaded by the system. No changes to the JVM or bytecode semantics are necessary. With a combination of static analysis and runtime optimizations, our prototype implementation showes reasonable performance (although traditional stack inspection is still faster), and is easier to consider for languages beyond Java. We call our system SAFKASI (the Security Architecture Formerly Known as Stack Inspection).
Dan S. Wallach, Andrew W. Appel, Edward W. Felten
ACM Trans. Softw. Eng. Methodol.2
1999 Proof-Carrying Authentication
abstract
We have designed and implemented a general and powerful distributed authentication framework based on higher-order logic. Authentication frameworks — including Taos, SPKI, SDSI, and X.509 — have been explained using logic. We show that by starting with the logic, we can implement these frameworks, all in the same concise and efficient system. Because our logic has no decision procedure — although proof checking is simple — users of the framework must submit proofs with their requests.
Andrew W. Appel, Edward W. Felten
CCS1
1999 Lightweight Lemmas in lambda-Prolog
Andrew W. Appel, Amy P. Felty
ICLP1
1999 Hierarchical modularity
abstract
To cope with the complexity of very large systems, it is not sufficient to divide them into simple pieces because the pieces themselves will either be too numerous or too large. A hierarchical modular structure is the natural solution. In this article we explain how that approach can be applied to software. Our compilation manager provides a language for specifying where individual modules fit into a hierarchy and how they are related semantically. We pay particular attention to the structure of the global name space of program identifiers that are used for module linkage because any potential for name clashes between otherwise unrelated parts of a program can negatively affect modularity. We discuss the theoretical issues in building software hierarchically, and we describe our implementation of CM, the compilation manager for Standard ML of New Jersey.
Matthias Blume, Andrew W. Appel
ACM Trans. Program. Lang. Syst.2
1997 Lambda-Splitting: A Higher-Order Approach to Cross-Module Optimizations
abstract
We describe an algorithm for automatic inline expansion across module boundaries that works in the presence of higher-order functions and free variables; it rearranges bindings and scopes as necessary to move nonexpansive code from one module to another. We describe---and implement---the algorithm as transformations on λ-calculus. Our inliner interacts well with separate compilation and is efficient, robust, and practical enough for everyday use in the SML/NJ compiler. Inlining improves performance by 4--8% on existing code, and makes it possible to use much more data abstraction by consistently eliminating penalties for modularity.
Matthias Blume, Andrew W. Appel
ICFP2
1997 Shrinking lambda Expressions in Linear Time
abstract
Functional-language compilers often perform optimizations based on beta and delta reduction. To avoid speculative optimizations that can blow up the code size, we might wish to use only shrinking reduction rules guaranteed to make the program smaller: these include dead-variable elimination, constant folding, and a restricted beta rule that inlines only functions that are called just once. The restricted beta rule leads to a shrinking rewrite system that has not previously been studied. We show some efficient normalization algorithms that are immediately useful in optimizing compilers; and we give a confluence proof for our system, showing that the choice of normalization algorithm does not affect final code quality.
Andrew W. Appel, Trevor Jim
J. Funct. Program.1
1996 Iterated Register Coalescing
abstract
An important function of any register allocator is to target registers so as to eliminate copy instructions. Graph-coloring register allocation is an elegant approach to this problem. If the source and destination of a move instruction do not interfere, then their nodes can be coalesced in the interference graph. Chaitin's coalescing heuristic could make a graph uncolorable (i.e., introduce spills); Briggs et al. demonstrated a conservative coalescing heuristic that preserves colorability. But Briggs's algorithm is too conservative, and leaves too many move instructions in our programs. We show how to interleave coloring reductions with Briggs's coalescing heuristic, leading to an algorithm that is safe but much more aggressive.
Lal George, Andrew W. Appel
POPL2
1996 Empirical and Analytic Study of Stack Versus Heap Cost for Languages with Closures
abstract
Abstract We present a comprehensive analysis of all the components of creation, access and disposal of heap-allocated and stack-allocated activation records. Among our results are: •Although stack frames are known to have a better cache read-miss rate than heap frames, our simple analytical model (backed up by simulation results) shows that the difference is too trivial to matter. •The cache write-miss rate of heap frames is very high; we show that a variety of miss-handling strategies (exemplified by specific modern machines) can give good performance, but not all can. •Stacks restrict the flexibility of closure representations (for higher-order functions) in important (and costly) ways. •The extra load placed on the garbage collector by heap-allocated frames is small. •The demands of modern programming languages make stacks complicated to implement efficiently and correctly. Overall, the execution cost of stack-allocated and heap-allocated frames is similar; but heap frames are simpler to implement and allow very efficient first-class continuations.
Andrew W. Appel, Zhong Shao 0001
J. Funct. Program.1
1996 Iterated Register Coalescing
abstract
An important function of any register allocator is to target registers so as to eliminate copy instructions. Graph-coloring register allocation is an elegant approach to this problem. If the source and destination of a move instruction do not interfere, then their nodes can be coalesced in the interference graph. Chaitin's coalescing heuristic could make a graph uncolorable (i.e., introduce spills); Briggs et al. demonstrated a conservative coalescing heuristic that preserves colorability. But Briggs's algorithm is too conservative and leaves too many move instructions in our programs. We show how to interleave coloring reductions with Briggs's coalescing heuristic, leading to an algorithm that is safe but much more aggressive.
Lal George, Andrew W. Appel
ACM Trans. Program. Lang. Syst.2
1995 A Type-Based Compiler for Standard ML
abstract
Compile-time type information should be valuable in efficient compilation of statically typed functional languages such as Standard ML. But how should type-directed compilation work in real compilers, and how much performance gain will type-based optimizations yield? In order to support more efficient data representations and gain more experience about type-directed compilation, we have implemented a new type-based middle end and back end for the Standard ML of New Jersey compiler. We describe the basic design of the new compiler, identify a number of practical issues, and then compare the performance of our new compiler with the old non-type-based compiler. Our measurement shows that a combination of several simple type-based optimizations reduces heap allocation by 36%; and improves the already-efficient code generated by the old non-type-based compiler by about 19% on a DECstation 500.
Zhong Shao 0001, Andrew W. Appel
PLDI2
1995 A Debugger for Standard ML
abstract
Abstract We have built a portable, instrumentation-based, replay debugger for the Standard ML of New Jersey compiler. Traditional ‘source-level’ debuggers for compiled languages actually operate at machine level, which makes them complex, difficult to port, and intolerant of compiler optimization. For secure languages like ML, however, debugging support can be provided without reference to the underlying machine, by adding instrumentation to program source code before compilation. Because instrumented code is (almost) ordinary source, it can be processed by the ordinary compiler. Our debugger is thus independent from the underlying hardware and runtime system, and from the optimization strategies used by the compiler. The debugger also provides reverse execution, both as a user feature and an internal mechanism. Reverse execution is implemented using a checkpoint and replay system; checkpoints are represented primarily by first-class continuations.
Andrew P. Tolmach, Andrew W. Appel
J. Funct. Program.2
1994 Separate Compilation for Standard ML
abstract
Languages that support abstraction and modular structure, such as Standard ML, Modula, Ada, and (more or less) C++, may have deeply nested dependency hierarchies among source files. In ML the problem is particularly severe because ML's powerful parameterized module (functor) facility entails dependencies among implementation modules, not just among interfaces.
Andrew W. Appel, David B. MacQueen
PLDI1
1994 Axiomatic Bootstrapping: A Guide for Compiler Hackers
abstract
If a compiler for language L is implemented in L , then it should be able to compile itself. But for systems used interactively commands are compiled and immediately executed, and these commands may invoke the compiler; so there is the question of how ever to cross-compile for another architecture. Also, where the compiler writes binary files of static type information that must then be read in by the bootstrapped interactive compiler, how can one ever change the format of digested type information in binary files? Here I attempt an axiomatic clarification of the bootstrapping technique, using Standard ML of New Jersey as a case study. This should be useful to implementors of any self-applicable interactive compiler with nontrivial object-file and runtime-system compatibility problems.
Andrew W. Appel
ACM Trans. Program. Lang. Syst.1
1993 Smartest Recompilation
abstract
To separately compile a program module in traditional statically-typed languages, one has to manually write down an import interface which explicitly specifies all the external symbols referenced in the module. Whenever the definitions of these external symbols are changed, the module has to be recompiled. In this paper, we present an algorithm which can automatically infer the “minimum” import interface for any module in languages based on the Damas-Milner type discipline (e.g., ML). By “minimum”, we mean that the interface specifies a set of assumptions (for external symbols) that are just enough to make the module type-check and compile. By compiling each module using its “minimum” import interface, we get a separate compilation method that can achieve the following optimal property: A compilation unit never needs to be recompiled unless its own implementation changes.
Zhong Shao 0001, Andrew W. Appel
POPL2
1993 A Critique of Standard ML
abstract
Abstract Standard ML is an excellent language for many kinds of programming. It is safe, efficient, suitably abstract, and concise. There are many aspects of the language that work well. However, nothing is perfect: Standard ML has a few shortcomings. In some cases there are obvious solutions, and in other cases further research is required.
Andrew W. Appel
J. Funct. Program.1
1991 Virtual Memory Primitives for User Programs
abstract
Memory Management Units (MMUS) are traditionally used by operating systems to implement disk-paged virtual memory.!30me operating systems allow user programs to specify the protection level (inaccessible, readonly.read-write ) of pages, and allow user programs to handle protection violations.but these mechanisms are not, always robust, efficient,, or well-matched to the needs of applications,.We survey several user-level algorithms that make use of page-protection techniques, and analyze their common characteristics.in an attempt to answer the question, "M7hat virtual-memory primitives should the operating system provide to user processes, and how well do today's operating systems provide them?' for running it on SunOS.
Andrew W. Appel, Kai Li 0001
ASPLOS1
1990 An Advisor for Flexible Working Sets
abstract
The traditional model of virtual memory working sets does not account for programs that can adjust their working sets on demand. Examples of such programs are garbage-collected systems and databases with block cache buffers. We present a memory-use model of such systems, and propose a method that may be used by virtual memory managers to advise programs on how to adjust their working sets. Our method tries to minimize memory contention and ensure better overall system response time. We have implemented a memory “advice server” that runs as a non-privileged process under Berkeley Unix. User processes may ask this server for advice about working set sizes, so as to take maximum advantage of memory resources. Our implementation is quite simple, and has negligible overhead, and experimental results show that it results in sizable performance improvements.
Rafael Alonso, Andrew W. Appel
SIGMETRICS2
1989 Continuation-Passing, Closure-Passing Style
abstract
We implemented a continuation-passing style (CPS) code generator for ML. Our CPS language is represented as an ML datatype in which all functions are named and most kinds of ill-formed expressions are impossible. We separate the code generation into phases that rewrite this representation into ever-simpler forms. Closures are represented explicitly as records, so that closure strategies can be communicated from one phase to another. No stack is used. Our benchmark data shows that the new method is an improvement over our previous, abstract-machine based code generator.
Andrew W. Appel, Trevor Jim
POPL1
1989 Simple Generational Garbage Collection and Fast Allocation
abstract
Abstract Generational garbage collection algorithms achieve efficiency because newer records point to older records; the only way an older record can point to a newer record is by a store operation to a previously created record, and such operations are rare in many languages. A garbage collector that concentrates just on recently allocated records can take advantage of this fact. Such a garbage collector can be so efficient that the allocation of records costs more than their disposal. A scheme for quick record allocation attacks this bottleneck. Many garbage‐collected environments do not know when to ask the operating system for more memory. A robust heuristic solves this problem. This paper presents a simple, efficient, low‐overhead version of generational garbage collection with fast allocation, suitable for implementation in a Unix environment.
Andrew W. Appel
Softw. Pract. Exp.1
1989 Allocation without Locking
abstract
Abstract In a programming environment with both concurrency and automatic garbage collection, the allocation and initialization of a new record is a sensitive matter: if it is interrupted half‐way through, the allocating process may be in a state that the garbage collector cannot understand. In particular, the collector will not know which words of the new record have been initialized and which are meaningless (and unsafe to traverse). For this reason, parallel implementations usually use a locking or semaphore mechanism to ensure that allocation is an atomic operation. The locking significantly adds to the cost of allocation. This paper shows how allocation can run extremely quickly even in a multi‐thread environment: open‐coded, without locking.
Andrew W. Appel
Softw. Pract. Exp.1
1989 Vectorized garbage collection
Andrew W. Appel, Aage Bendiksen
J. Supercomput.1
1988 Real-Time Concurrent Collection on Stock Multiprocessors
abstract
We've designed and implemented a copying garbage-collection algorithm that is efficient, real-time, concurrent, runs on commercial uniprocessors and shared-memory multiprocessors, and requires no change to compilers. The algorithm uses standard virtual-memory hardware to detect references to “from space” objects and to synchronize the collector and mutator threads. We've implemented and measured a prototype running on SRC's 5-processor Firefly. It will be straightforward to merge our techniques with generational collection. An incremental, non-concurrent version could be implemented easily on many versions of Unix.
Andrew W. Appel, John R. Ellis, Kai Li 0001
PLDI1
1988 Simulating digital circuits with one bit per wire
abstract
An algorithm to simulate synchronous digital logic circuits in space proportional to one bit per wire, as long as the specification has a hierarchical nature, is described. An entire simulation might fit in the fast cache of some computers. The simulation algorithm is simple to implement, and runs relatively quickly. Although the algorithm has a quadratic worst-case running time, empirical results show that the running time for typical circuits is close to linear. The algorithm is reasonably time-efficient in absolute terms (a few microseconds per gate), although somewhat slower than recently developed event-driven or straight-line simulators, and much slower than word-parallel straight-line compiled simulators. In effect, the algorithm produces behavioral simulators automatically from a circuit description: each module is a subroutine that may be invoked from other parts of the circuit.>
Andrew W. Appel
IEEE Trans. Comput. Aided Des. Integr. Circuits Syst.1
1987 Garbage Collection can be Faster than Stack Allocation
Andrew W. Appel
Inf. Process. Lett.1
1987 Generalization of the Sethi-Ullman Algorithm for Register Allocation
abstract
Abstract The Sethi‐Ullman algorithm for register allocation finds an optimal ordering of a computation tree. Two simple generalizations of the algorithm increase its applicability without significantly increasing its cost.
Andrew W. Appel, Kenneth J. Supowit
Softw. Pract. Exp.1
1985 Semantics-Directed Code Generation
abstract
computer's memory after executionCode generation proceeds by successive reductions.Each transformation corresponds to a machine-operation; the reducer emits one line of assembly code as it performs each reduction:
Andrew W. Appel
POPL1