Skip to content

Latest commit

 

History

History
114 lines (79 loc) · 5.71 KB

HACKING.markdown

File metadata and controls

114 lines (79 loc) · 5.71 KB

Hacking GHCJS

If you want to hack on GHCJS, please join our friendly community on IRC at #ghcjs on freenode (You're also welcome if you only use the compiler or just want to chat about it!). The channel can be quiet from time to time, but with a little patience you should be able to find people to get you started or point you in the right direction.

The repositories you will be interested in are:

  • https://github.com/ghcjs/ghcjs

    The compiler itself, code generator, linker, test suite

    examples:

    • Executables ( src-bin )
    • Main code generator ( src/Gen2/Generator.hs )
    • Optimizer ( src/Gen2/Optimizer.hs )
    • Linker ( src/Gen2/Linker.hs )
    • Generated runtime code (h$ap_x_y etc): ( src/Gen2/RtsApply.hs )
  • https://github.com/ghcjs/shims

    Implementation of much of the runtime system and JavaScript dependencies. Code from this repository is linked into the lib.js and lib1.js files when generating a .jsexe. Installed by ghcjs-boot, the default installation location is ~/.ghcjs/version/ghcjs/shims.

    examples:

    • thread scheduler, MVar implementation ( src/thread.js )
    • STM implementation (src/stm.js)
    • IO system ( pkg/base.js ) (buffered IO for putStrLn etc)
    • Heap scanner for weak references and finalizers, finding deadlocks and heap profiling ( src/gc.js )
    • package-specific dependencies (pkg), dependencies listed in packagename.yaml (temporary measure until Cabal supports JavaScript dependencies directly)
    • third party libraries (lib)
  • https://github.com/ghcjs/ghcjs-prim

    GHCJS primitives used by the runtime system, some basic utilities for converting JS data (for packages that cannot depend on ghcjs-base) and Template Haskell communication code. This package is treated in a special way by the compiler, symbol names are not versioned, similar to wired-in packages.

  • https://github.com/ghcjs/ghcjs-base

    GHCJS base library, basic marshalling between JavaScript and Haskell data

If you've changed something that affects the code generated by GHCJS, you'll need to rebuild the base packages (reboot the compiler). Often, a full reboot is not required. You can run a quick boot to install only the essential packages (e.g. base, integer-gmp, array, but not ghcjs-base). Adjust the -j4 flag (number of concurrent jobs) for your system:

$ ghcjs-boot --dev --no-haddock --no-prof --quick -j4

After a change, please run the test suite to check that it does not break anything. Install jsshell and node.js first to make sure that the tests run correctly (js and node executables should be in your PATH)).

When the compiler has been booted, run cabal test, or run the test program directly for more options:

$ ./dist/build/test/test --help

For example to run a specific test or tests that match a pattern:

$ ./dist/build/test/test -t pattern

New test cases, in particular if you add new features, are always welcome. The testrunner automatically picks up new tests (.hs files that start with a lowercase letter) in the existing categories.

Fixing boot problems

If some change prevents your GHCJS from booting correctly, you can manually run boot steps to track down the problem.

First run ghcjs-boot with the -v2 or -v3 options to get more information about the problem. Then set some environment variables to make the compiler skip the check that it's been booted:

$ export GHCJS_BOOTING=1

Additionally, if you are fixing a problem in stage 1 (before GHCJS has a working Cabal package):

$ export GHCJS_BOOTING_STAGE1=1

Debugging GHCJS programs

TODO add better instructions here

  • link your program with -debug: ghcjs -debug -o test test.hs, this adds debugging information to the generated code
  • get more information from the runtime system by enabling various tracing and logging options. See the code in the shims repository for more info. Examples:
    • -DGHCJS_LOG_BUFFER: output log/trace messages to the h$logBuffer variable instead of the console. useful in the browser to avoid overloading the console.
    • -DGHCJS_TRACE_SCHEDULER: messages from the thread scheduler
    • -DGHCJS_TRACE_CALLS: print all function calls from the main loop. warning: lots of output. Requires -debug for name information
    • -DGHCJS_TRACE_STACK: print top of stack for every call in the main loop. warning: even more output
    • -DGHCJS_TRACE_WEAK: output related to weak references
    • -DGHCJS_TRACE_STM: output for software transactional memory
    • -DGHCJS_TRACE_GC: output garbage collector (heap scanner) related messages
    • -DGHCJS_TRACE_PROF: output profiling related messages
  • see the utility programs in utils in the ghcjs repository for tools for inspecting object files, quickly bisecting bugs in the optimizer etc.

Profiling GHCJS programs

You can use the JavaScript profiler to get a basic idea where the majority of time in your program is spent. Non-exported names (like stack frame functions) start with h$$, scroll up in the code to find an exported name to which they belong.

Unfortunately due to Haskell's lazy evaluation and GHCJS's tail-call optimization, the information here is far less useful than GHC profiles for native code. Work on full profiling support has started. Cost centre stacks have been implemented and stack traces work, but there is no front end yet.