Async Part 4 - What does the Hack compiler do with async functions
In the last article we looked at how the C# transforms async functions into executable code. Starting from this article we will start looking at how async functions in the Hack language are executed.
Example function
For this investigation we will be looking at a simple async function:
async function addAsync(int $a, int $b): Awaitable<int> { $sum = $a + $b; await HH\Asio\usleep(1000); return $sum + 42; }
Setting up our HHVM environment
To compile HHVM and Hack we will perform the following steps:
- Install Debian 10
- Follow the directions for building from source
- To enable disassembly, we will use the following command to configure while building:
./configure -DCMAKE_BUILD_TYPE=Debug -DMYSQL_UNIX_SOCK_ADDR=/dev/null -DENABLE_XED=ON
- To see the the HHVM bytecode and intermediate representation of our program, we will use this command to execute it:
TRACE=hhir:1,printir:2 HPHP_TRACE_FILE=/dev/stdout ./hhvm -vEval.DumpBytecode=1 ./test.hack
What Hack does with our async function
Let’s see what the HHVM bytecode generated by the compiler looks like:
Function (can_async_eager_ret) addAsync Param: a int (HH\int) Param: b int (HH\int) Ret: int (HH\Awaitable<HH\int>) maxStackCells: 6 numLocals: 3 numIterators: 0 // line 5 0: VerifyParamType L:0 2: VerifyParamType L:1 // line 2 4: CGetL L:1:1 7: CGetL2 L:0:0 10: Add 11: SetL L:2 13: PopC // line 3 14: NullUninit 15: NullUninit 16: Int 1000 25: FCallFuncD <> 1 1 "0" 21 (46) "" "HH\\Asio\\usleep" 37: Dup 38: IsTypeC Null 40: JmpNZ 6 (46) 45: Await 46: PopC // line 4 47: Int 42 56: CGetL2 L:2:2 59: Add 60: VerifyRetTypeC 61: RetC
We can see here that the async support is directly built into the bytecode.
At offset 45
we can see the Await
instruction.
The await operator is a first class operation in the HHVM bytecode.
Unlike C#, the Hack compiler does not transform our function into state machine.
We will have to go deeper into the HHVM compiler next time to see what’s going on.
Next time we will go deeper into HHVM intermediate representation to figure out what is going on with our async function at runtime.