Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2
* vim: set ts=8 sts=2 et sw=2 tw=80:
3
*
4
* Copyright 2016 Mozilla Foundation
5
*
6
* Licensed under the Apache License, Version 2.0 (the "License");
7
* you may not use this file except in compliance with the License.
8
* You may obtain a copy of the License at
9
*
11
*
12
* Unless required by applicable law or agreed to in writing, software
13
* distributed under the License is distributed on an "AS IS" BASIS,
14
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
* See the License for the specific language governing permissions and
16
* limitations under the License.
17
*/
18
19
#include "wasm/WasmRealm.h"
20
21
#include "vm/Realm.h"
22
#include "wasm/WasmInstance.h"
23
24
#include "debugger/DebugAPI-inl.h"
25
26
using namespace js;
27
using namespace wasm;
28
29
wasm::Realm::Realm(JSRuntime* rt) : runtime_(rt) {}
30
31
wasm::Realm::~Realm() { MOZ_ASSERT(instances_.empty()); }
32
33
struct InstanceComparator {
34
const Instance& target;
35
explicit InstanceComparator(const Instance& target) : target(target) {}
36
37
int operator()(const Instance* instance) const {
38
if (instance == &target) {
39
return 0;
40
}
41
42
// Instances can share code, so the segments can be equal (though they
43
// can't partially overlap). If the codeBases are equal, we sort by
44
// Instance address. Thus a Code may map to many instances.
45
46
// Compare by the first tier, always.
47
48
Tier instanceTier = instance->code().stableTier();
49
Tier targetTier = target.code().stableTier();
50
51
if (instance->codeBase(instanceTier) == target.codeBase(targetTier)) {
52
return instance < &target ? -1 : 1;
53
}
54
55
return target.codeBase(targetTier) < instance->codeBase(instanceTier) ? -1
56
: 1;
57
}
58
};
59
60
bool wasm::Realm::registerInstance(JSContext* cx,
61
HandleWasmInstanceObject instanceObj) {
62
MOZ_ASSERT(runtime_ == cx->runtime());
63
64
Instance& instance = instanceObj->instance();
65
MOZ_ASSERT(this == &instance.realm()->wasm);
66
67
instance.ensureProfilingLabels(cx->runtime()->geckoProfiler().enabled());
68
69
if (instance.debugEnabled() &&
70
instance.realm()->debuggerObservesAllExecution()) {
71
instance.debug().ensureEnterFrameTrapsState(cx, true);
72
}
73
74
{
75
if (!instances_.reserve(instances_.length() + 1)) {
76
return false;
77
}
78
79
auto runtimeInstances = cx->runtime()->wasmInstances.lock();
80
if (!runtimeInstances->reserve(runtimeInstances->length() + 1)) {
81
return false;
82
}
83
84
// To avoid implementing rollback, do not fail after mutations start.
85
86
InstanceComparator cmp(instance);
87
size_t index;
88
89
MOZ_ALWAYS_FALSE(
90
BinarySearchIf(instances_, 0, instances_.length(), cmp, &index));
91
MOZ_ALWAYS_TRUE(instances_.insert(instances_.begin() + index, &instance));
92
93
MOZ_ALWAYS_FALSE(BinarySearchIf(runtimeInstances.get(), 0,
94
runtimeInstances->length(), cmp, &index));
95
MOZ_ALWAYS_TRUE(
96
runtimeInstances->insert(runtimeInstances->begin() + index, &instance));
97
}
98
99
// Notify the debugger after wasmInstances is unlocked.
100
DebugAPI::onNewWasmInstance(cx, instanceObj);
101
return true;
102
}
103
104
void wasm::Realm::unregisterInstance(Instance& instance) {
105
InstanceComparator cmp(instance);
106
size_t index;
107
108
if (BinarySearchIf(instances_, 0, instances_.length(), cmp, &index)) {
109
instances_.erase(instances_.begin() + index);
110
}
111
112
auto runtimeInstances = runtime_->wasmInstances.lock();
113
if (BinarySearchIf(runtimeInstances.get(), 0, runtimeInstances->length(), cmp,
114
&index)) {
115
runtimeInstances->erase(runtimeInstances->begin() + index);
116
}
117
}
118
119
void wasm::Realm::ensureProfilingLabels(bool profilingEnabled) {
120
for (Instance* instance : instances_) {
121
instance->ensureProfilingLabels(profilingEnabled);
122
}
123
}
124
125
void wasm::Realm::addSizeOfExcludingThis(MallocSizeOf mallocSizeOf,
126
size_t* realmTables) {
127
*realmTables += instances_.sizeOfExcludingThis(mallocSizeOf);
128
}
129
130
void wasm::InterruptRunningCode(JSContext* cx) {
131
auto runtimeInstances = cx->runtime()->wasmInstances.lock();
132
for (Instance* instance : runtimeInstances.get()) {
133
instance->tlsData()->setInterrupt();
134
}
135
}
136
137
void wasm::ResetInterruptState(JSContext* cx) {
138
auto runtimeInstances = cx->runtime()->wasmInstances.lock();
139
for (Instance* instance : runtimeInstances.get()) {
140
instance->tlsData()->resetInterrupt(cx);
141
}
142
}