My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
HowFlexcoverWorks  
How the Flexcover SDK works
Updated Feb 4, 2010 by joseph.b...@gmail.com

Basic Principles

The Flexcover SDK works by injecting calls to a global top-level function named coverage() into the emitted bytecode in a SWF. This function takes a single argument that encodes a location in the program, where the location may be either a line number or a branch identifier. At runtime, the expectation is that coverage() will log this information to some destination capable of analyzing it. Analysis is the job of the flexcover project; all the Flexcover SDK does is to ensure that this information actually gets passed to these function calls.

Thus, the resulting program must be linked with a SWC that defines a function declared as public function coverage(key:String). This function is external to the Flexcover SDK and is defined as part of the flexcover codebase, in the CoverageAgent subproject.

General Approach

The injection of coverage function calls is performed in the actual bytecode emitter, i.e. the code generation part of the compiler. This is comparatively easy because it is very similar to the way that debug line information is generated, and in fact Flexcover piggybacks its approach on the generation of this debug info.

Other implementation choices could have been made. For example, the syntax tree generation could have been modified to synthesize calls to coverage(...) at every statement break or the head of every conditional clause. This would have required much more work, a deeper understanding of the compiler, and would have a much larger patch cross-section in the compiler codebase. It would perhaps have distinct advantages though, since it would eliminate some "nonsense branches" that are an artifact of the way the compiler generates conditionals in some situations.

Implementation Notes

modules/asc/src/java/macromedia/asc/semantics/Emitter.java:
modules/asc/src/java/macromedia/asc/semantics/FlowGraphEmitter.java
 * StartMethod() passes additional info into ByteccodeEmitter to allow instrumentation
 * If, LoopEnd take additional args, to inhibit unwanted instrumentation

modules/asc/src/java/macromedia/asc/semantics/CodeGenerator.java
 * coverageScopes maintains a stack that is pushed/popped by function scopes, allowing the name of the current function to be available for generating coverage line/branch keys.  It also is used to hack up a synthetic name for anonymous functions and constructors.

modules/asc/src/java/macromedia/asc/util/ContextStatics.java
modules/asc/src/java/macromedia/asc/util/Context.java
 * The coverageKeys set accumulates a list of all coverage keys generated by instrumentation during the processing of some source module.  These are later emitted into a .cvm file.

modules/asc/src/java/macromedia/asc/embedding/avmplus/DebugInfo.java
 * the debug_branch_file_dirty and debug_function_dirty are used to prevent duplicate instrumentation of the same entity in the code.

modules/asc/src/java/macromedia/asc/embedding/avmplus/ActionBlockEmitter.java
 * If(), LoopEnd() patched to record branch coverage
 * flushDebugInfo() patched to record line coverage

modules/compiler/src/java/flex2/tools/flexbuilder/BuilderApplication.java
modules/compiler/src/java/flex2/tools/flexbuilder/BuilderLibrary.java
modules/compiler/src/java/flex2/tools/flexbuilder/BuilderConfiguration.java
modules/compiler/src/java/flex2/tools/oem/Application.java
modules/compiler/src/java/flex2/tools/oem/Library.java
modules/compiler/src/java/flex2/tools/oem/Configuration.java
modules/compiler/src/java/flex2/tools/oem/Report.java
modules/compiler/src/java/flex2/tools/oem/internal/ConfigurationConstants.java
modules/compiler/src/java/flex2/tools/oem/internal/OEMConfiguration.java
modules/compiler/src/java/flex2/tools/oem/internal/OEMReport.java
modules/compiler/src/java/flex2/tools/oem/internal/LinkerConfiguration.java
modules/compiler/src/java/flex2/tools/oem/internal/OEMUtil.java
modules/compiler/src/java/flex2/tools/oem/internal/ApplicationCompilerConfiguration.java
modules/compiler/src/java/flex2/tools/oem/internal/LibraryCompilerConfiguration.java
 * handling of coverage-related compiler options

modules/compiler/src/java/flex2/tools/Compc.java
modules/compiler/src/java/flex2/tools/SwcChecksums.java
modules/compiler/src/java/flex2/tools/Compiler.java
modules/compiler/src/java/flex2/linker/Configuration.java
modules/compiler/src/java/flex2/linker/API.java
modules/compiler/src/java/flex2/linker/SimpleMovie.java
modules/compiler/src/java/flex2/linker/CoverageMetadataWriter.java
modules/compiler/src/java/flex2/linker/FlexMovie.java
modules/compiler/src/java/flex2/compiler/Source.java
modules/compiler/src/java/flex2/compiler/CompilationUnit.java
 * emission of .cvm files

modules/compiler/src/java/flex2/compiler/as3/Compiler.java
 * synthesize a phony reference to the coverage() function so it gets linked in
 * propagate coverage keys from Context up into CompilationUnits for later emission as .cvms

modules/compiler/src/java/flex2/compiler/as3/BytecodeEmitter.java
 * actual generation of coverage() calls for line and branch instrumentation

Sign in to add a comment
Powered by Google Project Hosting