Some details of implementation - PowerPoint PPT Presentation

About This Presentation
Title:

Some details of implementation

Description:

associates M with the compiled function ... (their use only in scope was assured at compile-time ) ... Compiler compiles each non-local use v to code for a ... – PowerPoint PPT presentation

Number of Views:11
Avg rating:3.0/5.0
Slides: 22
Provided by: off9
Category:

less

Transcript and Presenter's Notes

Title: Some details of implementation


1
Some details of implementation
  • As part of / extension of type-checking
  • Each declaration d(x) associated with a type
  • ? type size information
  • Compiler decides on
  • Address (see below)
  • Size of storage
  • Each use u(x) associated with some d(x)
    compiler generates code to access allocated
    address (for read/write/)

2
  • On address allocation
  • For global block fixed addresses
  • For functions
  • Many calls ? many allocations
  • Allocated at run-time
  • address allocation and access code are
    relative to (yet unknown) base address
    (assumed to be stored in a register
    at run-time)
  • If total size for parameters is M, compiler
  • associates M with the compiled function
  • generates code to allocate M at run-time when
    the function is called
  • (the estimate M is modified below)

3
  • At run-time when a function value is applied
  • a memory chunk S of size M is allocated
  • the values of the arguments are stored
  • In S (in right positions) , or
  • Elsewhere (in the heap) references are stored
    in S
  • Arg. Values may be variable size (inconvenient
    for implementation)
  • Another reason next chapter
  • Base address of S is put into a register, valid
    for this activation
  • Access for resolution of a use is by relative
    addressing ? one machine instruction

4
  • Extension for other blocks (let/let/letrec/letrec
    )
  • Compiler also knows types sizes of variables
    declared locally in a function
  • It associates a relative address also to each
    variable
  • name conflicts (variable x in different
    blocks) are no problem each d(x) is
    associated with a distinct address
  • (essentially, variables are re-named
    to distinct names --- the addresses)
  • Each use u(x) is associated with one d(x)
    relative access code is generated (scope rules
    used here)
  • The size M for a function the allocated chunk S
    include the parameters all locals
  • (same for global block)

5
  • When a function value is applied (revisited)
  • A memory S of size M for the arguments and
    locals is allocated (only exception real-time
    with small memory)
  • -- essentially frames of parameters and locals
    are merged into an extended frame
  • the values of the arguments are stored
    immediately
  • variables bound to cells these are effectively
    allocated
  • Other variable bindings code for processing the
    defining expressions is generated in the right
    places
  • (their use only in scope was assured at
    compile-time )
  • Address allocation, relative addressing (for
    locals) as described above
  • Access for resolution of parameters locals is
    by one machine instruction

6
  • Example ( C)
  • int x
  • int f(double x)
  • int y, z
  • Note the actual names are not used at run-time

memory chunk for global block
x ref to fv
7
  • Parameters and locals are accessed efficiently
  • What about global variable access?
  • The static (nesting) depth, of a use u(x),
    sd(u(x)) of function boundaries to its
    binding declaration d(x)
  • (given that local blocks are merged into
    function, the compiled static depth counts only
    function boundaries)
  • sd(u(x)) -- the number of frame hops needed to
    get to a binding for it
  • this number is known to the compiler!

8
  • Contd
  • Compiler compiles each non-local use v to code
    for a loop to traverse sd(v) links of static
    parents , followed by relative access to right
    position
  • Summary
  • Variable declarations are replaced by positions
  • Uses (both locals and non-locals) are compiled to
    access code to these positions
  • ? Compilation generates efficient computation
  • ( rule alpha!)


9
  • Implementation of function values
  • A function value is implemented by a pair of
    pointers
  • To the compiled code, (including code to
    allocate storage, to store return value, .. )
  • To a (extended) frame, static parent pair (its
    environment)

10
Life and death on the stack
  • Two approaches to programming languages
    implementation
  • Stack-based a run-time stack of activation
    records (one per function activation
    corresponds to conceptual activation stack)
    common for imperative/OO pls
  • Continuation-based do not employ a stack common
    for functional languages
  • We discuss the stack-based

11
  • An activation record contains activation-relevant
    data
  • Saved registers
  • Return address
  • Dynamic pointer
  • .. (more such data)
  • one of
  • (extended) frame , static (parent) pointer
    (automatic storage)
  • A reference to frame, static pointer (heap
    storage)
  • Heap A storage area allocated for a program,
    contains
  • Internal, run-time data structure
  • Program data
  • Q what determines which of these two is
    selected?

12
  • We consider two questions
  • What determines whether a frame is stored in the
    activation record on the stack, or in the heap?
  • Can cells be allocated for parameters/locals on
    the stack, or should they be allocated in the
    heap?
  • Pros cons of stack allocation
  • (de-)allocation is very efficient (hardware
    support)
  • Data stored in activation record die when it is
    popped
  • ?Need to understand liveness (only for the 2
    questions)

13
  • Example (a simple counter object)
  • (define counter
  • (let ((count 0))
  • (lambda (msg)
  • (cond ((eqv? msg show) count)
  • ((eqv? msg inc) (set! count (
    1 count))))))
  • counter is bound to a function value with a
    reference to a frame that corresponded to a
    dead activation (de-allocated from stack)
  • This frame is live (reachable from a live
    activation)
  • ? The frame must reside in the heap

14
  • Liveness definition for func. values, frames,
    bindings
  • (conservative definition)
  • Liveness reachable
  • A binding is reachable if it is stored in
    reachable frame
  • A frame is reachable if it is
  • Associated with a live activation
  • Frame of a reachable function value
  • Reachable by static parent reference from a
    reachable frame
  • A function value is reachable if it is the value
    in a reachable binding
  • (the above contains mutual
    recursion, what is the base case?)

15
  • Addition a func. value is live, but not bound,
    when
  • Created as anonymous function
  • Is the value of an expression (e.g., a function
    call)
  • In 1st case,
  • if immediately applied, then use and throw -- not
    stored, irrelevant to current discussion
  • If bound to an identifier, then covered by the
    definition
  • If expression value that is 2nd case
  • In 2nd case, the interesting situations are
    (why?)
  • It is the return value from a function call
  • It is passed as a parameter to a function call
  • Of these two, only the first should really worry
    us why?

16
  • Restriction P (used in Pascal)
  • Pascal allows nesting of function expressions,
    but
  • A locally generated function can be passed
  • to functions invoked in the activation (stack
    grows)
  • but never out of the activation down the stack
  • ? when activation dies, so does the frame, and
    the bindings in it (there is no live function
    value that references it)
  • The restriction must apply also to functions
    stored in cells or data structures cannot
    return anything containing a function

a function call cannot return a function value
17
  • Example
  • Main
  • func D(func z, int x) . z(x),
  • func E(int x)
  • func F(func C)
  • func G(int y) F(D),..D(F,y),
  • G(x3)
  • E(5)
  • Main starts ? values d and e for D, E are
    created
  • Calls e(5) ? values f and g for F and G are
    created
  • Starts g(8) ? can call a static brother (f) / a
    static uncle (d) of g
  • In either case, the dynamic activation stack grows

Mutually recursive
Mutually recursive
18
  • In Pascal, frame with bindings stored in
    activation record (when activation dies, they
    certainly cease to be live)
  • Functions can be created locally, then passed as
    parameters
  • Static pointer (reference to static parent) is
    needed
  • It always points to an activation record deeper
    in the stack
  • (there is an alternative implementation strategy
    store static pointers for activations in a
    vector we skip)

19
  • Restriction C (used in C)
  • All the bindings generated in program outside
    functions are stored in one global frame (fixed)
  • (addresses for all global variables
    computed at compile-time)
  • A function value knows about the variables
    declared before it in program
  • That it uses only these is checked by the
    compiler
  • Bindings for parameters locals in a function
    call are stored in a extended frame for the
    activation
  • The static parent of each activation record is
    the global frame ? not needed

No function nesting allowed all functions are
global
20
  • Summary In Pascal, C (and similar imperative
    pls)
  • Restrictions on functions guarantee that frame
    and bindings created for an activation die with
    it
  • Bindings stored in activation record (automatic)
  • fast (de-)allocation
  • Additionally
  • That uses are in scope is checked at compile-time

21
  • At one extreme is C
  • Does not believe in function nesting
  • Extremely simple environment structure
  • At the other extreme are functional pls
  • No restrictions on nesting, heavy use of
    higher-order functions
  • Environment structure (frames) separated from
    run-time stack, stored in heap
  • Rely on garbage collection
  • (In some implementations, even an activation
    stack is absent)
Write a Comment
User Comments (0)
About PowerShow.com