0x7CFE / llst

LLVM powered Little Smalltalk.
Other
93 stars 10 forks source link

Eliminate shadow stack in favor of execution context #66

Open 0x7CFE opened 9 years ago

0x7CFE commented 9 years ago

Overview

Execution context of a Smalltalk method is represented by an instance of Context class. It holds all information required to execute a method:

Jit version of VM takes advantage of hardware stack and links intermediate values directly. This allows us to eliminate the value stack completely. Instances of Context that are created during jit execution are allocated on the hardware stack. Even their stack, bytePointer and stackTop fields aren't initialized and left simply as nil.

However, everything has it's cost. In particular, every intermediate value created during jit execution should be protected in terms of GC safety. If garbage collection occur, it may effectively change the location of many objects rendering their pointers completely unusable unless protected. Much worse, locations of intermediate values may be stored in register, not in memory. If GC will not be able to track such values it will not update them.

Problem is solved by introducing so called shadow stack: a linked list of pointers to a stack frames that may contain intermediate values. GC knows about shadow stack and traverse it when garbage collection occurs. It is jit code generator responsibility to maintain the shadow stack along method execution and to re-load the values which may be changed since last GC. Finally, when method is finished and a value need to be returned shadow stack is unwound. This also happens during exception propagation.

The problem

Shadow stacks work well, but their maintenance takes time. Top entry in the shadow stack is located in a global variable which is not very flexible and not scalable when we start think about threading. Finally, shadow stack is redundant. In fact, it duplicates all information that may be deduced by looking at context instances. We're dealing with fully reflexive object oriented language, by the way :)

Let's try to use existing Smalltalk objects and solve the issue on our own.

The solution

The only purpose of shadow stack is to pin point locations on the hardware stack which should be tracked by GC. We know that context objects are tracked by GC, have unused fields and are accessible from the jit code, hmm…

Okay, so here's the deal:

Simple as it is. We even may pin point the locations of spilled registers that are known to hold object pointers and update them too. In that case it will be redundant to protect the context and self pointers!