Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some basic Doxygen comments for major APIs #5

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/environment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,29 @@

namespace winter {

/**
* \brief Represents a single WebAssembly sandboxed environment.
*
* Each Environment represents a completely isolated WebAssembly sandbox. Each sandbox operates
* entirely independently from all others. Because of this, there are several restrictions on
* sharing between WebAssembly code instantiated in different sandboxes:
*
* - WebAssembly code from one sandbox cannot directly call WebAssembly code in a different sandbox
* - References can only be used in the WebAssembly sandbox in which they were created
* - Linear memory cannot be shared between WebAssembly code in different sandboxes, even if it is
* marked as shared
*/
class Environment {
TypeTable _types;
public:
/**
* \brief Gets the TypeTable used by WebAssembly code in this sandbox.
*/
const TypeTable& types() const { return _types; }

/**
* \brief Gets the TypeTable used by WebAssembly code in this sandbox.
*/
TypeTable& types() { return _types; }
};

Expand Down
124 changes: 121 additions & 3 deletions src/func.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,25 @@ class LinkedFunc;

using JitFunction = uint32_t (*)(LinkedFuncInternal* func);

/**
* \brief Represents a stream of WebAssembly instructions.
*/
class InstructionStream {
std::vector<uint8_t> _stream;
public:
explicit InstructionStream(std::vector<uint8_t>&& stream) : _stream(std::move(stream)) {}

/**
* \brief Gets the size (in bytes) of this instruction stream.
*/
size_t size() const { return _stream.size(); }

friend class InstructionCursor;
};

/**
* \brief Represents a cursor for reading from an InstructionStream.
*/
class InstructionCursor {
const InstructionStream* _stream;
const uint8_t* _cursor;
Expand All @@ -66,32 +75,74 @@ class InstructionCursor {
_cursor = _stream->_stream.data() + off;
}

/**
* \brief Gets the cursor's current offset (in bytes) in the instruction stream.
*/
size_t offset() const { return _cursor - _stream->_stream.data(); }

/**
* \brief Jumps this cursor the specified number of bytes forward or backward.
*/
void jump_relative(ssize_t off) {
WASSERT(off >= begin() - _cursor, "Instruction cursor out-of-bounds");
WASSERT(off <= end() - _cursor, "Instruction cursor out-of-bounds");

_cursor += off;
}

/**
* \brief Reads the next byte at this cursor as a uint8_t.
*/
uint8_t read_u8() {
WASSERT(_cursor != end(), "Instruction cursor out-of-bounds");

return *(_cursor++);
}
};

/**
* \brief Represents a WebAssembly function which has not yet been created.
*
* There are two different kinds of AbstractFunc:
*
* - An AbstractFunc with is_import set to false represents a WebAssembly function which will be
* created when instantiating a module.
* - An AbstractFunc with is_import set to true represents a function which will be imported from
* another module.
*
* \see AbstractModule
* \see UnlinkedFunc
* \see LinkedFunc
*/
struct AbstractFunc {
bool is_import;

bool is_import; ///< Whether this function will be imported from another module.

/**
* \brief The debug name of this function, or empty string if no debug name was provided.
*
* For functions which will be imported from another module, i.e. have is_import set to true,
* this value will not be used and the debug name will be read from the function which ends up
* being linked into this slot. In that case, this field will be the empty string.
*/
std::string debug_name;

/**
* \brief The WebAssembly instructions constituting this function.
*
* For functions which will be imported from another module, i.e. have is_import set to true,
* this field will not be populated and will instead be set to nullptr.
*/
std::shared_ptr<const InstructionStream> instrs;
FuncSig sig;
FuncSig sig; ///< The signature of this function.

AbstractFunc(bool is_import, std::string debug_name, std::shared_ptr<const InstructionStream> instrs, FuncSig sig)
: is_import(is_import), debug_name(std::move(debug_name)), instrs(std::move(instrs)), sig(std::move(sig)) {}

/**
* \brief Creates an AbstractFunc for a function which will be imported from another module.
*
* \param[in] sig the function signature that the function being imported must have.
*/
static AbstractFunc for_import(FuncSig sig) {
return AbstractFunc(true, "", nullptr, std::move(sig));
}
Expand All @@ -105,6 +156,12 @@ struct UnlinkedFuncInternal {
};
static_assert(std::is_standard_layout<UnlinkedFuncInternal>::value, "UnlinkedFuncInternal must be standard layout");

/**
* \brief Represents a WebAssembly function which has been partially instantiated.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be useful to explain what "partially instantiated" means

*
* \see AbstractFunc
* \see LinkedFunc
*/
class UnlinkedFunc {
UnlinkedFuncInternal _internal;
std::string _debug_name;
Expand All @@ -119,13 +176,43 @@ class UnlinkedFunc {
UnlinkedFunc& operator=(const UnlinkedFunc&) = delete;
UnlinkedFunc& operator=(UnlinkedFunc&&) = delete;
public:
/**
* \brief Gets a pointer to the internal information structure for this function.
*
* The internal data structure contains basic information about this function that must be
* accessible to JITted code for performance reasons. This information is represented in a
* standard-layout struct so that it can be read/written without needing to call C++ code.
*
* \warning This is not considered to be part of the public API of winter and is only for
* internal use by the VM. The layout of the internal struct is not stable and should
* not be relied upon.
*/
UnlinkedFuncInternal* internal() { return &_internal; }

/**
* \brief Gets the function signature for calling this function.
*/
const FuncSig& signature() const { return *_internal.sig; }

/**
* \brief Gets the debug name for this function or an empty string if no name was provided.
*/
const std::string& debug_name() const { return _debug_name; }

/**
* \brief Gets the instruction stream for the WebAssembly instructions in this function.
*/
std::shared_ptr<const InstructionStream> instrs() const { return _instrs; }

/**
* \brief Creates an UnlinkedFunc from an AbstractFunc.
*
* This function creates an unlinked instance of the given WebAssembly function. Any linked
* versions of the returned function can only be called from the context of the provided
* WebAssembly sandbox.
*/
static std::shared_ptr<UnlinkedFunc> instantiate(const AbstractFunc& func, Environment& env);

static std::shared_ptr<UnlinkedFunc> create_mock(const FuncSig* sig) {
auto func = std::shared_ptr<UnlinkedFunc>(new UnlinkedFunc());

Expand All @@ -143,6 +230,12 @@ struct LinkedFuncInternal {
};
static_assert(std::is_standard_layout<LinkedFuncInternal>::value, "LinkedFuncInternal must be standard layout");

/**
* \brief Represents a WebAssembly function which is part of a fully instantiated module.
*
* \see UnlinkedFunc
* \see ModuleInstance
*/
class LinkedFunc {
LinkedFuncInternal _internal;
std::shared_ptr<UnlinkedFunc> _unlinked;
Expand All @@ -157,12 +250,37 @@ class LinkedFunc {
LinkedFunc& operator=(const LinkedFunc&) = delete;
LinkedFunc& operator=(LinkedFunc&&) = delete;
public:
/**
* \brief Gets a pointer to the internal information structure for this function.
*
* The internal data structure contains basic information about this function that must be
* accessible to JITted code for performance reasons. This information is represented in a
* standard-layout struct so that it can be read/written without needing to call C++ code.
*
* \warning This is not considered to be part of the public API of winter and is only for
* internal use by the VM. The layout of the internal struct is not stable and should
* not be relied upon.
*/
LinkedFuncInternal* internal() { return &_internal; }

/**
* \brief Gets the UnlinkedFunc that this function was created from.
*/
UnlinkedFunc& unlinked() const { return *_unlinked; }

/**
* \brief Gets the module instance that this function is part of.
*/
ModuleInstance& module() const { return *_module; }

/**
* \brief Creates a new LinkedFunc from an UnlinkedFunc.
*
* This function creates a linked version of the provided UnlinkedFunc using the provided
* ModuleInstance for linking.
*/
static std::unique_ptr<LinkedFunc> instantiate(std::shared_ptr<UnlinkedFunc> unlinked, ModuleInstance* module);

static std::unique_ptr<LinkedFunc> create_mock(const FuncSig* sig) {
auto func = std::unique_ptr<LinkedFunc>(new LinkedFunc());
auto unlinked = UnlinkedFunc::create_mock(sig);
Expand Down
Loading