summaryrefslogtreecommitdiffstats
path: root/js/src/wasm/WasmRealm.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--js/src/wasm/WasmRealm.cpp152
1 files changed, 152 insertions, 0 deletions
diff --git a/js/src/wasm/WasmRealm.cpp b/js/src/wasm/WasmRealm.cpp
new file mode 100644
index 0000000000..8907715c8f
--- /dev/null
+++ b/js/src/wasm/WasmRealm.cpp
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ *
+ * Copyright 2016 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wasm/WasmRealm.h"
+
+#include "vm/GlobalObject.h"
+#include "vm/Realm.h"
+#include "wasm/WasmDebug.h"
+#include "wasm/WasmInstance.h"
+#include "wasm/WasmProcess.h"
+
+#include "debugger/DebugAPI-inl.h"
+#include "wasm/WasmInstance-inl.h"
+
+using namespace js;
+using namespace wasm;
+
+wasm::Realm::Realm(JSRuntime* rt) : runtime_(rt) {}
+
+wasm::Realm::~Realm() { MOZ_ASSERT(instances_.empty()); }
+
+struct InstanceComparator {
+ const Instance& target;
+ explicit InstanceComparator(const Instance& target) : target(target) {}
+
+ int operator()(const Instance* instance) const {
+ if (instance == &target) {
+ return 0;
+ }
+
+ // Instances can share code, so the segments can be equal (though they
+ // can't partially overlap). If the codeBases are equal, we sort by
+ // Instance address. Thus a Code may map to many instances.
+
+ // Compare by the first tier, always.
+
+ Tier instanceTier = instance->code().stableTier();
+ Tier targetTier = target.code().stableTier();
+
+ if (instance->codeBase(instanceTier) == target.codeBase(targetTier)) {
+ return instance < &target ? -1 : 1;
+ }
+
+ return target.codeBase(targetTier) < instance->codeBase(instanceTier) ? -1
+ : 1;
+ }
+};
+
+bool wasm::Realm::registerInstance(JSContext* cx,
+ Handle<WasmInstanceObject*> instanceObj) {
+ MOZ_ASSERT(runtime_ == cx->runtime());
+
+ Instance& instance = instanceObj->instance();
+ MOZ_ASSERT(this == &instance.realm()->wasm);
+
+ instance.ensureProfilingLabels(cx->runtime()->geckoProfiler().enabled());
+
+ if (instance.debugEnabled() &&
+ instance.realm()->debuggerObservesAllExecution()) {
+ instance.debug().ensureEnterFrameTrapsState(cx, &instance, true);
+ }
+
+ {
+ if (!instances_.reserve(instances_.length() + 1)) {
+ return false;
+ }
+
+ auto runtimeInstances = cx->runtime()->wasmInstances.lock();
+ if (!runtimeInstances->reserve(runtimeInstances->length() + 1)) {
+ return false;
+ }
+
+ // To avoid implementing rollback, do not fail after mutations start.
+
+ InstanceComparator cmp(instance);
+ size_t index;
+
+ // The following section is not unsafe, but simulated OOM do not consider
+ // the fact that these insert calls are guarded by the previous reserve
+ // calls.
+ AutoEnterOOMUnsafeRegion oomUnsafe;
+ (void)oomUnsafe;
+
+ MOZ_ALWAYS_FALSE(
+ BinarySearchIf(instances_, 0, instances_.length(), cmp, &index));
+ MOZ_ALWAYS_TRUE(instances_.insert(instances_.begin() + index, &instance));
+
+ MOZ_ALWAYS_FALSE(BinarySearchIf(runtimeInstances.get(), 0,
+ runtimeInstances->length(), cmp, &index));
+ MOZ_ALWAYS_TRUE(
+ runtimeInstances->insert(runtimeInstances->begin() + index, &instance));
+ }
+
+ // Notify the debugger after wasmInstances is unlocked.
+ DebugAPI::onNewWasmInstance(cx, instanceObj);
+ return true;
+}
+
+void wasm::Realm::unregisterInstance(Instance& instance) {
+ InstanceComparator cmp(instance);
+ size_t index;
+
+ if (BinarySearchIf(instances_, 0, instances_.length(), cmp, &index)) {
+ instances_.erase(instances_.begin() + index);
+ }
+
+ auto runtimeInstances = runtime_->wasmInstances.lock();
+ if (BinarySearchIf(runtimeInstances.get(), 0, runtimeInstances->length(), cmp,
+ &index)) {
+ runtimeInstances->erase(runtimeInstances->begin() + index);
+ }
+}
+
+void wasm::Realm::ensureProfilingLabels(bool profilingEnabled) {
+ for (Instance* instance : instances_) {
+ instance->ensureProfilingLabels(profilingEnabled);
+ }
+}
+
+void wasm::Realm::addSizeOfExcludingThis(MallocSizeOf mallocSizeOf,
+ size_t* realmTables) {
+ *realmTables += instances_.sizeOfExcludingThis(mallocSizeOf);
+}
+
+void wasm::InterruptRunningCode(JSContext* cx) {
+ auto runtimeInstances = cx->runtime()->wasmInstances.lock();
+ for (Instance* instance : runtimeInstances.get()) {
+ instance->setInterrupt();
+ }
+}
+
+void wasm::ResetInterruptState(JSContext* cx) {
+ auto runtimeInstances = cx->runtime()->wasmInstances.lock();
+ for (Instance* instance : runtimeInstances.get()) {
+ instance->resetInterrupt(cx);
+ }
+}