libjit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Using libjit for stack based VM


From: Aleksey Demakov
Subject: Re: Using libjit for stack based VM
Date: Thu, 22 Jul 2021 19:19:14 +0300

Hi,

I'm not quite sure what the problem you are dealing with. I only see
that you created two values on the "stack" array but basically do not
use it as a real stack. You overwrite the same "stack[0]" value
storing different constants to it. This is not how a stack is supposed
to work. After any binary op two top values on the stack are popped
and the op result is pushed.

Thus instead of this

    tmp = jit_value_get_param(function, 0);
    jit_insn_store(function, stack[0], tmp);

    tmp = jit_value_get_param(function, 1);
    jit_insn_store(function, stack[1], tmp);

    tmp = jit_insn_lt(function, stack[0], stack[1]);
    jit_insn_store(function, stack[0], tmp);

It's better to have something like this

    int top = 0;

    stack[top] = jit_value_get_param(function, 0);
    top++;

    stack[top] = jit_value_get_param(function, 1);
    top++;

    top -= 2; // pop 2 top elements
    stack[top] = jit_insn_lt(function, stack[top], stack[top + 1]);
    top++;   // push the result

This is described here (the stack top manipulation is shortened there a bit):

http://demakov.com/projects/libjit-docs/libjit_7.html

As for the branch there is indeed a complication. You have to store
the result at some common variable and then fill the stack top again
after the branch.

    top--;
    jit_insn_branch_if_not(function, stack[top], &label1);

    jit_value_t common = jit_value_create(function, jit_type_int);

    /* true */
    tmp = jit_value_create_nint_constant(function, jit_type_int, 100);
    jit_insn_store(function, common, tmp);

    /* go to end */
    jit_insn_branch(function, &label2);

    /* label1 */
    jit_insn_label(function, &label1);

    /* false */
    tmp = jit_value_create_nint_constant(function, jit_type_int, 200);
    jit_insn_store(function, common, tmp);

    /* label2 end */
    jit_insn_label(function, &label2);

    /* fill the stack top */
    stack[top] = jit_insn_load(function, common);
    top++;

    /* return */
    top--;
    jit_insn_return(function, stack[top]);

Generally both branches must consume the same number of values from
the stack. And both branches must produce the same number of values
(probably different from the consumed number). In your example you
consume 0 values and produce 1 value. But there may be other cases.
Thus you have to analyze the branches to see how many temporary values
have to be created and thus how many stack positions have to be filled
after the branch.

Regards,
Aleksey


On Sun, Jul 18, 2021 at 5:19 PM Slawomir Maludzinski
<slawomir.maludzinski@gmail.com> wrote:
>
> Hi,
>
> I would like to use libjit for stack based VM. Do you know how to change the 
> following bytecode into jit-ed version using libjit?
>
> Lets say we have the following function:
>
> int test_min(int a, int b) { return (a < b) ? a : b; }
>
> Code:
> 0: iload_0
> 1: iload_1
> 2: if_icmpge 9
> 5: iload_0
> 6: goto 10
> 9: iload_1
> 10: ireturn
>
> Do you know how to manage the stack when the above bytecode is compiled using 
> JIT? Without JIT reference to an object from the top of stack is returned. I 
> would like to translate each bytecode into separate jit_insn function calls 
> however, I cannot imagine how this can be done automatically.
>
> I am attaching a simple program where I commented on hurdles.
>
> Thank you for your help.
>
> Sławomir Maludziński
>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]