HOT-Compilation: Garbage Collection

Similar documents
Worksheet #4. Foundations of Programming Languages, WS 2014/15. December 4, 2014

CMSC 330: Organization of Programming Languages

Lecture 13: Garbage Collection

CS 536 Introduction to Programming Languages and Compilers Charles N. Fischer Lecture 11

Heap Management. Heap Allocation

CMSC 330: Organization of Programming Languages

CS61, Fall 2012 Section 2 Notes

Deallocation Mechanisms. User-controlled Deallocation. Automatic Garbage Collection

Programming Project 4: COOL Code Generation

Compiler Construction D7011E

CMSC 330: Organization of Programming Languages. Memory Management and Garbage Collection

Programming Assignment IV Due Thursday, November 18th, 2010 at 11:59 PM

Garbage Collection (1)

Introduction to C Language (M3-R )

Class Information ANNOUCEMENTS

15-122: Principles of Imperative Computation, Fall 2015

The Dynamic Typing Interlude

Lecture 15 Garbage Collection

Programming Assignment IV Due Thursday, June 1, 2017 at 11:59pm

CSE 351, Spring 2010 Lab 7: Writing a Dynamic Storage Allocator Due: Thursday May 27, 11:59PM

Short Notes of CS201

Reference Counting. Reference counting: a way to know whether a record has other users

EL6483: Brief Overview of C Programming Language

Automatic Memory Management

ECS 153 Discussion Section. April 6, 2015

CS201 - Introduction to Programming Glossary By

EECE.2160: ECE Application Programming

CS 137 Part 8. Merge Sort, Quick Sort, Binary Search. November 20th, 2017

C Programming. Course Outline. C Programming. Code: MBD101. Duration: 10 Hours. Prerequisites:

Reference Counting. Reference counting: a way to know whether a record has other users

CS 4120 Lecture 37 Memory Management 28 November 2011 Lecturer: Andrew Myers

Lecture Notes on Advanced Garbage Collection

Qualifying Exam in Programming Languages and Compilers

CITS3211 FUNCTIONAL PROGRAMMING. 14. Graph reduction

Agenda. CSE P 501 Compilers. Java Implementation Overview. JVM Architecture. JVM Runtime Data Areas (1) JVM Data Types. CSE P 501 Su04 T-1

CS 241 Honors Memory

Lecture 7 More Memory Management Slab Allocator. Slab Allocator

CS61C : Machine Structures

A Fast Review of C Essentials Part I

In Java we have the keyword null, which is the value of an uninitialized reference type

Automatic Garbage Collection

Run-Time Environments/Garbage Collection

Lecture Notes on Memory Layout

Recitation #11 Malloc Lab. November 7th, 2017

Topic 6: A Quick Intro To C. Reading. "goto Considered Harmful" History

Outline. Computer programming. Debugging. What is it. Debugging. Hints. Debugging

Compilers. 8. Run-time Support. Laszlo Böszörmenyi Compilers Run-time - 1

Vector and Free Store (Pointers and Memory Allocation)

One-Slide Summary. Lecture Outine. Automatic Memory Management #1. Why Automatic Memory Management? Garbage Collection.

CS61C : Machine Structures

Dynamic Data Structures (II)

Design Issues. Subroutines and Control Abstraction. Subroutines and Control Abstraction. CSC 4101: Programming Languages 1. Textbook, Chapter 8

Garbage Collection. Steven R. Bagley

Manual Allocation. CS 1622: Garbage Collection. Example 1. Memory Leaks. Example 3. Example 2 11/26/2012. Jonathan Misurda

Run-time Environments - 3

Malloc Lab & Midterm Solutions. Recitation 11: Tuesday: 11/08/2016

Memory Management. Memory Management... Memory Management... Interface to Dynamic allocation

Week 5, continued. This is CS50. Harvard University. Fall Cheng Gong

Intermediate Programming, Spring 2017*

Run-time Environments

Run-time Environments

Name: CIS 341 Final Examination 10 December 2008

CS52 - Assignment 8. Due Friday 4/15 at 5:00pm.

Garbage Collection Algorithms. Ganesh Bikshandi

Lecture 20 C s Memory Model

Declaring Pointers. Declaration of pointers <type> *variable <type> *variable = initial-value Examples:

Writing a Dynamic Storage Allocator

What goes inside when you declare a variable?

Lecture Topics. Administrivia

Topic 6: A Quick Intro To C

Programming with MPI

(T) x. Casts. A cast converts the value held in variable x to type T

Runtime. The optimized program is ready to run What sorts of facilities are available at runtime

Practice Problems for the Final

CS 137 Part 5. Pointers, Arrays, Malloc, Variable Sized Arrays, Vectors. October 25th, 2017

CS Programming In C

Recitation #12 Malloc Lab - Part 2. November 14th, 2017

Garbage Collection. Vyacheslav Egorov

Lecture 8 Dynamic Memory Allocation

CS61A Notes 02b Fake Plastic Trees. 2. (cons ((1 a) (2 o)) (3 g)) 3. (list ((1 a) (2 o)) (3 g)) 4. (append ((1 a) (2 o)) (3 g))

CS61C : Machine Structures

CS24: INTRODUCTION TO COMPUTING SYSTEMS. Spring 2017 Lecture 7

Programming refresher and intro to C programming

Function Call Stack and Activation Records

CE221 Programming in C++ Part 2 References and Pointers, Arrays and Strings

Quiz 0 Review Session. October 13th, 2014

QUIZ. What is wrong with this code that uses default arguments?

CSCI 171 Chapter Outlines

Object Oriented Programming: In this course we began an introduction to programming from an object-oriented approach.

Provided by - Microsoft Placement Paper Technical 2012

CS1622. Semantic Analysis. The Compiler So Far. Lecture 15 Semantic Analysis. How to build symbol tables How to use them to find

COSC 2P91. Introduction Part Deux. Week 1b. Brock University. Brock University (Week 1b) Introduction Part Deux 1 / 14

Lists (Section 5) Lists, linked lists Implementation of lists in C Other list structures List implementation of stacks, queues, priority queues

CS577 Modern Language Processors. Spring 2018 Lecture Garbage Collection

Chapter 1 GETTING STARTED. SYS-ED/ Computer Education Techniques, Inc.

ECE 375: Computer Organization and Assembly Language Programming

C & Data Structures syllabus

Lecture 20 Notes C s Memory Model

Recitation 10: Malloc Lab

A program execution is memory safe so long as memory access errors never occur:

Transcription:

HOT-Compilation: Garbage Collection TA: Akiva Leffert aleffert@andrew.cmu.edu Out: Saturday, December 9th In: Tuesday, December 9th (Before midnight) Introduction It s time to take a step back and congratulate yourself. You ve implemented large parts of an SML compiler. The stages after closure conversion hoisting, allocation, code generation, are not very interesting, at least with a naive implementation. However, even after code generation, the job of the compiler writer is not yet done. Modern languages typically provide automatic memory management facilities packaged as part of a runtime. This constitutes an allocator and a garbage collector. In this assignment you will be implementing a simple garbage collector. More specifically, you will be implementing a copying garbage collector using the Cheney scan algorithm. 2 Overview For this assignment, you ll need to dust off your C hacking skills. You will implement the functions declared in runtime/gc.h. Prototypes for the two functions are reproduced here: hotcint_t gc_init(hotcint_t space_size, void gc_collect(hotc_t* root, Implementation of these functions should go in runtime/gc.c. We will explain the purpose of and parameters to each of these functions in Section 5. You may find useful macros defined in runtime/runtime.h. We provide you with the skeleton of a compiler based around the code you have written for the previous assignments and will write for this assignment. Simply drop your assignment solutions into the appropriate directory. Once you have run make, you can invoke it with the following command:./hotc <filename> This command accepts the flag -o <outfile> to control the name of the output binary. The default output binary name is a.out. Despite the presence of this compiler, we recommend you test your code using small C programs as they will be easier to understand and trace. To build a C file named, for example, test.c, run the following at the command line: gcc test.c -Iruntime runtime/runtime.c runtime/gc.c -falign-functions

Executables generated by this take an optional integer argument which represents the size of the heap in bytes. The default value is 0000. We include a selection of tests in the tests directory. Do not consider your implementation exhaustively tested if you pass those tests. Additionally, You many find the -g flag to gcc useful. It generates debugging information for use with gdb. Also, note that the runtime only works on 32-bit machines and is only guaranteed to work on the andrew system. Submit your code via AFS by copying gc.c to the directory /afs/andrew/course/5/50-89/submit/<your andrew id>/gc/ Note: Your submission will be graded automatically; if you submit a gc.c that fails to compile under the version of GCC on andrew (3.4.6) using this assignment s base distribution, we won t be able to grade it. 3 Memory Management In this section we explain how an allocator based around a garbage collector works. We then explain the structure of a copying collector. While you will only be implementing a collector, the collector will need to allocate memory during the copying phase of a collection as well as manage state used by the allocator so you ll need to understand how it works. 3. Allocation We use a linear allocation scheme. That is, the allocator assumes that it has a contiguous region of memory and simply steps through that region as it recieves allocation requests. It keeps a pointer to the beginning of the unassigned part of the region. This pointer is the allocation pointer. When the allocator receives an allocation request it simply increments the allocation pointer by the size of the request. We make the (reasonable) assumption that memory is not infinite. As such, the allocator can reach the end of its memory region. The allocator further assumes that it has a pointer to the end of the allocation memory region so that it can determine when it has reached the end. This is the limit pointer. If an allocation would cause the allocation pointer to move beyond the limit pointer, the allocator will invoke the garbage collector, hopefully clearing enough space to make the allocation. The collector will return a new allocation pointer and limit pointer when invoked. If, after a collection, there is still not enough space, the program exits with an error. For our implementation of an allocator, and the one which you ll be testing against, see the hotc check and hotc alloc functions in runtime/runtime.c.we decouple the checking and allocation stages so that all of the checking can be done at the beginning of a function, combining multiple checks into one big check with the cost of just one. 3.2 Copying Collection Typical semispace collectors, including the one you will implement, divide memory into two regions called the from-space and the to-space. Such collectors are called semispace collectors. The two blocks of memory often exchange roles during the run of the program. Allocation is always done in the current to-space. Thus only half of memory can actually be used at any one time. During a collection, the from-space and the to-space swap pointers. Then all reachable objects are copied from the new from-space to the new to-space. A reachable object is one which may be used by the program at any point in the future. The collector assumes there is a root pointer which is connected to all reachable pieces of memory by traversing the memory graph starting at the root. The obvious way to copy all of the reachable objects is to perform a depth first traversal, starting at the root node and copying each thing it points to and so on recursively. The things an object points to are known as its children. This strategy has three problems. First, such a traversal can loop forever if there is a cycle in the memory graph. Second, if two objects point to the same object, a naive traversal would make two copies of that object. Third, such a traversal uses memory linear in the depth of the traversal. Putting this memory on the stack is a problem because a deep memory graph would cause a stack overflow. 2

Putting it on the heap would require having another memory manager just to do memory management, which is possible (and indeed your code will need to call malloc during initialization), but undesiriable for code, runtime, and memory complexity reasons. The Cheney scan algorithm solves all these problems. Before we state the algorithm in pseudo-code, we will introduce the basic concepts. The first is that of a forwarding pointer. This will be used to solve the problem of multiple copies and memory cycles. The idea is to have a data structure that indicates if an object has been copied and if so, to where. The new location of that object is called the object s forwarding pointer. With a forwarding pointer structure, before copying an object, we can see if it already has a forwarding pointer. If it does, instead of copying, we simply overwrite the pointer to the object with its new location. If the object does not have a forwarding pointer then we copy it and set its forwarding pointer before traversing the object s children. In this way we never copy an object more than once and object aliases remain synchronized. It happens that an object s forwarding pointer typically doesn t need to be put in an auxiliary data structure but rather can be written over the header of the old object since its data has been copied somewhere else. You should take advantage of this in your collector. The Cheney scan algorithm replaces the linear memory usage of a typical DFS with a single extra pointer. This pointer is called the scan pointer, or sometimes the gray pointer. After we copy an object using this algorithm we do not immediately copy the object s children as we would in a DFS. Instead, we use a different method of traversal. All objects we have copied so far exist in the to-space. Therefore we can simply linearly step through the objects in the to-space starting at the beginning. Think of this as the queue in a breadthfirst search. Each copied object gets put in the end of the queue (the allocation point in the to-space), and we trace its children only when we reach it in the queue with the scan pointer. After we copy an object (or not if it has a forwarding pointer) we simply increment the scan pointer to the start of the next object. When the scan pointer reaches the allocation pointer we know that all the objects in the from-space have been copied. Pseudo-code for the garbage collection algorithm appears in Figure. Your actual code should look similar to this but handle several important special cases. Relevant implementation details will be explained in the next section. 4 Value Representations The HOT Compiler converts all values into one of two forms: pointers to tuples and everything else. We will call the second type of value a primitive though there is nothing necessarily primitive about them. Such a value may be hiding a large complicated data structure, just one the garbage collector shouldn t try to traverse through. All these values are the size of a word - 4 bytes on a 32-bit architecture. Only pointers to tuples will have children (the elements of the tuple). Thus, you will need to modify the pseudocode in Figure, which assumed all objects were of the same form. Pointers to tuples have the lowest bit set to 0. Primitives have the lowest bit set to. This means, among other things, that the default for arithmetic is 3-bit with the lowest bit as and the integer value shited left bit. Primitives should not be recursed through by the garbage collector. For example, your collector should recognize a 3-bit integer like 0, represented as the tagged, 32-bit value 2 ((0 << ) = 2)), by seeing that the lowest bit is set and know not to copy it when the copy part of the algorithm is called on it, but rather pass the value back out unchanged. We assign all values the type hotc t which is declared in runtime/runtime.h and is duplicated in Figure 2. This type is declared as a union of many things to lessen the burden of casting within the runtime - don t be distracted by the number and name of fields. All representation information you need to know about will be described in this document. To access subfields of an object you can use the different selectors. For example, assume for the moment that the size of a pointer to a tuple is stored in its first element (the actual details are slightly more complicated than that and will be explained in the next section. To access this value for some pointer p you would say p.arr[0].num. 3

collect: to_space, from_space = from_space, to_space alloc_pointer = to_space limit_pointer = alloc_pointer + space_size scan_pointer = alloc_pointer *root = copy(*root) while scan_pointer < alloc_pointer: for p in children(scan_pointer): *p = copy(*p) scan_pointer = scan_pointer + size(scan_pointer) copy(p): if is_forwarded(p): return get_forwarding_pointer(p) else: memcpy(p, alloc_pointer) new_address = alloc_pointer forwarding_address = alloc_pointer set_forwarding_address(p, alloc_pointer) alloc_pointer = alloc_pointer + size(p) return forwarding_address Figure : Cheney scan copying collection algorithm union hotc_t { hotcint_t num; hotcstr_t str; hotcchr_t chr; union hotc_t* arr; void* fun; }; Figure 2: Internal universal type 4

3 0 0 0 63 2 (tuple size field) 33 32 95 23(integer value) 65 64 Tag bit 42(integer value) Figure 3: Layout of the tuple (23, 42) 4. Tuple Layout Tuples are represented as a C array where the first element is a header field followed by a sequence of words of the indicated size. The header field keeps track of the number of words which follow the header field. Thus, the total size of the array in words is that size plus one. However, the header field is not just an integer, its lowest bit and highest bit are significant. Thus the actual size value is stored in the middle 30 bits as an unsigned integer. The lowest bit is reserved for your use. We suggest you use it to mark whether you have overwritten the header field with a forwarding pointer. This usage will never conflict with the bits of a pointer as the allocator always returns word aligned pointers. The high bit is an indication for the garbage collector not to trace the children of the object. If this bit is on, the collector should not recurse through the children of an object when stepping through the to-space. We call such objects untraced. This allows the runtime system to create objects that it does not want the garbage collector to trace through like any other value. This protection enables the implementation of values where the lowest bit is not, allowing the implementation of things like 32-bit integers and strings. Figure 3, presents the memory layout of the tuple (23, 42). When examining this diagram, remember that integers are tagged, so that they are shifted up bit, with the lowest bit set to. Figure 4 shows the null-terminated string hello as an untraced tuple. Since the text of the string is in an untraced tuple, the collector shouldn t try to trace every four characters as if they were a value or pointer. 5 Implementation As mentioned in the overview, you will implement two functions, plus whatever helper functions and global data you may need. Now that you understand the details of copying collection, we can explain the interface properly. 5

3 0 0 2 (tuple size field) 63 56 48 40 32 l l e h 95 64 - - \0 o unused bytes null terminator Figure 4: Layout of the tuple hello hotcint_t gc_init(hotcint_t space_size, The first argument to gc init is the size, in bytes, of each semispace. You will need to allocate two regions, the starting from-space and the starting to-space. Each of these should be of this size. You should do this using malloc. You should place the start of the to-space into the allocp argument and the end of the to-space into the limitp argument. Signify any initialization errors, such as malloc failures by returning a non-zero value. A return value of zero signifies successful initialization of the garbage collector. void gc_collect(hotc_t* root, The gc collect function is the function which should implement the collection algorithm previously described. The first argument is a pointer to the root pointer. The second and third arguments should receive the new allocation pointer and limit pointer respectively. After a call to this function, the to-space should contain no garbage and be ready for allocations starting at allocp. 6