tor-browser

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

BaselineCompileTask.cpp (4823B)


      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 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "jit/BaselineCompileTask.h"
      8 #include "jit/JitRuntime.h"
      9 #include "jit/JitScript.h"
     10 #include "vm/HelperThreadState.h"
     11 
     12 #include "vm/JSScript-inl.h"
     13 #include "vm/Realm-inl.h"
     14 
     15 using namespace js;
     16 using namespace js::jit;
     17 
     18 void BaselineCompileTask::runHelperThreadTask(
     19    AutoLockHelperThreadState& locked) {
     20  {
     21    AutoUnlockHelperThreadState unlock(locked);
     22    runTask();
     23  }
     24 
     25  FinishOffThreadBaselineCompile(this, locked);
     26 
     27  // Ping the main thread so that the compiled code can be incorporated at
     28  // the next interrupt callback.
     29  runtimeFromAnyThread()->mainContextFromAnyThread()->requestInterrupt(
     30      InterruptReason::AttachOffThreadCompilations);
     31 }
     32 
     33 // Debugging RAII class which marks the current thread as performing
     34 // an offthread baseline compilation.
     35 class MOZ_RAII AutoEnterBaselineBackend {
     36 public:
     37  AutoEnterBaselineBackend() {
     38 #ifdef DEBUG
     39    JitContext* jcx = GetJitContext();
     40    jcx->enterBaselineBackend();
     41 #endif
     42  }
     43 
     44 #ifdef DEBUG
     45  ~AutoEnterBaselineBackend() {
     46    JitContext* jcx = GetJitContext();
     47    jcx->leaveBaselineBackend();
     48  }
     49 #endif
     50 };
     51 
     52 void BaselineCompileTask::markScriptsAsCompiling() {
     53  for (auto* snapshot : snapshots_) {
     54    JSScript* script = snapshot->script();
     55    script->jitScript()->setIsBaselineCompiling(script);
     56  }
     57 }
     58 
     59 bool OffThreadBaselineSnapshot::compileOffThread(TempAllocator& temp,
     60                                                 CompileRealm* realm) {
     61  masm_.emplace(temp, realm);
     62  compiler_.emplace(temp, realm->runtime(), masm_.ref(), this);
     63 
     64  if (!compiler_->init()) {
     65    return false;
     66  }
     67  MethodStatus status = compiler_->compileOffThread();
     68  return status != Method_Error;
     69 }
     70 
     71 void BaselineCompileTask::runTask() {
     72  jit::JitContext jctx(realm_->runtime());
     73  AutoEnterBaselineBackend enter;
     74 
     75  TempAllocator* temp = alloc_->new_<TempAllocator>(alloc_);
     76  if (!temp) {
     77    failed_ = true;
     78    return;
     79  }
     80 
     81  for (auto* snapshot : snapshots_) {
     82    if (!snapshot->compileOffThread(*temp, realm_)) {
     83      failed_ = true;
     84      return;
     85    }
     86  }
     87 }
     88 
     89 /* static */
     90 void BaselineCompileTask::FinishOffThreadTask(BaselineCompileTask* task) {
     91  for (auto* snapshot : task->snapshots_) {
     92    JSScript* script = snapshot->script();
     93    if (script->isBaselineCompilingOffThread()) {
     94      script->jitScript()->clearIsBaselineCompiling(script);
     95    }
     96    snapshot->compiler_.reset();
     97    snapshot->masm_.reset();
     98  }
     99 
    100  // The task is allocated into its LifoAlloc, so destroying that will
    101  // destroy the task and all other data accumulated during compilation.
    102  js_delete(task->alloc_);
    103 }
    104 
    105 void BaselineCompileTask::finishOnMainThread(JSContext* cx) {
    106  AutoRealm ar(cx, firstScript());
    107  for (auto* snapshot : snapshots_) {
    108    if (!snapshot->compiler_->finishCompile(cx)) {
    109      cx->recoverFromOutOfMemory();
    110    }
    111  }
    112 }
    113 
    114 void js::AttachFinishedBaselineCompilations(JSContext* cx,
    115                                            AutoLockHelperThreadState& lock) {
    116  JSRuntime* rt = cx->runtime();
    117 
    118  while (true) {
    119    GlobalHelperThreadState::BaselineCompileTaskVector& finished =
    120        HelperThreadState().baselineFinishedList(lock);
    121 
    122    // Find a finished task for this runtime.
    123    bool found = false;
    124    for (size_t i = 0; i < finished.length(); i++) {
    125      BaselineCompileTask* task = finished[i];
    126      if (task->runtimeFromAnyThread() != rt) {
    127        continue;
    128      }
    129      found = true;
    130 
    131      HelperThreadState().remove(finished, &i);
    132      rt->jitRuntime()->numFinishedOffThreadTasksRef(lock)--;
    133      {
    134        if (!task->failed()) {
    135          AutoUnlockHelperThreadState unlock(lock);
    136          task->finishOnMainThread(cx);
    137        }
    138        BaselineCompileTask::FinishOffThreadTask(task);
    139      }
    140    }
    141    if (!found) {
    142      break;
    143    }
    144  }
    145 }
    146 
    147 void BaselineSnapshot::trace(JSTracer* trc) {
    148  TraceOffthreadGCPtr(trc, script_, "baseline-snapshot-script");
    149  TraceOffthreadGCPtr(trc, globalLexical_, "baseline-snapshot-lexical");
    150  TraceOffthreadGCPtr(trc, globalThis_, "baseline-snapshot-this");
    151  if (callObjectTemplate_) {
    152    TraceOffthreadGCPtr(trc, callObjectTemplate_,
    153                        "baseline-snapshot-call-object-template");
    154  }
    155  if (namedLambdaTemplate_) {
    156    TraceOffthreadGCPtr(trc, namedLambdaTemplate_,
    157                        "baseline-snapshot-named-lambda-template");
    158  }
    159 }
    160 
    161 void BaselineCompileTask::trace(JSTracer* trc) {
    162  if (!realm_->runtime()->runtimeMatches(trc->runtime())) {
    163    return;
    164  }
    165  for (auto* snapshot : snapshots_) {
    166    snapshot->trace(trc);
    167  }
    168 }