Skip to content

Commit

Permalink
Split the State into a modeling and active State
Browse files Browse the repository at this point in the history
This patch starts to move any operation on the execution context
into the VM state, for potential modeling.

The b9::VirtualMachineState has been renamed to State, and it's
functionality has been expanded with new push / pop operations.

This patch introduces two new State variants: Active and Model. The
ActiveState will always write out the state. For example, a push really
will write out a value to the operand stack. The Model state will track
the push, and only write out to the stack when we force a commit.

Now, we use the state unconditionally, instead of checking for the lazy
vm state everywhere. Which state we use depends on the flag.

This PR also removes the QSTACK, QRELOAD, and QRELOAD_DROP macros, in
favor of inline functions and virtual function calls.

Signed-off-by: Robert Young <[email protected]>
  • Loading branch information
rwy7 committed Jul 12, 2018
1 parent 142a367 commit af93519
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 142 deletions.
6 changes: 4 additions & 2 deletions b9/include/b9/compiler/MethodBuilder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "b9/VirtualMachine.hpp"
#include "b9/compiler/Compiler.hpp"
#include "b9/compiler/GlobalTypes.hpp"
#include "b9/compiler/VirtualMachineState.hpp"
#include "b9/compiler/State.hpp"
#include "b9/instructions.hpp"

#include <Jit.hpp>
Expand All @@ -25,7 +25,9 @@ class MethodBuilder : public TR::MethodBuilder {

private:
void defineFunctions();

void defineLocals();

void defineParameters();

/// For a single bytecode, generate the
Expand All @@ -50,7 +52,7 @@ class MethodBuilder : public TR::MethodBuilder {

TR::IlValue *popInt48(TR::BytecodeBuilder *builder);

void drop(TR::BytecodeBuilder *builder);
void drop(TR::BytecodeBuilder *builder, std::size_t n = 1);

TR::IlValue *loadVal(TR::IlBuilder *builder, int valIndex);

Expand Down
178 changes: 178 additions & 0 deletions b9/include/b9/compiler/State.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
#if !defined(B9_STATE_HPP_)
#define B9_STATE_HPP_

#include <ilgen/BytecodeBuilder.hpp>
#include <ilgen/IlBuilder.hpp>
#include <ilgen/MethodBuilder.hpp>
#include <ilgen/VirtualMachineOperandStack.hpp>
#include <ilgen/VirtualMachineRegister.hpp>
#include <ilgen/VirtualMachineRegisterInStruct.hpp>
#include <ilgen/VirtualMachineState.hpp>

namespace b9 {

/// An interface to working with the state of the B9 execution context.
class State : public TR::VirtualMachineState {
public:
/// Push an Om::Value onto the stack
virtual void pushValue(TR::IlBuilder *, TR::IlValue *value) = 0;

/// Pop an Om::Value from the stack
virtual TR::IlValue *popValue(TR::IlBuilder *) = 0;

/// The size of the stack has been changed as part of an external operation.
/// Adjust the model to note the new size.
virtual void adjust(TR::IlBuilder *b, int n) = 0;
};

template <typename BuilderT>
State *state(BuilderT *b) {
return dynamic_cast<State *>(b->vmState());
}

/// State object that keeps VM structures up to date. Commit and reload are
/// no-ops, since state is always written out immediately. Copy and Merge are
/// also no-ops, there is no model to merge or copy.
class ActiveState : public State {
public:
ActiveState(TR::MethodBuilder *b, const GlobalTypes &types) : types_(types) {}

ActiveState(const ActiveState &) = default;

/// Push a Value onto the OperandStack. Will actually update the stack.
virtual void pushValue(TR::IlBuilder *b, TR::IlValue *value) override final {
TR::IlValue *stack = this->stack(b);

TR::IlValue *stackTop = b->LoadIndirect("b9::OperandStack", "top_", stack);

b->StoreAt(stackTop, b->ConvertTo(types_.stackElement, value));

TR::IlValue *newStackTop =
b->IndexAt(types_.stackElementPtr, stackTop, b->ConstInt32(1));

b->StoreIndirect("b9::OperandStack", "top_", stack, newStackTop);
}

/// Pop a Value from the OperandStack. Will actually update the stack.
virtual TR::IlValue *popValue(TR::IlBuilder *b) override final {
auto stack = this->stack(b);

TR::IlValue *stackTop = b->LoadIndirect("b9::OperandStack", "top_", stack);

TR::IlValue *newStackTop =
b->IndexAt(types_.stackElementPtr, stackTop, b->ConstInt32(-1));

b->StoreIndirect("b9::OperandStack", "top_", stack, newStackTop);

TR::IlValue *value = b->LoadAt(types_.stackElementPtr, newStackTop);

return value;
}

virtual void adjust(TR::IlBuilder *b, int n) override final {
assert(n < 1);
// TODO: No way to increase stack size in model.
}

/// @group VirtualMachineState overrides
/// @{

virtual void Commit(TR::IlBuilder *b) override final {
// nothing to commit
}

virtual void Reload(TR::IlBuilder *b) override final {
// nothing to reload
}

virtual VirtualMachineState *MakeCopy() override final {
return new ActiveState(*this);
}

virtual void MergeInto(TR::VirtualMachineState *other,
TR::IlBuilder *b) override final {
// nothing to merge
}

/// @}

private:
TR::IlValue *stack(TR::IlBuilder *b) {
return b->StructFieldInstanceAddress("b9::ExecutionContext", "stack_",
b->Load("executionContext"));
}

const GlobalTypes &types_;
};

/// Lazy VM state that only commits state on demand.
/// Simulates all state of the virtual machine state while compiled code is
/// running. It simulates the stack and the pointer to the top of the stack.
class ModelState : public State {
public:
ModelState(TR::MethodBuilder *b, const GlobalTypes &types)
: stack_(nullptr), stackTop_(nullptr) {
stackTop_ = new TR::VirtualMachineRegisterInStruct(
b, "b9::OperandStack", "stack", "top_", "stackTop");

stack_ = new TR::VirtualMachineOperandStack(b, 64, types.stackElement,
stackTop_, true, 0);
}

ModelState(const ModelState &other)
: stack_(other.stack_), stackTop_(other.stackTop_) {}

/// Model a push onto the OperandStack. The Value will be saved in an
/// intermediate IlValue.
virtual void pushValue(TR::IlBuilder *b, TR::IlValue *value) override final {
return stack_->Push(b, value);
}

/// Model a pop from the OperandStack. The result is an Il Value.
virtual TR::IlValue *popValue(TR::IlBuilder *b) override final {
return stack_->Pop(b);
}

virtual void adjust(TR::IlBuilder *b, int n) override final {
assert(n < 1);
// TODO: No way to increase stack size yet.
stack_->Drop(b, -int32_t(n));
}

/// @group TR::VirtualMachineState overrides
/// @{

virtual void Commit(TR::IlBuilder *b) override final {
stack_->Commit(b);
stackTop_->Commit(b);
}

virtual void Reload(TR::IlBuilder *b) override final {
stackTop_->Reload(b);
stack_->Reload(b);
}

virtual TR::VirtualMachineState *MakeCopy() override final {
return new ModelState(*this);
}

virtual void MergeInto(TR::VirtualMachineState *other,
TR::IlBuilder *b) override final {
MergeInto(dynamic_cast<ModelState *>(other), b);
}

void MergeInto(ModelState *other, TR::IlBuilder *b) {
stack_->MergeInto(other->stack_, b);
stackTop_->MergeInto(other->stackTop_, b);
}

/// @}

private:
TR::VirtualMachineOperandStack *stack_;
TR::VirtualMachineRegister *stackTop_;
};

} // namespace b9

#endif // B9_STATE_HPP_
52 changes: 0 additions & 52 deletions b9/include/b9/compiler/VirtualMachineState.hpp

This file was deleted.

Loading

0 comments on commit af93519

Please sign in to comment.