summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/wavm/Lib/Runtime/Context.cpp
blob: 645ef8693aad91d2bbee707ce25a295fd3c59d43 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <string.h>
#include <atomic>
#include <vector>
#include "RuntimePrivate.h"
#include "WAVM/Inline/Assert.h"
#include "WAVM/Inline/BasicTypes.h"
#include "WAVM/Platform/Memory.h"
#include "WAVM/Platform/RWMutex.h"
#include "WAVM/Runtime/Runtime.h"
#include "WAVM/RuntimeABI/RuntimeABI.h"

using namespace WAVM;
using namespace WAVM::Runtime;

Context* Runtime::createContext(Compartment* compartment, std::string&& debugName)
{
	WAVM_ASSERT(compartment);
	Context* context = new Context(compartment, std::move(debugName));
	{
		Platform::RWMutex::ExclusiveLock lock(compartment->mutex);

		// Allocate an ID for the context in the compartment.
		context->id = compartment->contexts.add(UINTPTR_MAX, context);
		if(context->id == UINTPTR_MAX)
		{
			delete context;
			return nullptr;
		}
		context->runtimeData = &compartment->runtimeData->contexts[context->id];

		// Commit the page(s) for the context's runtime data.
		if(!Platform::commitVirtualPages(
			   (U8*)context->runtimeData,
			   sizeof(ContextRuntimeData) >> Platform::getBytesPerPageLog2()))
		{
			delete context;
			return nullptr;
		}
		Platform::registerVirtualAllocation(sizeof(ContextRuntimeData));

		// Initialize the context's global data.
		memcpy(context->runtimeData->mutableGlobals,
			   compartment->initialContextMutableGlobals,
			   maxMutableGlobals * sizeof(IR::UntaggedValue));

		context->runtimeData->context = context;
	}

	return context;
}

Runtime::Context::~Context()
{
	WAVM_ASSERT_RWMUTEX_IS_EXCLUSIVELY_LOCKED_BY_CURRENT_THREAD(compartment->mutex);
	if(id != UINTPTR_MAX) { compartment->contexts.removeOrFail(id); }

	Platform::decommitVirtualPages((U8*)runtimeData,
								   sizeof(ContextRuntimeData) >> Platform::getBytesPerPageLog2());
	Platform::deregisterVirtualAllocation(sizeof(ContextRuntimeData));
}

Compartment* Runtime::getCompartment(const Context* context) { return context->compartment; }

void Runtime::setCheckStackDepthCallback(Context* context, void (*callback)())
{
	context->setCheckStackDepthCallback(callback);
}

Context* Runtime::cloneContext(const Context* context, Compartment* newCompartment)
{
	// Create a new context and initialize its runtime data with the values from the source context.
	Context* clonedContext = createContext(newCompartment);
	if(clonedContext)
	{
		memcpy(clonedContext->runtimeData->mutableGlobals,
			   context->runtimeData->mutableGlobals,
			   maxMutableGlobals * sizeof(IR::UntaggedValue));
		clonedContext->checkStackDepthCallback = context->checkStackDepthCallback;
	}
	return clonedContext;
}