WasmRealm.cpp (4329B)
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 * 10 * http://www.apache.org/licenses/LICENSE-2.0 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/GlobalObject.h" 22 #include "vm/Realm.h" 23 #include "wasm/WasmDebug.h" 24 #include "wasm/WasmInstance.h" 25 #include "wasm/WasmProcess.h" 26 27 #include "debugger/DebugAPI-inl.h" 28 #include "wasm/WasmInstance-inl.h" 29 30 using namespace js; 31 using namespace wasm; 32 33 wasm::Realm::Realm(JSRuntime* rt) : runtime_(rt) {} 34 35 wasm::Realm::~Realm() { MOZ_ASSERT(instances_.empty()); } 36 37 struct InstanceComparator { 38 const Instance& target; 39 explicit InstanceComparator(const Instance& target) : target(target) {} 40 41 int operator()(const Instance* instance) const { 42 if (instance == &target) { 43 return 0; 44 } 45 return instance < &target ? -1 : 1; 46 } 47 }; 48 49 bool wasm::Realm::registerInstance(JSContext* cx, 50 Handle<WasmInstanceObject*> instanceObj) { 51 MOZ_ASSERT(runtime_ == cx->runtime()); 52 53 Instance& instance = instanceObj->instance(); 54 MOZ_ASSERT(this == &instance.realm()->wasm); 55 56 instance.ensureProfilingLabels(cx->runtime()->geckoProfiler().enabled()); 57 58 if (instance.debugEnabled() && 59 instance.realm()->debuggerObservesAllExecution()) { 60 instance.debug().ensureEnterFrameTrapsState(cx, &instance, true); 61 } 62 63 { 64 if (!instances_.reserve(instances_.length() + 1)) { 65 return false; 66 } 67 68 auto runtimeInstances = cx->runtime()->wasmInstances.lock(); 69 if (!runtimeInstances->reserve(runtimeInstances->length() + 1)) { 70 return false; 71 } 72 73 // To avoid implementing rollback, do not fail after mutations start. 74 75 InstanceComparator cmp(instance); 76 size_t index; 77 78 // The following section is not unsafe, but simulated OOM do not consider 79 // the fact that these insert calls are guarded by the previous reserve 80 // calls. 81 AutoEnterOOMUnsafeRegion oomUnsafe; 82 (void)oomUnsafe; 83 84 MOZ_ALWAYS_FALSE( 85 BinarySearchIf(instances_, 0, instances_.length(), cmp, &index)); 86 MOZ_ALWAYS_TRUE(instances_.insert(instances_.begin() + index, &instance)); 87 88 MOZ_ALWAYS_FALSE(BinarySearchIf(runtimeInstances.get(), 0, 89 runtimeInstances->length(), cmp, &index)); 90 MOZ_ALWAYS_TRUE( 91 runtimeInstances->insert(runtimeInstances->begin() + index, &instance)); 92 } 93 94 // Notify the debugger after wasmInstances is unlocked. 95 DebugAPI::onNewWasmInstance(cx, instanceObj); 96 return true; 97 } 98 99 void wasm::Realm::unregisterInstance(Instance& instance) { 100 InstanceComparator cmp(instance); 101 size_t index; 102 103 if (BinarySearchIf(instances_, 0, instances_.length(), cmp, &index)) { 104 instances_.erase(instances_.begin() + index); 105 } 106 107 auto runtimeInstances = runtime_->wasmInstances.lock(); 108 if (BinarySearchIf(runtimeInstances.get(), 0, runtimeInstances->length(), cmp, 109 &index)) { 110 runtimeInstances->erase(runtimeInstances->begin() + index); 111 } 112 } 113 114 void wasm::Realm::ensureProfilingLabels(bool profilingEnabled) { 115 for (Instance* instance : instances_) { 116 instance->ensureProfilingLabels(profilingEnabled); 117 } 118 } 119 120 void wasm::Realm::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, 121 size_t* realmTables) { 122 *realmTables += instances_.sizeOfExcludingThis(mallocSizeOf); 123 } 124 125 void wasm::InterruptRunningCode(JSContext* cx) { 126 auto runtimeInstances = cx->runtime()->wasmInstances.lock(); 127 for (Instance* instance : runtimeInstances.get()) { 128 instance->setInterrupt(); 129 } 130 } 131 132 void wasm::ResetInterruptState(JSContext* cx) { 133 auto runtimeInstances = cx->runtime()->wasmInstances.lock(); 134 for (Instance* instance : runtimeInstances.get()) { 135 instance->resetInterrupt(); 136 } 137 }