tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }