Skip to main content
Engineering LibreTexts

13.5: Contexts — Representing Method Execution

  • Page ID
    43740
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    We saw that blocks refer to the home context when looking for variables. So now we will look at contexts. Contexts represent program execution. The Pharo execution engine represents its current execution state with the following information:

    1. the CompiledMethod whose bytecodes are being executed;
    2. the location of the next bytecode to be executed in that CompiledMethod. This is the interpreter’s program pointer;
    3. the receiver and arguments of the message that invoked the CompiledMethod;
    4. any temporary variable needed by the CompiledMethod;
    5. a call stack.

    In Pharo, the class MethodContext represents this execution information. A MethodContext instance holds information about a specific execution point. The pseudo-variable thisContext gives access to the current execution point.

    A method context where temp can be accessed.
    Figure \(\PageIndex{1}\): A method context where we can access the value of the temporary variable temp at that given point of execution.

    Interacting with Contexts

    Let us look at an example. Define the following method and execute it using Bexp new first: 33.

    Bexp>>first: arg
        | temp |
        temp := arg * 2.
        thisContext copy inspect.
        ^ temp
    

    You will get the inspector shown in Figure \(\PageIndex{1}\). Note that we copy the current context obtained using thisContext because the Virtual Machine limits memory consumption by reusing contexts.

    MethodContext does not only represent activation context of method execution but also the ones for blocks. Let us have a look at some values of the current context:

    • sender points to the previous context that led to the creation of the current one. Here when you executed the expression, a context was created and this context is the sender of the current one.
    • method points to the currently executing method.
    • pc holds a reference to the latest executed instruction. Here its value is 27. To see which instruction is referred to, double click on the method instance variable and select the all bytecodes field, you should get the situation depicted in Figure \(\PageIndex{2}\), which shows that the next instruction to be executed is pop (instruction 28).
    • stackp defines the depth of the stack of variables in the context. In most cases, its value is the number of stored temporary variables (including arguments). But in certain cases, for example during a message send, the depth of the stack is increased: the receiver is pushed, then the arguments, lastly the message send is executed and the depth of the stack goes back to its previous value.
    • closureOrNil holds a reference to the currently executing closure or nil.
    • receiver is the message receiver.

    The class MethodContext and its superclasses define many methods to get information about a particular context. For example, you can get the values of the arguments by sending the arguments message and the value of a particular temporary variable by sending tempNamed:.

    CompiledMethod bytecodes.
    Figure \(\PageIndex{2}\): The pc variable holds 27 because the last (bytecode) instruction executed was the message send inspect.

    Block nesting and contexts

    Now let us look at the case of block nesting and its impact on home contexts. In fact, a block points to a context when it was created: it is its outer context. Now depending on the situation the outer context of a block can be its home context or not. This is not complex: Each block is created inside some context. This is the block’s outer context. The outer context is the direct context in which a block was created. The home context is the one at the method level. If the block is not nested then the outer context is also the block home context.

    If the block is nested inside another block execution, then the outer context refers to that block execution context, and the block execution’s outerContext is the home context. There are as many outer context steps as there are nesting levels.

    Let’s look at the following example. When you execute, just press "ok" to the dialogs popping up.

    | homeContext b1 |
    homeContext := thisContext.
    b1 := [| b2 |
        self assert: thisContext closure == b1.
        self assert: b1 outerContext == homeContext.
        self assert: b1 home = homeContext.
        b2 := [self assert: thisContext closure == b2.
            self assert: b2 outerContext closure outerContext == homeContext].
            self assert: b2 home = homeContext.
        b2 value].
    b1 value
    
    • First we set in homeContext, the context before the block creation. homeContext is the home context of the blocks b1 and b2 because they are defined during this execution.
    • thisContext closure == b1 shows that the context inside the execution of the block b1 has a pointer to b1. The outer context of b1 is homeContext. Nothing new because b1 is defined during the execution starting after the assignment. The home context of b1 is the same as its outer context.
    • Inside b2 execution, the current context points to b2 itself since it is a closure. The outer context of the closure in which b2 is defined i.e., b1 points to homeContext. Finally the home context of b2 is homeContext. This last point shows that all the nested blocks have a separate outer context, but they share the same home context.

    This page titled 13.5: Contexts — Representing Method Execution is shared under a CC BY-SA 3.0 license and was authored, remixed, and/or curated by Alexandre Bergel, Damien Cassou, Stéphane Ducasse, Jannik Laval (Square Bracket Associates) via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.