The Erlang BEAM Virtual Machine Specification


Bogumil Hausman
Computer Science Laboratory
Ericsson Telecom AB
Rev. 1.2
October 1997

Contents

1 Introduction
2 BEAM Virtual Machine
3 BEAM Virtual Machine Instruction Set

1 Introduction

The following document describes the Erlang BEAM instruction set used for the BEAM threaded-code emulation. To make it self contained the document starts with a short introduction to the BEAM Virtual Machine clarifying different notions used later in the text.

1.1 Historical Note

This document describes BEAM as it was in 1997. BEAM has grown and changed significantly between then and the time this note was added (2012). This information is mainly for historical interest.

2 BEAM Virtual Machine

2.1 Data Areas

The data areas are the code area, containing loaded compiled Erlang code, and a stack and heap. The stack contains call frames with local variables and return addresses. The heap contains terms created by the Erlang execution. The stack and the heap are allocated as one memory area and grow towards each other. Having the heap and the stack allocated together makes testing for memory overflow very efficient as we compare two pointers (top-of-heap pointer and top-of-stack pointer) residing in hardware registers.

Each call frame on the stack starts with a return-address pointer, CP, followed by local variables which are accessed by integer offset from a pointer to the top of the stack. Frames are allocated only after a clause guard is evaluated and if the clause body contains local variables and function calls. Frames are allocated and discarded by the A_op and D_op instructions with explicitly given frame size N. For garbage collection purposes the stack structure can be obtained by looking for stored return addresses. A call frame can contain as well catch resumption addresses (see the Catch instruction) and next-instruction pointers (see the C instruction).

The Erlang BEAM system allows mixing threaded code emulation with compiling into C. When an Erlang function compiled to C is called, the next instruction pointer, I, is stored in the current local frame and the CP pointer is set to the emulator code which would restore the I pointer upon return from the called function.

2.2 Data Objects

An Erlang term is represented by a 32-bit unsigned word containing a value and a tag. The tag (4-bit) resides in the least significant bits and distinguishes the type of the term.

The value part of an atom is an index into a global atom table where the atom is represented. The value part of a small integer is the integer itself. The value part of a big number integer is a pointer to a heap object containing the integer sign and number of words building the integer value. The value part of a list is a pointer to two consecutive heap locations with two tagged objects (the head and tail of the list). The value part of a tuple is a pointer to a heap object containing tuple size followed by the tuple elements. The value part of a float is a pointer to a heap object containing a two-word float value. The value part of a process identifier is the process identifier itself.

The current BEAM implementation uses the following tags:

#define SMALL          15              /* small integer       */
#define BIG            11              /* big integer pointer */
#define FLOAT           9              /* float pointer       */
#define ATOM            7              /* atom                */
#define REFER           6              /* reference           */
#define PORT            5              /* port                */
#define PID             3              /* process identifier  */
#define TUPLE           2              /* tuple pointer       */
#define NIL            (BIG + 16)      /* empty list          */
#define LIST            1              /* list pointer        */
#define ARITYVAL       10              /* tuple arity         */
#define MOVED          12              /* moved heap pointer  */
#define CATCH          THING           /* resumption address  */
#define THING          13              /* float value         */
#define BINARY         14              /* binary pointer      */
#define BLANK          ARITYVAL        /* blank local var     */
#define IC             SMALL           /* next instr. pointer */

#define CP0             0              /* CP pointer          */
#define CP4             4              /* CP pointer          */
#define CP8             8              /* CP pointer          */
#define CP12           12              /* CP pointer          */
Since some data objects can reside only on heap or stack the same tag can be used for two different objects (CATCH and THING, BLANK and ARITYVAL). There are some other cases when the same tag can be reused. Since objects representing the big-number integers are tagged heap pointers, the BIG flag can be used as well to represent an empty list, NIL (since the NIL value part becomes a non valid heap pointer).

The CP tags are reserved for the return-address pointer, CP. The pointer does not have to be tagged if on the current platform the pointer has always the two last bits set to 0.

2.3 Registers

The BEAM Virtual Machine uses the following registers:
  • HTOP - top-of-heap pointer
  • E - top-of-stack pointer
  • CP - return-address pointer (where to go when a function is ready executed)
  • I - next-instruction pointer
  • x(N) - argument registers (to pass function parameters), x(N) are also used to hold temporal variables
  • y(N) - local variables (y(N) are not real registers, they reside in a local frame and are accessed by integer offset from a top-of-stack pointer)
  • fcalls - number of reductions done (to check for suspension while doing function call)
  • 2.4 Function Calls

    To call an Erlang function we pass parameters by loading argument registers, x(N), and update the return-address register, CP. On function return the return value is stored in x(0).

    2.5 Concurrency

    Erlang processes are dynamically spawned and killed during the execution. Each process has its own heap and stack area. For concurrency purposes the Erlang BEAM provides suspension and scheduling mechanisms. A suspending process stores its current state in its suspension record and is added to a scheduler queue. To guarantee a fair scheduling a process is suspended after a fixed number of reductions and then the first process from the queue is resumed.

    To receive messages each process has its own local message queue. Sending a message results in copying the message into the receiver heap and storing the message reference in the receiver message queue. While waiting for messages to be received a process is swapped out, and is added to the scheduler queue only when a new message is received (i.e. the addition is done by a process sending the message), or a time-out occurs.

    3 BEAM Virtual Machine Instruction Set

    The following chapter describes the Erlang BEAM instruction set used for the threaded-code emulation.

    3.1 The Instructions Format

    Byte-code Syntax (produced by the BEAM compiler and saved in module_name.beam file):
     
    opcode value
    operand1
    operand2
    ...

    Opcode values less than 255 are coded as one byte, opcode values larger than 255 are coded as two bytes (255 and the rest). Module, function, atom names and floating point numbers are coded as a list of ASCII values preceded by the length of the list.

    It means that operands in the byte-code syntax diagram can have different size due to their type:

    8-bit long

    16-bit long

    24-bit long

    32-bit long

    other operands are 16-bit long.

    Threaded-code Syntax (produced by the BEAM loader while loading the compiled byte code):
     
    label address
    operand1
    operand2
    ...

    The label address (four bytes) is an address of the corresponding emulator code. After loading, atoms and small integers are ready created (index in atom table + TAG, integer value + TAG). After loading all operands are four-bytes long (one 32-bit word). When an operand is NIL or a temporal variable x(0), only one word is used. When an operand is a temporal variable x(N) or a local variable y(N) the first word indicates type of the variable (X_arg or Y_arg) and the second its index N. For efficiency purposes in many instructions types of operands are implicitly coded as the instructions opcodes. Each line in the threaded-code syntax diagram represents a 32-bit word.

    When a threaded-code syntax corresponds to a byte-code syntax (only instruction opcode is changed to a label address and operands are build, &FuncBegin is added, or instruction offset is changed to instruction address for branch purposes), only the threaded-code syntax is given.

    3.2 Format Instructions

    IntCode

    Provide some information to the threaded-code loader.

    Byte-code Syntax:
     
    IntCode_op
    code size
    module name
    magic number

    Threaded-code Syntax: none (the instruction is removed by loader)

    code size is a total size (in 32-bit words)of the compiled module code after loading

    module name is an atom name corresponding to the name of the module

    magic number is used to prevent loading of old format code (is checked against the loader magic number while loading)

    3.3 Procedural Instructions

    FuncBegin

    Generate the BADMATCH error (there is a bad match in an Erlang clause/case/if/receive body).

    Byte-code Syntax:
     
    FuncBegin_op
    function name
    function arity

    Threaded-code Syntax:
     
    lb_FuncBegin
    module_name
    function_name
    function_arity

    module_name, function_name are ready created atoms.

    Generate the current context information (the current module, function and arity), set the BADMATCH error, branch to error handling procedure.

    The FuncBegin instruction starts each compiled Erlang function. To save space the context information provided is reused by other instructions. When an Erlang function is called the first instruction after FuncBegin is executed.

    C/CO/ResC

    C: Call a local Erlang function. A local function is the one which reside in the same module as the function caller.

    CO: Call a local Erlang function. The continuation program pointer (CP register) is already set.

    ResC: Call a resident Erlang function. A resident Erlang function is a local function which cannot be called from and return to other modules. The instruction is used to optimize control handling when a threaded-code Erlang function cannot be mixed with other Erlang functions compiled into C code.

    Byte-code Syntax:
     
    C/CO/ResC_op
    function name
    function arity

    Threaded-code Syntax:
     
    lb_C/CO/ResC
    &function
    function_arity
    &FuncBegin

    &function is an address of the first instruction corresponding to the called function (more precisely the first instruction after corresponding FuncBegin).

    function_arity is a number of function arguments.

    &FuncBegin is an address of the current function FuncBegin instruction.

    C: Store pointer to the next instruction in the current stack frame. Set the continuation program pointer at the emulator code restoring the next instruction pointer, increment number of reductions and check for suspension (if suspending, generate the current module, function and arity information using &FuncBegin), branch to called function.

    CO: As above but the continuation program pointer is already set in the CP register (the instruction is used when the last function in the body is called and there is no stack frame to be discarded).

    ResC: Set the continuation program pointer at the next instruction, increment number of reductions and check for suspension (if suspending, generate the current module, function and arity information using &FuncBegin), branch to called function.

    CL

    Discard the current stack frame. Call a local Erlang function.

    Byte-code Syntax:
     
    CL_op
    function name
    function arity
    frame size

    Threaded-code Syntax:
     
    lb_CL
    &function
    function_arity
    frame_size
    &FuncBegin

    frame_size is a size of the current stack frame to be discarded.

    For info on other operands see C/CO.

    Copy the continuation program pointer from the current stack frame into CP, discard the frame, increment number of reductions and check for suspension, branch to called function.

    TrC/TrCO

    TrC: A traced version of the C instruction.

    TrCO: A traced version of the CO instruction.

    Byte-code Syntax:
     
    TrC/TrCO_op
    function name
    function arity

    Threaded-code Syntax:
     
    lb_TrC/TrCO
    &function
    function_arity
    &FuncBegin
    function_name

    function_name is an atom corresponding to the called function name; used to generate some information for tracing purposes.

    For info on other operands see C/CO.

    The same semantics as C/CO but some trace information (the called function module, name, arity) is sent to a tracing Erlang process.

    TrCL

    TrCL is a traced version of the CL instruction.

    Byte-code Syntax:
     
    TrCL_op
    function name
    function arity
    frame size

    Threaded-code Syntax:
     
    lb_TrCL
    &function
    function_arity
    frame_size
    &FuncBegin
    function_name

    function_name is an atom corresponding to the called function name; used to generate some information for tracing purposes.

    For info on other operands see TrCL.

    The same semantics as CL but some trace information (the called function module, name, arity) is sent to a tracing Erlang process.

    CEx/TrCEx

    Call an external Erlang function. TrCEx is a traced version of the CEx instruction.

    Byte-code Syntax:
     
    CEx/TrCEx_op
    module name
    function name
    function arity

    Threaded-code Syntax:
     
    lb_CEx/TrCEx
    module_name
    function_name
    function_arity
    &FuncBegin

    module_name, function_name, function_arity define the external function to be called.

    &FuncBegin is an address of the current function FuncBegin instruction.

    CEx: Set the continuation program pointer at the next instruction, increment number of reductions and check for suspension (if suspending, generate the current module, function and arity information using &FuncBegin), check if the called function is loaded, if yes branch to the called function (the address is taken from the export-function table), if not call an error handler.

    TrCEx: The same semantics as CEx but some trace information (the called function: module, name, arity) is sent to a tracing Erlang process.

    CExL/TrCExL

    Discard the current stack frame. Call an external Erlang function. TrCExL is a traced version of the CExL instruction.

    Byte-code Syntax:
     
    CExL/TrCExL_op
    module name
    function name
    function arity
    frame size

    Threaded-code Syntax:
     
    lb_CExL/TrCExL
    module_name
    function_name
    function_arity
    &FuncBegin
    frame_size

    frame_size is a size of the current stack frame to be discarded.

    For info on other operands see CEx/TrCEx.

    CExL: Copy the continuation program pointer from the current stack frame into CP, discard the frame, increment number of reductions and check for suspension, check if the called external function is loaded, branch to the function.

    TrCExL: The same semantics as CExL but some trace information (the called function: module, name, arity) is sent to a tracing Erlang process.

    R/ResR

    R: Return from an Erlang function call.

    ResR: Return from a resident Erlang function call.

    Threaded-code Syntax:
     
    lb_R/ResR

    R: Restore the next instruction pointer from the current stack frame. Return control to the function caller.

    ResR: Go to instruction which address is stored in the CP register.

    TrR

    A traced return from an Erlang function call.

    Threaded-code Syntax:
     
    lb_TrR
    &FuncBegin

    The same semantics as R but some trace information (the function we return to: module, name, arity) is sent to a tracing Erlang process.

    ERR_ACT

    Generate the FUNCTION_CLAUSE error (there are no Erlang clauses matching a given function call).

    Threaded-code Syntax:
     
    lb_ERR_ACT
    &FuncBegin

    Generate the current context information using the &FuncBegin pointer, set the FUNCTION_CLAUSE error, branch to error handling procedure.

    A

    Allocate a new stack frame.

    Threaded-code Syntax:
     
    lb_A
    frame_size
    n

    n is a number of live temporal variables x(0), ..., x(n-1) (for garbage collection purposes).

    Check for required stack space, call garbage collection if necessary. Allocate a new stack frame (of frame_size). Update the stack-top pointer E. Copy the continuation program pointer CP into the new frame.

    I

    Initialize a local variable (located in the current stack frame).

    Threaded-code Syntax:
     
    lb_I
    n

    n is an index of a local variable y(n) which must be explicitly initialized.

    Initialize a local variable y(n).

    D

    Discard the current stack frame.

    Threaded-code Syntax:
     
    lb_D
    frame_size

    Copy the continuation program pointer from the current stack frame into CP, discard the frame. Update the stack-top pointer E.

    TH

    Check for required heap space.

    Threaded-code Syntax:
     
    lb_TH
    m
    n

    m is a size of required heap space (in words).

    n is a number of live temporal variables x(0), ..., x(n-1) (for garbage collection purposes).

    Check for required heap space, call garbage collection if necessary.

    3.4 Put Instructions

    The put instructions are used to build new Erlang data objects. All objects are build on an Erlang process heap. In all cases the heap space requirements have been already checked.

    PL

    Having head and tail build a new list.

    Threaded-code Syntax:
     
    lb_PL
    type
    head
    type
    tail
    type
    list

    type indicates sort of the following operand: X_arg - a temporal variable, Y_arg - a local variable, C_arg - a constant (atom, NIL, or a small integer). Depending on its type, an operand can be an index (for X_arg and Y_arg) or ready created Erlang data object (for C_arg).

    Having head and tail build a new list. Set list to the new created data object. Update the heap-top pointer, HTOP.

    PL_<type>

    Having head and tail build a new list. PL_<type> is a specialized version of the PL instruction.

    Threaded-code Syntax:
     
    lb_PL_<type>
    list
    head
    tail

    PL_<type> has the same semantics as the PL instruction. The only difference is that types of all operands are coded implicitly as instruction opcode. For example PL_xyx means that the first and the third operands are temporal variables while the second operand is a local variable. The decision which types are coded as specialized instructions has been based on their frequency in existing large industrial applications.

    PS

    Having a given string convert it to a corresponding list. Build the list.

    Threaded-code Syntax:
     
    lb_PS
    string_length
    string_elements0
    ...
    string_elementsN
    type
    list

    string_length is the length of the included string (number of string elements).

    string_elements<i> is a 32-bit word consisting of four string elements (each 8-bit long). Depending on string_length the last string_elements<i> can be shorter.

    type indicates sort of the following operand.

    Having a string of a given length, build a new list consisting of the string elements. Set list to the new created data object. Update the heap-top pointer, HTOP.

    PInt_<type>

    The PInt_<type> instruction followed by a number of PIntVal instructions is used to build a big number integer.

    Threaded-code Syntax:
     
    lb_PInt_<type>
    pointer
    arity
    sign

    pointer is a pointer to the being created big number integer.

    arity gives a number of following words with the big number value.

    sign is the big number sign.

    Create an initial l structure for a big number integer. The instruction is followed by an arity number of PIntVal instructions. Set pointer to the new created data object. Update the heap-top pointer. The type of pointer is implicitly coded as instruction opcode.

    PIntVal

    Build a big number value.

    Threaded-code Syntax:
     
    lb_PIntVal
    value

    value is a word being part of a big number integer value.

    Put a value word on a process heap. The instruction must be preceded by the PInt_<type> instruction or other PIntVal instructions. Update the heap-top pointer.

    PFlt_<type>

    Build a double floating point number.

    Threaded-code Syntax:
     
    lb_PFlt_<type>
    pointer
    value0
    value1

    value0 and value1 build the double float value.

    Put value0 and value1 on a process heap. Set pointer to the new created data object. Update the heap-top pointer. The type of pointer is implicitly coded as instruction opcode.

    PT0_<type>

    The PT0_<type> instruction followed by a number of PTEl_<type> instructions build a tuple.

    Threaded-code Syntax:
     
    lb_PT0_<type>
    tuple
    arity

    tuple is a pointer to the being created tuple data object.

    arity gives a number of following tuple elements.

    Create an initial structure for a tuple data object. The instruction is followed by an arity number of PTEl_<type> instructions. Set the tuple pointer to the new created object. Update the heap-top pointer. The type of tuple is implicitly coded as instruction opcode.

    PTEl_<type>

    Build a tuple element.

    Threaded-code Syntax:
     
    lb_PTEl_<type>
    element

    element is a tuple element to be put on heap.

    Put a tuple element on a process heap. The instruction must be preceded by the PT0_<type> instruction or other PTEl_<type> instructions. Update the heap-top pointer. The type of element is implicitly coded as instruction opcode.

    3.5 Get Instructions

    The get instructions are used to match against Erlang function arguments, function return values, and Erlang variables. The type of object matched has been already checked.

    GL2_<type>

    Having a given list get its head and tail.

    Threaded-code Syntax:
     
    lb_GL2_<type>
    list
    head
    tail

    list is a pointer to existing list.

    head and tail are pointers to respectively head and tail.

    Having a given list set the head pointer to its head and tail to its tail. Types of all operands are coded implicitly as instruction opcode.

    GTp_<type>

    Having a given tuple check its arity. The instruction is followed by a number of the GTEl instructions.

    Threaded-code Syntax:
     
    lb_GTp_<type>
    &FuncBegin
    tuple
    arity

    &FuncBegin is an address of the current function FuncBegin instruction.

    tuple is a pointer to existing tuple.

    arity is the required arity.

    The instruction occurs only in a clause/case/if/receive body. Having a given tuple check its arity. If not equal the required one (arity), generate the current context information (using &FuncBegin), set the BADMATCH error, and branch to error handling procedure. Type of tuple is coded implicitly as instruction opcode.

    GTp_head_<type>

    Having a given tuple check its arity. GTp_head_<type> is a specialized version of the GTp_<type> instruction.

    Threaded-code Syntax:
     
    lb_GTp_head_<type>
    address
    tuple
    arity

    address is a branch address in a case of failure.

    tuple is a pointer to existing tuple.

    arity is the required arity.

    The instruction occurs only in a clause/case/if/receive head. Having a given tuple check its arity. If not equal the required one, branch to the next clause/option using address. Type of tuple is coded implicitly as instruction opcode.

    GTEl_<type>

    Having a given tuple get its element.

    Threaded-code Syntax:
     
    lb_GTEl_<type>
    tuple
    element
    index

    tuple is a pointer to existing tuple.

    element is a tuple element with required index.

    Get a tuple element with required index. The instruction must be preceded by the GTp_<type> or GTp_head_<type> instruction. Types of tuple and element are coded implicitly as instruction opcode.

    3.6 Test Instructions

    The test instructions are used to test types of Erlang data objects.

    <Test0>_<type>

    Check if a given Erlang data object has required data type. The instruction usually precedes other get instructions

    <Test0> succeeds if a data object is:

  • TNil - an empty list
  • TT - a tuple
  • TNonEmpL - a non-empty list

  •  

     

    Threaded-code Syntax:
     
    lb_<Test0>_<type>
    &FuncBegin
    object

    &FuncBegin is an address of the current function FuncBegin instruction.

    object is an existing Erlang data object.

    The instruction occurs only in a clause/case/if/receive body. Having a given data object check its type. In a case of failure, generate the current context information (using &FuncBegin), set the BADMATCH error, and branch to error handling procedure. Type of object (X_arg, Y_arg, C_arg) is coded implicitly as instruction opcode.

    <Test1>_head_<type>

    Check if a given Erlang data object has required data type. <Test1>_head_<type> is a specialized version of the <Test0>_<type> instruction.

    <Test1> succeeds if a data object is:

  • TNil - an empty list
  • TT - a tuple
  • TNonEmpL - a non-empty list

  •  

     

    Threaded-code Syntax:
     
    lb_<Test1>_head_<type>
    address
    object

    address is a branch address in a case of failure.

    object is an existing Erlang data object.

    The instruction occurs only in a clause/case/if/receive head. Having a given data object check its type. In a case of failure, branch to next clause/option using address. Type of object (X_arg, Y_arg, C_arg) is coded implicitly as instruction opcode.

    <Test2>_<type>

    Check if a given Erlang data object has required data type. The instruction occurs only in guards.

    <Test2> succeeds if a data object is:

  • TInt - an integer
  • TFlt - a float
  • TCnst - a constant (not a list or tuple)
  • TL - a list
  • TPrId - a process identifier
  • TRef - a reference
  • TPrt - a port
  • TBn - a binary

  •  

     

    Threaded-code Syntax:
     
    lb_<Test2>_<type>
    address
    object

    address is a branch address in a case of failure.

    object is an existing Erlang data object.

    The instruction occurs only in a clause/case/if/receive guard. Having a given data object check its type. In a case of failure, branch to next clause/option using address. Type of object (X_arg, Y_arg, C_arg) is coded implicitly as instruction opcode.

    3.7 Move Instructions

    M_<type>

    Move an internal data object to a given temporal or local variable.

    Threaded-code Syntax:
     
    lb_M_<type>
    object
    register

    object is an internal data object.

    register is a temporal or local variable.

    Move an internal data object (can be of type X_arg, Y_arg, C_arg) to a temporal or local variable (X_arg or Y_arg). Types of operands are coded implicitly as instruction opcode.

    3.8 Exception Handling

    Throw

    Throw an exception or error.

    Threaded-code Syntax:
     
    lb_Throw
    &FuncBegin
    type
    object

    object is an internal data object.

    Throw an internal data object (can be of type X_arg, Y_arg, C_arg). When a Throw is executed the stack is searched for a saved resumption address (set by Catch), the top-of-stack pointer is reset to point at the found call frame and the execution continues there. If there is no resumption address on the stack (a process catch counter is zero), the current context information is generated (using the &FuncBegin pointer), the THROWN error is set, and the control is transfered to error handling procedure.

    Catch

    Catch an exception or error.

    Threaded-code Syntax:
     
    lb_Catch
    index
    &CatchEnd

    index is a place in the local frame when a resumption address &CatchEnd is saved.

    &CatchEnd is a catch resumption address.

    Save a resumption address &CatchEnd in the local frame at position with index offset. Increment a process catch counter. The instruction is followed by a CatchEnd instruction. By followed we mean that the CatchEnd instruction is put after corresponding Erlang Expression the catch protects from errors.

    CatchEnd

    Clear a resumption address set by Catch.

    Threaded-code Syntax:
     
    lb_CatchEnd
    index

    index is a place in the local frame when a resumption address &CatchEnd was saved.

    Clear a resumption address stored in the local frame at position with index offset. Decrement a process catch counter. The instruction is preceded by a matching Catch instruction (see Catch for further details).

    3.9 Inter-process Communication

    Send

    Send a given message to a given address.

    Threaded-code Syntax:
     
    lb_Send
    &FuncBegin
    type
    address
    type
    message

    type indicates sort of the following operand (X_arg, Y_arg, C_arg).

    address is the address of the message being sent (can be an Erlang process or port).

    message is an internal data object containing the message.

    Having a given message send it to a given address. If the address is not valid, call an Erlang error handler. If while sending to a remote node the corresponding communication channel is busy, suspend for a certain period of time and try later. When suspending, generate the current context information using &FuncBegin.

    Receive

    The receive Erlang primitive is compiled into a sequence of instructions implementing the required receive semantics:
        rec:  Rec (set a message pointer)
       loop:  loopRec (fetch the message)
    pattern:  match the message against required pattern
              if matched then
                   RmMsg (remove the message from the mailbox,
                           mark all other messages as untried,
                           if the timeout has been set then
                              clear the timeout)
                   evaluate given action
                   TPattEnd (goto next instruction after receive)
              else
                   if there are more patterns to be matched then
                        goto pattern (try the next pattern)
                   else
                        loopRecEnd (mark the current message as tried,
                                    if there are more messages then
                                       update message pointer,
                                       goto loop (try the next message))
                        WaitTOut (if there is given timeout and 
                                   the timeout is not set
                                     set the required timeout and suspend)
                        Wait (suspend)
    If there are no matching messages the process suspends until a new message is received or a timeout occurs, then the process is rescheduled for execution.
              if a new message is received then
                   goto rec (set a message pointer)
              else if a timeout occurs then
                   goto timeout (evaluate given timeout action)
              else
                   remain suspended
    timeout:  TimeOut (mark all messages as untried)
              evaluate given timeout action
              TPattEnd (goto next instruction after receive)
    Depending on the context set a message pointer can mean set the pointer to the first message in the mailbox (when the receive primitive is entered for the first time), or set the pointer to the first new received, untried, message (when a new message is received and the suspended process is rescheduled for execution).

    Rec

    Set a message pointer.

    Threaded-code Syntax:
     
    lb_Rec

    The Rec instruction is executed when an Erlang process enters the receive primitive for the first time (the message pointer is set to the first message in the mailbox) or the suspended process is rescheduled for execution (the pointer is set to the first new received, untried, message).

    loopRec

    Fetch a new message.

    Threaded-code Syntax:
     
    lb_loopRec
    &wait
    index

    &wait is a branch address in a case of no more messages to be matched.

    index is a place in the local frame where a being matched message is saved.

    Check the message pointer, if NIL (no more messages) branch to the Wait or WaitTOut instruction for suspension. Otherwise save the message in the local variable, y(index), before matching. The instruction is followed by other instructions for the required matching, and a loopRecEnd instruction. The loopRecEnd instruction is put after all instructions doing the required pattern matching.

    loopRecEnd

    Update message pointer.

    Threaded-code Syntax:
     
    lb_loopRecEnd
    &loopRec

    &loopRec is an address of the corresponding loopRec instruction.

    Update the message pointer, branch to the corresponding loopRec instruction (try the next message). The instruction is preceded by a matching loopRec instruction (see loopRec for further details).

    Wait

    Suspend the current Erlang process.

    Threaded-code Syntax:
     
    lb_Wait
    &rec
    &FuncBegin

    &rec is an address of the corresponding Rec instruction.

    There are no matching messages in the mailbox and the current Erlang process is suspended. When the process is rescheduled later for execution the next-instruction pointer is set to the &rec address. When suspending, generate the current context information using &FuncBegin.

    WaitTOut

    Suspend the current Erlang process. Set the required timeout.

    Threaded-code Syntax:
     
    lb_WaitTOut
    &rec
    &FuncBegin
    type
    time

    &rec is an address of the corresponding Rec instruction.

    type indicates sort of the following operand (X_arg, Y_arg, C_arg).

    time contains the required timeout value.

    The same semantics as Wait with the difference that the required timeout is set first. The timeout is set only once when the receive primitive is entered for the first time. The instruction is part of receive augmented with a timeout.

    RmMsg

    Remove a message from a mailbox.

    Threaded-code Syntax:
     
    lb_RmMsg

    Remove a matched message from a process mailbox. The RmMsg instruction is executed when a fetched message is successfully matched and a corresponding action is going to be evaluated. All other messages are marked as untried. The instruction clears the previously set timeout (if any).

    TimeOut

    Mark all mailbox messages as untried.

    Threaded-code Syntax:
     
    lb_TimeOut

    Mark all messages in the current mailbox as untried. The TimeOut instruction is executed when a timeout occurs and the messages must be marked as untried for future receives.

    TPattEnd

    Branch to a given instruction address.

    Threaded-code Syntax:
     
    lb_TPattEnd
    &instruction

    &instruction is an instruction address.

    Set the next-instruction pointer to &instruction and branch to it. The TPattEnd instruction is used to transfer control when one of the alternatives in receive/case/if primitive is ready evaluated. &instruction points to the first instruction after the primitive.

    3.10 Primitives

    The only new instructions needed to implement the case and if semantics are: TPattEnd (covered earlier in the context of receive), CaseEnd and IfEnd.

    CaseEnd

    Generate the CASE_CLAUSE error (there are no matching case patterns).

    Threaded-code Syntax:
     
    lb_CaseEnd
    &FuncBegin
    type
    object

    type indicates sort of the following operand (X_arg, Y_arg, C_arg).

    object is an internal data object being matched.

    The instruction is executed when there are no matching case patterns. Generate the current context information using &FuncBegin, set the CASE_CLAUSE error, generate information about the object being matched, branch to error handling procedure.

    IfEnd

    Generate the IF_CLAUSE error (there are no succeeding if guards).

    Threaded-code Syntax:
     
    lb_IfEnd
    &FuncBegin

    The instruction is executed when there are no succeeding if guards. Generate the current context information using &FuncBegin, set the IF_CLAUSE error, branch to error handling procedure.

    3.11 Built-in Functions

    Bult-in functions are compiled into different instructions depending on the function arity. For efficiency reasons some built-in functions are coded explicitly. There are some other Erlang expressions which are treated as built-in functions (e.g. mixed arithmetic, integer arithmetic).

    Bif_0_<type>

    Call a built-in function of arity 0 (the function cannot fail).

    Threaded-code Syntax:
     
    lb_Bif_0_<type>
    bif
    ret

    bif is a bif-table index.

    ret is an internal data object.

    Given a bif-table index, bif, execute a corresponding build-in function. Put the result in the ret object. Type of the object (X_arg or Y_arg) is coded implicitly as instruction opcode.

    Bif_1_<type>

    Call a built-in function of arity 1 (the function can fail).

    Threaded-code Syntax:
     
    lb_Bif_1_<type>
    address
    bif
    arg
    ret

    bif is a bif-table index.

    address is a branch address in a case of failure.

    arg and ret are internal data objects.

    Given a bif-table index, bif, and argument, arg, execute a corresponding build-in function. Put the result in the ret object. In a case of failure, if the built-in function occurs in a guard, branch to the next clause/option using address. If the function occurs in a body (address points to the corresponding FuncBegin), the current context information is generated and the error handling procedure is called. The error information is set by the failing build-in function. Types of arg and ret are coded implicitly as instruction opcode.

    Bif_2

    Call a built-in function of arity 2 (the function can fail).

    Threaded-code Syntax:
     
    lb_Bif_2
    address
    bif
    type
    arg0
    type
    arg1
    type
    ret

    bif is a bif-table index.

    address is a branch address in a case of failure.

    type indicates sort of the following operand.

    arg0, arg1, and ret are internal data objects.

    The same semantics as Bif_1_<type> with the difference that the built-in function is called with two arguments and types of all operands are explicitly given.

    Bif_3

    Call a built-in function of arity 3 (the function can fail). The function can occur both in a clause/case/if/receive head (mixed arithmetic, integer arithmetic) or body.

    Threaded-code Syntax:
     
    lb_Bif_3
    address
    bif
    type
    arg0
    type
    arg1
    type
    arg2
    type
    ret

    bif is a bif-table index.

    address is a branch address in a case of failure.

    type indicates sort of the following operand.

    arg0, arg1, arg2 and ret are internal data objects.

    Given a bif-table index, bif, and arguments: arg0, arg1, and arg2 execute a corresponding build-in function. Put the result in the ret object. In a case of failure, if the built-in function occurs in a guard, branch to the next clause/option using address. If the function occurs in a body (address points to the corresponding FuncBegin), the current context information is generated and the error handling procedure is called. The error information is set by the failing build-in function.

    Appl3

    Call an apply/3 built-in function (the function can fail). The function can occur only in a clause/case/if/receive body.

    Threaded-code Syntax:
     
    lb_Appl3
    &FuncBegin
    type
    module
    type
    func
    type
    arg_list

    &FuncBegin is an address of the current function FuncBegin instruction.

    type indicates sort of the following operand.

    module, func, and arg_list are internal data objects.

    Call apply(module,func,arg_list). Put the result in x(0). In a case of failure, generate the current context information and branch to error handling procedure. The error information is set by the failing build-in function.

    Hd/Tl

    Call a hd/1 or tl/1 built-in function (the function can fail).

    Threaded-code Syntax:
     
    lb_Hd/Tl
    address
    type
    list
    type
    hd/tl

    address is a branch address in a case of failure.

    type indicates sort of the following operand.

    list and hd/tl are internal data objects.

    Given a list, list, extract its head/tail. Put the result in the hd/tl object. In a case of failure, if the built-in function occurs in a guard, branch to the next clause/option using address. If the function occurs in a body (address points to the corresponding FuncBegin), the current context information is generated and the error handling procedure is called. The error information is set by the failing build-in function.

    <Bif0>

    Call a given built-in function (the function cannot fail).

    <Bif0> can be the following:

  • CurrentNode - node/0
  • Self - self/0
  • MakeRef - make_ref/0
  • Gleader - group_leader/0
  • GrbCollect - garbage_collect/0
  • ErAll - erase/0

  •  

     

    Threaded-code Syntax:
     
    lb_<Bif0>
    type
    ret

    type indicates sort of the following operand.

    ret is an internal data object.

    Call a given built-in function. Put the result in the ret object.

    CheckPrCode/ExitPid

    Call a check_process_code/2 or exit/2 built-in function (the function can fail). The function can occur only in a clause/case/if/receive body.

    Threaded-code Syntax:
     
    lb_CheckPrCode/ExitPid
    &FuncBegin
    type
    arg0
    type
    arg1
    type
    ret

    &FuncBegin is an address of the current function FuncBegin instruction.

    type indicates sort of the following operand.

    arg0, arg1, and ret are internal data objects.

    Call check_process_code(arg0,arg1) or exit(arg0,arg1). Put the result in ret. In a case of failure, generate the current context information and branch to error handling procedure. The error information is set by the failing build-in function.

    Exit

    Call an exit/1 built-in function.

    Threaded-code Syntax:
     
    lb_Exit
    &FuncBegin
    type
    arg0

    &FuncBegin is an address of the current function FuncBegin instruction.

    type indicates sort of the following operand.

    arg0 is an internal data object.

    Call exit(arg0). &FuncBegin is used to generate required context information.

    GrbCollect

    Call a garbage_collect/1 built-in function (the function can fail). The function can occur only in a clause/case/if/receive body.

    Threaded-code Syntax:
     
    lb_GrbCollect
    &FuncBegin
    type
    arg0
    type
    ret

    &FuncBegin is an address of the current function FuncBegin instruction.

    type indicates sort of the following operand.

    arg0 and ret are internal data objects.

    Call garbage_collect(arg0). Put the result in ret. In a case of failure, generate the current context information and branch to error handling procedure. The error information is set by the failing build-in function.

    Halt

    Call a halt/0 built-in function.

    Threaded-code Syntax:
     
    lb_Halt

    Call halt().

    3.12 Arithmetic Expressions

    Arithmetic expressions are compiled into general purpose C-function calls doing the required arithmetic, and are treated as calls to built-in functions covered already in the context of Built-in Functions. For efficiency reasons (when the compile-time type analysis generates more information about given arguments) some arithmetic expressions are coded explicitly.

    FlArth

    Evaluate a given arithmetic expression, arguments are floating point numbers.

    Threaded-code Syntax:
     
    lb_FlArth
    address
    op
    type
    arg0
    type
    arg1
    type
    ret

    address is a branch address in a case of failure.

    op is a given operator (+, -, *).

    type indicates sort of the following operand.

    arg0, arg1, and ret are internal data objects.

    Having an operator, op, and its arguments arg0 and arg1 evaluate the required floating point arithmetic. Put the result in ret. In a case of failure, if the arithmetic expression occurs in a guard, branch to the next clause/option using address. If the expression occurs in a body (address points to the corresponding FuncBegin), the current context information is generated, the BADARITH error is set and the error handling procedure is called.

    FlArthDiv

    Evaluate a floating point division, arguments are floating point numbers.

    Threaded-code Syntax:
     
    lb_FlArthDiv
    address
    type
    arg0
    type
    arg1
    type
    ret

    address is a branch address in a case of failure.

    type indicates sort of the following operand.

    arg0, arg1, and ret are internal data objects.

    Having two floating point arguments, arg0 and arg1, evaluate a floating point division. Put the result in ret. In a case of failure, if the arithmetic expression occurs in a guard, branch to the next clause/option using address. If the expression occurs in a body (address points to the corresponding FuncBegin), the current context information is generated, the BADARITH error is set and the error handling procedure is called.

    IntArth

    Evaluate a given arithmetic expression, arguments are integers (cannot fail).

    Threaded-code Syntax:
     
    lb_IntArth
    op
    type
    arg0
    type
    arg1
    type
    ret

    op is a given operator (+, -, *).

    type indicates sort of the following operand.

    arg0, arg1, and ret are internal data objects.

    Having an operator, op, and its integer arguments arg0 and arg1 evaluate the required arithmetic. Put the result in ret.

    IntArth_<op>_<type>

    Evaluate a given arithmetic expression, arguments are integers. IntArth_<op>_<type> is a specialized version of the IntArth instruction.

    Threaded-code Syntax:
     
    lb_IntArth_<op>_<type>
    arg0
    arg1
    ret

    arg0, arg1, and ret are internal data objects.

    Having an operator and its integer arguments arg0 and arg1 evaluate the required arithmetic. Put the result in ret. The operator and types of operands are coded implicitly as instruction opcode.

    Plus/Minus_<type>

    Evaluate a given arithmetic expression, the second argument is a small integer.

    Threaded-code Syntax:
     
    lb_Plus/Minus_<type>
    address
    arg0
    arg1
    ret

    address is a branch address in a case of failure.

    arg1 is a small integer.

    arg0, and ret are internal data objects.

    Having an operator and its arguments (the second argument is a small integer) check if the result is a small integer (by checking the first argument). If not, call a general purpose C-function doing the arithmetic. If yes, evaluate the arithmetic expression directly in the emulator. Put the result in ret. In a case of failure, if the arithmetic expression occurs in a guard, branch to the next clause/option using address. If the expression occurs in a body (address points to the corresponding FuncBegin), the current context information is generated, the BADARITH error is set and the error handling procedure is called. Types of arg0 and ret are coded implicitly as instruction opcode.

    ArthBnot

    Evaluate a bitwise not arithmetic.

    Threaded-code Syntax:
     
    lb_ArthBnot
    address
    type
    arg0
    type
    ret

    address is a branch address in a case of failure.

    type indicates sort of the following operand.

    arg0 and ret are internal data objects.

    Having an arguments, arg0, evaluate a bitwise not arithmetic. Put the result in ret. In a case of failure, if the arithmetic expression occurs in a guard, branch to the next clause/option using address. If the expression occurs in a body (address points to the corresponding FuncBegin), the current context information is generated, the BADARITH error is set and the error handling procedure is called.

    3.13 Term Comparisons

    Term comparisons in guards are compiled into general purpose instructions doing the required comparison. For efficiency reasons, when given arguments can be type decorated by the compile-time type analysis, the comparisons are coded explicitly. Some term comparisons which occur in a clause/case/if/receive body are compiled into calls to corresponding functions in the erlang module and are treated accordingly.

    Cmp/IntCmp/FlCmp

    Evaluate a given term comparison. The instruction occurs only in guards. Cmp when types of arguments are unknown. IntCmp when arguments are integers. FlCmp when arguments are floats.

    Threaded-code Syntax:
     
    lb_Cmp/IntCmp/FlCmp
    address
    cmp
    type
    arg0
    type
    arg1

    address is a branch address in a case of failure.

    cmp is a term comparison operator (Cmp: >, <, >=, =<, ==, /=; IntCmp/FlCmp: >, <, >=, =<)

     

     

    type indicates sort of the following operand.

    arg0 and arg1 are internal data objects.

    Having a comparison operator, cmp, and its arguments, arg0 and arg1, perform the required term comparison. In a case of failure, branch to the next clause/option using address.

    ExEqEq_head/Eq_head/ExNEq/NEql

    Evaluate a given term comparison. The instruction occurs only in a clause/case/if/receive head or guard. ExEqEq_head when exact equal. ExNEq when exact not equal. Eql_head is a specialized version of the ExExEq instruction, and NEql is a specialized version of the ExNEq instruction when arguments are small integers or atoms.

    Threaded-code Syntax:
     
    lb_ExEqEq_head/Eq_head/ExNEq/NEql
    address
    type
    arg0
    type
    arg1

    address is a branch address in a case of failure.

    type indicates sort of the following operand.

    arg0 and arg1 are internal data objects.

    Having two arguments, arg0 and arg1, perform the required term comparison (ExEqEq_head: =:=; ExNEq: =/=). When arguments are small integers or atoms the exact not equal comparison, NEql, and the exact equal comparison, Eql, are done directly in the emulator. In a case of failure, branch to the next clause/option using address.

    Eql_head_<type>

    Evaluate the exact equal term comparison. Eql_head_<type> is a further specialization of the Eql_head instruction.

    Threaded-code Syntax:
     
    lb_Eql_head_<type>
    address
    arg0
    arg1

    address is a branch address in a case of failure.

    arg0 and arg1 are internal data objects.

    Eql_head_<type> has the same semantics as the Eql_head instruction. The only difference is that types of all operands are coded implicitly as instruction opcode. Which types are coded as specialized instructions has been based on their frequency in existing large industrial applications.

    ExEqEq/Eql

    Evaluate the exact equal term comparison. Eql is a specialized version of the ExEqEq instruction (when arguments are small integers or atoms). The instructions occur only in a clause/case/if/receive body.

    Threaded-code Syntax:
     
    lb_ExEqEq/Eql
    &FuncBegin
    type
    arg0
    type
    arg1

    &FuncBegin is an address of the current function FuncBegin instruction.

    type indicates sort of the following operand.

    arg0 and arg1 are internal data objects.

    Having two arguments, arg0 and arg1, perform the exact equal, =:=, term comparison. When arguments are small integers or atoms the comparison is done directly in the emulator (Eql). In a case of failure, generate the current context information using &FuncBegin, set the BADMATCH error, generate information about the object being matched, and branch to error handling procedure.

    3.14 Indexing Instructions

    Erlang BEAM handles indexing implicitly by building a decision tree to access different clauses or options (avoiding repetitions of the same tests), and explicitly by a set of instructions for indexing on integer and atom values.

    LookupSwitch

    LookupSwitch is used for indexing on integer values.

    Threaded-code Syntax:
     
    lb_LookupSwitch
    type
    arg0
    size
    value0
    address0
    ...
    valueN
    addressN

    type indicates sort of the following operand.

    arg0 is an internal data object.

    size is a size of the included jump table (N+1).

    value<i> is an integer value.

    address<i> is a branch address in a case of value match.

    Having arg0 check its value against values in a given jump table, in a case of match branch to the corresponding instruction (using address<i>). To enable a binary search the values are sorted when the instruction is generated. If there are no matches found, the next instruction is picked.

    JmpSwitch

    JmpSwitch is a specialized version of the LookupSwitch instruction when integer values build a sequence: 0, 1, 2, 3, ..., N.

    Threaded-code Syntax:
     
    lb_JmpSwitch
    type
    arg0
    size
    address0
    ...
    addressN

    type indicates sort of the following operand.

    arg0 is an internal data object.

    size is a size of the included jump table (N+1).

    address<i> is a branch address in a case of value match.

    Having arg0 check its value against size of a given jump table. If the value is less or equal the given size, the corresponding branch address is used. If not, the next instruction is picked.

    AtomSwitch

    AtomSwitch is used for indexing on atom values.

    Byte-code Syntax:
     
    AtomSwitch_op
    type
    arg0
    size
    atom_name0
    offset0
    ...
    atom_nameN
    offsetN

    Threaded-code Syntax:
     
    lb_AtomSwitch
    type
    arg0
    size
    atom0
    address0
    ...
    atomN
    addressN

    type indicates sort of the following operand.

    arg0 is an internal data object.

    size is a size of the included jump table (N+1).

    atom<i> is a ready created atom.

    address<i> is a branch address in a case of value match.

    Having arg0 check it against atoms in a given jump table, in a case of match branch to the corresponding instruction (using address<i>). To enable a binary search the atoms are sorted when the instruction is loaded and the atoms are built. If there are no matches found, the next instruction is picked.

    3.15 Instruction Folding

    To save space and improve emulation time (instruction decoding, updating of the next-instruction pointer, I) some very frequent instruction sequences are coded as one instruction. The decision which instruction sequences are coded explicitly has been based on their frequency in existing large industrial applications.

    AH

    Allocate a new stack frame and test for required heap space. AH is a result of instruction folding of A and TH instructions.

    Threaded-code Syntax:
     
    lb_AH
    frame_size
    m
    n

    m is a size of required heap space (in words).

    n is a number of live temporal variables x(0), ..., x(n-1) (for garbage collection purposes).

    Check for required stack and heap space, call garbage collection if necessary. Allocate a new stack frame. Update the stack-top pointer E. Copy the continuation program pointer CP into the new frame.

    PT_<type>

    The PT_<type> instruction is a result of instruction folding of PT0_<type> and PTEl_<type> instructions. Can be followed by a number of PTEl_<type> instructions.

    Threaded-code Syntax:
     
    lb_PT_<type>
    tuple
    arity
    element

    tuple is a pointer to the being created tuple data object.

    arity gives a number of following tuple elements.

    element is the tuple first element.

    Create an initial structure for a tuple data object. Build the first tuple element. Set the tuple pointer to the new created object. Update the heap-top pointer. The type of tuple is implicitly coded as instruction opcode.

    M_R_<type>r

    Move an internal data object to the x(0) register. Return from a resident Erlang function call.

    Threaded-code Syntax:
     
    lb_M_R_<type>r
    object

    object is an internal data object.

    Move an internal data object, object (can be of type X_arg, Y_arg, C_arg) to x(0) and return control to the function caller.

    M_D_R_<type>r

    Move an internal data object to the x(0) register. Discard the current stack frame. Return from a resident Erlang function call.

    Threaded-code Syntax:
     
    lb_M_D_R_<type>r
    object
    frame_size

    object is an internal data object.

    frame_size is a size of the current stack frame to be discarded.

    Move an internal data object, object, to x(0). Copy the continuation program pointer from the current stack frame into CP and discard the frame. Update the stack-top pointer E. Return control to the function caller.

    D_R

    Discard the current stack frame. Return from a resident Erlang function call.

    Threaded-code Syntax:
     
    lb_D_R
    frame_size

    frame_size is a size of the current stack frame to be discarded.

    Copy the continuation program pointer from the current stack frame into CP and discard the frame. Update the stack-top pointer E. Return control to the function caller.

    TT_GTp_<type>

    Check if a given Erlang data object is a tuple of required arity.

    Threaded-code Syntax:
     
    lb_TT_GTp_<type>
    &FuncBegin
    object
    arity

    &FuncBegin is an address of the current function FuncBegin instruction.

    object is an existing Erlang data object.

    arity is the required arity.

    The instruction occurs only in a clause/case/if/receive body. Having a given data object check if it is a tuple of arity arity. In a case of failure, generate the current context information, set the BADMATCH error, and branch to error handling procedure. Type of object is coded implicitly as instruction opcode.

    TT_GTp_head_<type>

    Check if a given Erlang data object is a tuple of required arity. TT_GTp_head_<type> is a specialized version of the TT_GTp_<type> instruction.

    Threaded-code Syntax:
     
    lb_TT_GTp_head_<type>
    address
    object
    arity

    address is a branch address in a case of failure.

    object is an existing Erlang data object.

    arity is the required arity.

    The instruction occurs only in a clause/case/if/receive head. Having a given data object check if it is a tuple of arity arity. In a case of failure branch to the next clause/option using address. Type of object is coded implicitly as instruction opcode.

    TNonEmpL_A_<type>/TInt_A_<type>

    Check if a given Erlang data object is a non-empty list/an integer. If yes, allocate a new stack frame.

    Threaded-code Syntax:
     
    lb_TNonEmpL/TInt_A_<type>
    address
    object
    frame_size
    n

    address is a branch address in a case of failure.

    object is an existing Erlang data object.

    frame_size is the required frame size.

    n is a number of live temporal variables x(0), ..., x(n-1) (for garbage collection purposes).

    The instruction occurs only in a clause/case/if/receive head. Having a given data object check if it is a non-empty list/an integer. If yes, allocate a new stack frame (of frame_size). If not, branch to the next clause/option using address. Type of object is coded implicitly as instruction opcode.

    I_<n>

    Initialize a number of local variables (n = 2/3/4).

    Threaded-code Syntax:
     
    lb_I_<n>
    index0
    ...
    indexN

    index<i> is an index of a local variable y(index<i>) which must be explicitly initialized.

    Initialize a number of local variables y(index<i>). Due to some compiler optimizations the indexes are not necessarily a sequence of numbers.

    A_I_<n>

    Allocate a new stack frame. Initialize a number of local variables (n = 1/2/3/4).

    Threaded-code Syntax:
     
    lb_A_I_<n>
    frame_size
    n
    index0
    ...
    indexN

    frame_size is the required frame size.

    n is a number of live temporal variables x(0), ..., x(n-1) (for garbage collection purposes).

    index<i> is an index of a local variable y(index<i>) which must be explicitly initialized.

    Allocate a new stack frame (of frame_size). Initialize a number of local variables y(index<i>). Due to some compiler optimizations the indexes are not necessarily a sequence of numbers.

    M_C_<type>r

    Load the argument register x(0). Call a resident Erlang function.

    Byte-code Syntax:
     
    M_C_<type>r_op
    object
    function name
    function arity

    Threaded-code Syntax:
     
    lb_M_C_<type>r
    object
    &function
    function_arity
    &FuncBegin

    object is an internal data object.

    &function is an address of the first instruction corresponding to the called function.

    function_arity is a number of function arguments.

    &FuncBegin is an address of the current function FuncBegin instruction.

    Move an internal data object, object, to x(0). Set the continuation program pointer at the next instruction, increment number of reductions and check for suspension (if suspending, generate the current context information), branch to called function. Type of object is coded implicitly as instruction opcode.

    M_CL_<type>r

    Load the argument register x(0). Discard the current stack frame. Call a local Erlang function.

    Byte-code Syntax:
     
    M_CL_<type>r_op
    object
    function name
    function arity
    frame size

    Threaded-code Syntax:
     
    lb_M_CL_<type>r
    object
    &function
    function_arity
    frame_size
    &FuncBegin

    object is an internal data object.

    frame_size is a size of the current stack frame to be discarded.

    For info on other operands see C/CO.

    Move an internal data object, object, to x(0). Copy the continuation program pointer from the current stack frame into CP, discard the frame, increment number of reductions and check for suspension, branch to called function. Type of object is coded implicitly as instruction opcode.