Run-Time Requirements for Compilers Compilers Spring 2001 Robert Dewar
Click here to load reader
Embed Size (px)
Transcript of Run-Time Requirements for Compilers Compilers Spring 2001 Robert Dewar
Run-Time Requirements for CompilersCompilersSpring 2001Robert Dewar
Major IssuesWhat is a compiler run-time?Major components of run-timeComputational SupportI/O interfacingStorage ManagementTasking interfacesException HandlingOther operating system issues
The Compiler Run-TimeSimple operations generate direct machine language (e.g. addition)But modern languages have many high level constructsCompiler generates calls to hidden routines called the run-time.Run-time is included silently in linked program (standard libraries used)
The Compiler Run-TimePart of the implementationNot available directly to programInterface may not be documentedSpecial calling sequences can be usedTailored asm may be appropriateSpecial operating system interfaceDelivered as part of the compilerLicensing considerations apply
Computational SupportSome simple operations may not be supported by instruction set64-bit integer arithmeticConversion of fpt to integerOverflow checkingFloating-point (emulation needed)Long shiftsSquare root
Handling Computational SupportNeed very small high efficiency routines, might possibly be inlinableSpecial calling sequences may be useful (e.g. args in registers)Assembly language may be reasonable in this caseImplementation is target dependent
Language ConsiderationsSome languages have no high level constructs, so need minimal run timeFor example, C, everything is done with explicit procedure calls.But other languages, e.g.C++ (stream operations)Ada (tasking)Java (automatic storage mgmt)
The Run-Time in CVery smallUsually only some computational routines.Standard has many standard functions as part of languageThese are explicit library routinesOften part of the underlying OSE.g. fopen, delete, etc.Command line interface needed
The Run-Time in AdaMuch more extensiveTaskingTimingStorage ManagementConversions (e.g. string to fpt)Requires extensive libraryOnly partly target dependent
Other LanguagesC++ nearer to C, but hasStreamsException HandlingJava, more extensive, addsStorage mgmt (garbage collection)Standardized arithmetic (IEEE fpt)Interface to JBC/JVM
Other Languages (cont)COBOL, much more extensiveDetailed complex I/O modelIncludes full indexed filesSORT subsystemINSPECT REPLACINGPICTURE editingDisplay and packed numeric formats
Other Languages (cont)Very high level languagesSetl, Python, GUILE, Visual BasicSet operationsGUI operationsHigh level operating systems interfacesE.g. COM/DCOM interfacingWeb interfacing
I/O interfaceLanguage may have explicit I/O statements, or rely on proc interfaceIn either case, have to map the language notion of I/O to op sysEnd of line (record vs stream)Notion of file system (directories?)Exception handlingCharacter sets (esp wide chars)
Implementing the I/O InterfaceTwo partsTarget independent codeTarget dependent codeTarget Independent codeSimply implements the language semanticsUsing some abstractions
Target Dependent I/OOn top of operating systemMap language semantics to OS semantics, deal with differences as well as possible.On a bare board, have to actually implement basic I/OPerhaps at the port levelBasically compiler includes an O/S
Storage ManagementStack AllocationHeap AllocationControlled AllocationAutomatic Garbage Collection
Stack ManagementStack must be allocated for each task in the programUsually handled by operating systemHave to worry about size of stackHow/whether to extend it as neededHow/whether to check stack overflowMay or may not be language required
Heap ManagementBasic semantics is Allocate/FreeParameters for allocationSize in bytesAlignment (often just use max alignment as required for example in C by malloc)Parameters for freeProbably just address (but perhaps size and aligmnent as well, as in Ada)
Heap AlgorithmsMany algorithms availableFree listMultiple free listsBinary allocatorPerformance considerationsAverage case timeWorst case time (real-time critical)Fragmentation considerations
OS Heap AllocationTypical O/S provides malloc/freeMalloc takes size in bytesReturns max aligned addressFree takes addressOptimized for average performanceOften algorithm is not documented
More on malloc/freeCan map language requirementsE.g. new in C++ or Ada maps to mallocUnchecked_Deallocation to freeMay want to allocate large blocks with malloc, subdivide for useBuilt in for PL/1 areasBuilt in for Ada collections with storage size clause given.
Commit StrategiesPhysical AllocationVirtual AllocationStorage committed at allocate timeStorage committed at use timeOverflow checkingIndication of out of memoryDifficulties with commit on use
Specialized StrategiesTrade off fragmentation with time performance.FragmentationInternal, block allocated is larger than needed by the allocation requestExternal, storage available, but not contiguous.
Example, Binary Storage Allocator (Buddy System)N free lists for 2**1, 2**2, 2**N unitsBlock of length 2**K is on 2**K boundary (last K address bits zero)To allocate block of length MUse next higher power of 2 (2**K)If available on free list grabIf not, allocate block of 2**(K+1), splitFree recombines if possible
BinaryAllocator Performance IssuesInternal FragmentationNeed 40 bytes, get 64 bytes, 24 wastedExternal FragmentationMay have 2 non-contiguous 128 byte blocks, but cannot allocate 256 bytesPerformanceBounded (at most K allocation steps)
Controlled AllocationIn C++, constructors automatically allocate storage, destructors free storage.In Ada, controlled type Initialize allocates, Finalize frees storage.Can be used for other than storage issues, but 99% of time usage is for allocate/free of memory
Implementing Controlled StorageCompiler inserts automatic calls to constructors and destructorsIn GNAT, you can use gnatG to see this happening in the expanded code.Constructors/destructors contain appropriate storage mgmt calls.
Automatic Garbage CollectionAllocate storage as neededFree storage automatically when no longer needed.Concept of reachabilityCan garbage collect when non-reachable.Possibly compact storageConsiderations of adjusting pointers
Determining Blocks in UseAssume that we can tell what blocks are currently allocated.We have certainly starting pointsGlobal and local variablesRegister contentsThese are called roots
Tracing Blocks in UseNeed to find all pointers in blocks in use, and recursively trace other blocks in use, following all pointers.Two approachesConservativeType-Accurate
Conservative TracingConservative Garbage CollectionIf it looks like a pointer, assume it isWill never release used storageMay hold onto garbageType-Accurate Garbage CollectionKnow where pointers areTrace only pointers, knowing types
Further Steps in GCOnce all blocks in use are tracedFree all remaining blocksPossibly compact blocks in useAdjust pointers if compactionRequires type accurate tracingSince only pointers must be adjustedEliminates external fragmentation
Concerns with GCStop the world and GCNot good for a rocket launch!Or even for an ATM/Web use if too slowParallel garbage collectionGC as you go alongHave a separate processor doing GCRequires delicate syncrhonization
Reference CountsEach block has a count of number of pointers to the block.Copying a pointer increments countDestroying a pointer decrements countIf count goes to zero, free blockBut cycles can be complete garbage and never freed.
TaskingMight be done with explicit libraryE.g. use of POSIX threads in CNo special compiler considerationsExcept for synchronization issuesE.g. when stuff can be held in registersVOLATILE/ATOMIC considerationsPOSIX/Threads is almost standardNot perfect, some variationsNot always completely implemented yet
Language Tasking ConstructsThreads in JavaTasks in AdaBuilt in defined semanticsMay be more or less precisely defined with respect toPriority handlingGuaranteed performanceDispatching issues (e.g. time slicing?)
Implementing TaskingMap tasks onto OS threads1/1 (each task is a thread)Many/1 (multiple tasks to a thread)All/1 (dont need OS threads)Cannot map tasks to processesBecause of address space issuesMay be difficult to get exact semantic equivalence.
Difficulties in Implementing Tasking, an ExampleCeiling priority protocolRaise priority to ceilingGrab resource, do processingLower priority to ceilingBut does last step lose controlIn Ada, never to equal prio taskIn POSIX, may well add to end of queue, thus losing control.
Bare Board Implementations of TaskingIf no operating system, then no threads to map to.Basically must write an executive that provides this capabilityThe compiler system ends up including a small tasking executive, a mini-operating system.
Implementations of Exception HandlingC++, Java and Ada share same same basic model of exceptions.Replacement semanticsRaise/Throw an exceptionAbandons current executionStrips stack framesTill exception is handled/caught
The setjmp/longjmp method for exceptions.When a handler is encountered, save enough machine state to restore as required (setjmp)When a throw occurs, restore most recently saved state (longjmp)Requires a stack of saved statesFast throw, but handlers cost
Zero-cost Exception HandlingA handler generates only static tables (PC range and handler ID)Throw unwinds stack framesRestoring all registersFind return pointsCheck return point against PC tableJump to handler on a match
More on Zero-cost approachRequires tight integration with compilerSt