#+TITLE: Contribution guideline Or, how to work on MoarVM. * Community MoarVM is a fairly small community. We communicate primarily on the #moarvm channel on libera.chat, and to a lesser extent via github issues. We use IRC bots to keep up to date with new commits that are published; but those don't always work well, unfortunately. The [[https://rakudoweekly.blog/][Rakudo Weekly News]] newsletter publishes progress in MoarVM, and there's also the =/r/rakulang= subreddit. * Code Standards Some things to keep in mind are: - We support Microsoft Windows, Apple macOS, Linux, and to the extent possible, other POSIX platforms such as the BSDs. (Because we are a small community, we don't always have a testing environment available). Patches to add support for other platforms are welcome. - MoarVM is written in C89 (for reasons of compatibility with the Microsoft VC++ compiler). The practical upshot is that declarations *must* be at the top of a function. - We use 4-spaces, no tabs for indentation. - Exported (non-static) functions should be 'namespaced' using the prefix =MVM_=, and should typically include the module name, e.g. =MVM_string_graphs=. =static= functions can be named whateever you like. Similarily, public structs should be prefixed with =MVM= as well. - Because MoarVM uses a generational garbage collector, code interacting with objects must take this into account: - An object may be moved by the garbage collector, so if any code takes a local pointer to an object, it must be treated as a GC root. This is effected by the =MVMROOT= macro (=src/gc/roots.h=) - An old object may reference a young one, and the nursery collector does not see this reference; hence a write barrier is required to ensure that this reference is counted. This is effected by the =MVM_ASSIGN_REF= macro (=src/gc/wb.h=). - We are not afraid of using macros. (But they are a dangerous powertool, so use with care). - Neither are we afraid of using dependencies when this makes sense. However, note that all dependencies must be fixed (we use =git submodules= for this purpose) and buildable from source. - Dependencies *must* be compatible with the MoarVM license (ARTISTIC-2.0). - Dependencies *must* be available on our supported platforms (at least Windows, macOS, Linux). * Building We use =make= for building, and =perl= for configuring the =Makefile=. MoarVM's =Makefile= should be highly parallelizable - the reader is adviced to take advantage of this. The author uses the following configuration: #+BEGIN_SRC sh export MAKEFLAGS="-j8" # 8 simultaneous jobs allowed #+END_SRC Nobody likes build-time dependencies, so please take that into account before adding any. * Testing MoarVM doesn't (currently) have a separate testing system, however it is exercised by the test suites for =nqp= and =rakudo=. - =make test= for nqp and rakudo should always pass. - rakudo =make spectest= should also pass, but ocassionally regresses, or contains tests that do not pass reliably Better testing: - configure MoarVM with the =--asan= option to catch memory corruption bugs. Note however, that because the runtime optimizer (=spesh=) runs in a separate thread, it may leak memory during a shutdown; this is normal. - If you see intermittent failures this may be related to runtime specialization, which runs on a separate thread (which introduces nondeterminism in when the code is optimized and hence run). The environment flag =MVM_SPESH_BLOCKING= synchronizes =spesh= so that this nondeterminism is removed. - The environment flags =MVM_SPESH_DISABLE=, =MVM_JIT_DISABLE= etc. can be used to determine if a bug is in the spesh/JIT subsystem. If it is, the script =tools/jit-bisect.pl= can be used to pinpoint where exactly. - run the test suite with the =MVM_SPESH_NODELAY= environment flag set; this will run the optimizer directly (without waiting for a routine to become active). * Debugging Pass the =--debug --optimize=0= flags to =Configure.pl= to get a build that is usable in a debugger. Note that the default wrapper scripts =nqp= and =raku= are *not* suitable for debugging because they =exec= just after starting. You can use the =raku-gdb-m= wrapper instead; or insert =gdb= or =lldb= into an explicit command line yourself. (The author of this document typically writes =gdb= scripts). *NB*: there are recently developed runner programs in C, which are equivalent to the old runner scripts, that don't have the same problem - you can start this as =raku-mc=. * Workflow Larger features are typically developed on separate branches. Such branches should be rebased to keep up to date with master. Bugfixes can go to master directly. * Miscellaneous Please all be nice to each other.