Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Lex Plt
Lex Plt

Posted on

     

Adding short-circuiting in a bytecode interpreter

In the previous article, we saw how to compile functions and handle their scopes. We also saw how to optimize a certain kind of function calls, the tail call ones inUnderstanding tail call optimization, now we are going to see yet another optimization, this time on conditions and expression evaluation.

Basic way to deal with conditionals

Following the previous article(s), we could implementand /or as follows:

# a and bLOAD aLOAD bAND# foo() and bar()LOAD fooCALL 0LOAD barCALL 0AND
Enter fullscreen modeExit fullscreen mode

As you can see, each argument have to be evaluated before calling the operator, which is not something we might want! In mainstream languages like C, C++, Java, Python... the expressiona and b would evaluateb only ifa istrue. Ifa isfalse, no need to evaluate the rest of the expression: it will befalse. Same thing goes foror, ifa istrue, no need to evaluate the rest of the expression: it will betrue.

Understanding how short-circuiting works

What we want is evaluate arguments one at a time in an expression, and immediately stop if we have afalse in anand expression, ortrue in anor expression. In Python you could write it like this:

ifaandb:print("hello")# vvvifa:ifb:print("hello")# else: ...# -----------------ifaorb:print("hello")# vvvifa:print("hello")# <-+--- this is exactly the same code,else:#   |    actually not duplicated onceifb:#   |    compiled.print("hello")# <-/
Enter fullscreen modeExit fullscreen mode
  1. (and) We check ifa istrue, if not do nothing. Otherwise, evaluateb and act accordingly.
  2. (or) We check ifa istrue and execute our code. Otherwise evaluateb and iftrue execute our code.

Implementation in bytecode

Let's see howand is implemented inArkScript (as of 16/09/2024):

LOAD_SYMBOL aDUPPOP_JUMP_IF_FALSE (after)  ---`POP                           |LOAD_SYMBOL b                 |                  <-----------+
Enter fullscreen modeExit fullscreen mode
  1. We load oura variable as before and duplicate it
  2. We duplicate it for later use
  3. We pop the duplicate, if it isfalse we jump after the expression, on the next instruction (which could be a store or another compare ; thanks to the duplicate, we still have thefalse value here at the end
  4. If it istrue, we pop the original value, we don't need it anymore and just loadb. As in3. we continue with no special treatment with the next instruction, now having our boolean loaded to compare it, store it...

And that's it, we don't have to have a specific implementation to handleif a and b andval = a and b separately, as we jump on the next instruction, which might be aPOP_JUMP_IF_FALSE in the case of a condition (to avoid executing the code of the condition), or aSTORE in case of a variable assignment.

[!NOTE]
Implementingor would be practically identical, apart from thePOP_JUMP_IF_FALSE instruction that would be aPOP_JUMP_IF_TRUE!

Originally fromlexp.lt

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

C++ fanatic, video game maker, working on my own scripting language
  • Pronouns
    They/Them
  • Work
    Back-end Scala developper
  • Joined

More fromLex Plt

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp