Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  JitActivation.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "vm/JitActivation.h"

#include "mozilla/Assertions.h"  // MOZ_ASSERT, MOZ_RELEASE_ASSERT

#include <stddef.h>  // size_t
#include <stdint.h>  // uint8_t, uint32_t
#include <utility>   // std::move

#include "debugger/DebugAPI.h"        // js::DebugAPI
#include "jit/Invalidation.h"         // js::jit::Invalidate
#include "jit/JSJitFrameIter.h"       // js::jit::InlineFrameIterator
#include "jit/RematerializedFrame.h"  // js::jit::RematerializedFrame
#include "js/AllocPolicy.h"           // js::ReportOutOfMemory
#include "vm/EnvironmentObject.h"     // js::DebugEnvironments
#include "vm/JSContext.h"             // JSContext
#include "vm/Realm.h"                 // js::AutoRealmUnchecked
#include "wasm/WasmCode.h"            // js::wasm::Code
#include "wasm/WasmConstants.h"       // js::wasm::Trap
#include "wasm/WasmFrameIter.h"  // js::wasm::{RegisterState,StartUnwinding,UnwindState}
#include "wasm/WasmInstance.h"  // js::wasm::Instance
#include "wasm/WasmProcess.h"   // js::wasm::LookupCode

#include "vm/Realm-inl.h"  // js::~AutoRealm

class JS_PUBLIC_API JSTracer;

js::jit::JitActivation::JitActivation(JSContext* cx)
    : Activation(cx, Jit),
      packedExitFP_(nullptr),
      encodedWasmExitReason_(0),
      prevJitActivation_(cx->jitActivation),
      ionRecovery_(cx),
      bailoutData_(nullptr),
      lastProfilingFrame_(nullptr),
      lastProfilingCallSite_(nullptr) {
  cx->jitActivation = this;
  registerProfiling();
}

js::jit::JitActivation::~JitActivation() {
  if (isProfiling()) {
    unregisterProfiling();
  }
  cx_->jitActivation = prevJitActivation_;

  // All reocvered value are taken from activation during the bailout.
  MOZ_ASSERT(ionRecovery_.empty());

  // The BailoutFrameInfo should have unregistered itself from the
  // JitActivations.
  MOZ_ASSERT(!bailoutData_);

  // Traps get handled immediately.
  MOZ_ASSERT(!isWasmTrapping());

  // Rematerialized frames must have been removed by either the bailout code or
  // the exception handler.
  MOZ_ASSERT_IF(rematerializedFrames_, rematerializedFrames_->empty());
}

void js::jit::JitActivation::setBailoutData(
    jit::BailoutFrameInfo* bailoutData) {
  MOZ_ASSERT(!bailoutData_);
  bailoutData_ = bailoutData;
}

void js::jit::JitActivation::cleanBailoutData() {
  MOZ_ASSERT(bailoutData_);
  bailoutData_ = nullptr;
}

void js::jit::JitActivation::removeRematerializedFrame(uint8_t* top) {
  if (!rematerializedFrames_) {
    return;
  }

  if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) {
    rematerializedFrames_->remove(p);
  }
}

js::jit::RematerializedFrame* js::jit::JitActivation::getRematerializedFrame(
    JSContext* cx, const JSJitFrameIter& iter, size_t inlineDepth,
    IsLeavingFrame leaving) {
  MOZ_ASSERT(iter.activation() == this);
  MOZ_ASSERT(iter.isIonScripted());

  if (!rematerializedFrames_) {
    rematerializedFrames_ = cx->make_unique<RematerializedFrameTable>(cx);
    if (!rematerializedFrames_) {
      return nullptr;
    }
  }

  uint8_t* top = iter.fp();
  RematerializedFrameTable::AddPtr p = rematerializedFrames_->lookupForAdd(top);
  if (!p) {
    RematerializedFrameVector frames(cx);

    // The unit of rematerialization is an uninlined frame and its inlined
    // frames. Since inlined frames do not exist outside of snapshots, it
    // is impossible to synchronize their rematerialized copies to
    // preserve identity. Therefore, we always rematerialize an uninlined
    // frame and all its inlined frames at once.
    InlineFrameIterator inlineIter(cx, &iter);

    // We can run recover instructions without invalidating if we're always
    // leaving the frame.
    MaybeReadFallback::FallbackConsequence consequence =
        MaybeReadFallback::Fallback_Invalidate;
    if (leaving == IsLeavingFrame::Yes) {
      consequence = MaybeReadFallback::Fallback_DoNothing;
    }
    MaybeReadFallback recover(cx, this, &iter, consequence);

    // Frames are often rematerialized with the cx inside a Debugger's
    // realm. To recover slots and to create CallObjects, we need to
    // be in the script's realm.
    AutoRealmUnchecked ar(cx, iter.script()->realm());

    // The Ion frame must be invalidated to ensure the rematerialized frame will
    // be removed by the bailout code or the exception handler. If we're always
    // leaving the frame, the caller is responsible for cleaning up the
    // rematerialized frame.
    if (leaving == IsLeavingFrame::No && !iter.checkInvalidation()) {
      jit::Invalidate(cx, iter.script());
    }

    if (!RematerializedFrame::RematerializeInlineFrames(cx, top, inlineIter,
                                                        recover, frames)) {
      return nullptr;
    }

    if (!rematerializedFrames_->add(p, top, std::move(frames))) {
      ReportOutOfMemory(cx);
      return nullptr;
    }

    // See comment in unsetPrevUpToDateUntil.
    DebugEnvironments::unsetPrevUpToDateUntil(cx,
                                              p->value()[inlineDepth].get());
  }

  return p->value()[inlineDepth].get();
}

js::jit::RematerializedFrame* js::jit::JitActivation::lookupRematerializedFrame(
    uint8_t* top, size_t inlineDepth) {
  if (!rematerializedFrames_) {
    return nullptr;
  }
  if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) {
    return inlineDepth < p->value().length() ? p->value()[inlineDepth].get()
                                             : nullptr;
  }
  return nullptr;
}

void js::jit::JitActivation::removeRematerializedFramesFromDebugger(
    JSContext* cx, uint8_t* top) {
  // Ion bailout can fail due to overrecursion and OOM. In such cases we
  // cannot honor any further Debugger hooks on the frame, and need to
  // ensure that its Debugger.Frame entry is cleaned up.
  if (!cx->realm()->isDebuggee() || !rematerializedFrames_) {
    return;
  }
  if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) {
    for (uint32_t i = 0; i < p->value().length(); i++) {
      DebugAPI::handleUnrecoverableIonBailoutError(cx, p->value()[i].get());
    }
    rematerializedFrames_->remove(p);
  }
}

void js::jit::JitActivation::traceRematerializedFrames(JSTracer* trc) {
  if (!rematerializedFrames_) {
    return;
  }
  for (RematerializedFrameTable::Enum e(*rematerializedFrames_); !e.empty();
       e.popFront()) {
    e.front().value().trace(trc);
  }
}

bool js::jit::JitActivation::registerIonFrameRecovery(
    RInstructionResults&& results) {
  // Check that there is no entry in the vector yet.
  MOZ_ASSERT(!maybeIonFrameRecovery(results.frame()));
  if (!ionRecovery_.append(std::move(results))) {
    return false;
  }

  return true;
}

js::jit::RInstructionResults* js::jit::JitActivation::maybeIonFrameRecovery(
    JitFrameLayout* fp) {
  for (RInstructionResults* it = ionRecovery_.begin(); it != ionRecovery_.end();
       it++) {
    if (it->frame() == fp) {
      return it;
    }
  }

  return nullptr;
}

void js::jit::JitActivation::removeIonFrameRecovery(JitFrameLayout* fp) {
  RInstructionResults* elem = maybeIonFrameRecovery(fp);
  if (!elem) {
    return;
  }

  ionRecovery_.erase(elem);
}

void js::jit::JitActivation::traceIonRecovery(JSTracer* trc) {
  for (RInstructionResults* it = ionRecovery_.begin(); it != ionRecovery_.end();
       it++) {
    it->trace(trc);
  }
}

void js::jit::JitActivation::startWasmTrap(wasm::Trap trap,
                                           const wasm::TrapSiteDesc& trapDesc,
                                           const wasm::RegisterState& state) {
  MOZ_ASSERT(!isWasmTrapping());

  bool unwound;
  wasm::UnwindState unwindState;
  MOZ_RELEASE_ASSERT(wasm::StartUnwinding(state, &unwindState, &unwound));
  // With return calls, it is possible to not unwind when there is only an
  // entry left on the stack, e.g. the return call trampoline that is created
  // to restore realm before returning to the interpreter entry stub.
  MOZ_ASSERT_IF(unwound, trap == wasm::Trap::IndirectCallBadSig);

  void* pc = unwindState.pc;
  const wasm::Frame* fp = wasm::Frame::fromUntaggedWasmExitFP(unwindState.fp);

  const wasm::Code& code = wasm::GetNearestEffectiveInstance(fp)->code();
  MOZ_RELEASE_ASSERT(&code == wasm::LookupCode(pc));

  setWasmExitFP(fp);
  wasmTrapData_.emplace();
  wasmTrapData_->resumePC =
      ((uint8_t*)state.pc) + jit::WasmTrapInstructionLength;
  wasmTrapData_->unwoundPC = pc;
  wasmTrapData_->trap = trap;
  // If the frame was unwound, the source location must be recovered from the
  // callsite so that it is accurate.
  if (unwound) {
    wasm::CallSite site;
    MOZ_ALWAYS_TRUE(code.lookupCallSite(pc, &site));
    wasmTrapData_->trapSiteDesc.bytecodeOffset =
        wasm::BytecodeOffset(site.lineOrBytecode());
    wasmTrapData_->trapSiteDesc.inlinedCallerOffsets =
        site.inlinedCallerOffsetsVector();
  } else {
    wasmTrapData_->trapSiteDesc = trapDesc;
  }
  wasmTrapData_->failedUnwindSignatureMismatch =
      !unwound && trap == wasm::Trap::IndirectCallBadSig;

  MOZ_ASSERT(isWasmTrapping());
}

void js::jit::JitActivation::finishWasmTrap() {
  MOZ_ASSERT(isWasmTrapping());
  packedExitFP_ = nullptr;
  wasmTrapData_.reset();
  MOZ_ASSERT(!isWasmTrapping());
}

Messung V0.5
C=90 H=94 G=91

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge