Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/js/src/wasm/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 9 kB image not shown  

Quelle  WasmPI.h   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:
 *
 * 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.
 */


#ifndef wasm_pi_h
#define wasm_pi_h

#include "mozilla/DoublyLinkedList.h"  // for DoublyLinkedListElement

#include "js/TypeDecls.h"
#include "wasm/WasmAnyRef.h"
#include "wasm/WasmTypeDef.h"

// [SMDOC] JS Promise Integration
//
// The API provides relatively efficient and relatively ergonomic interop
// between JavaScript promises and WebAssembly but works under the constraint
// that the only changes are to the JS API and not to the core wasm.
//
// Secondary (suspendable) stacks are introduced at the entrance into the wasm
// code -- a promising function. A suspendable stack can contain/store only
// wasm frames and be part of one activation. If there is a need to execute
// a JS script, the stack must be switched back (to the main stack).
//
// There is a special exit from the suspendable stack where it is expected to
// receive a promise from a JS script -- a suspending function/import. If wasm
// code calls such import, the suspendable stack will be unlinked from
// the current activation allowing the main stack to continue returning to
// the event loop.
//
// Here is a small example that uses JS Promise Integration API:
//
//     const suspending = new WebAssembly.Suspending(async () => 42)
//     const ins = wasmTextEval(`(module
//         (import "" "suspending" (func $imp (result i32)))
//         (func (export "entry") (result i32) (call $imp))
//     )`, {"": { suspending, }})
//     const promising = WebAssembly.promising(ins.exports.entry)
//     assertEq(await promising(), 42)
//
// The states transitions can be described by the following diagram:
//
//               Invoke
//               Promising                Promise
//     +-------+ Export     +----------+  Resolved  +---------+
//     |Initial+----------->|Wasm Logic|<-----------+Suspended|
//     +-------+            ++-+------++            +---------+
//                           | | ^    |Invoke            ^ Suspending Function
//                Return from| | |    |Suspending        | Returns a Promise
//     +--------+ Wasm Call  | | |    |Import       +----+---+
//     |Finished|<-----------+ | |    +------------>|JS Logic|
//     +--------+              | |                  +----+---+
//                +------------+ |                       | Re-entry
//                |Invoke Other  |Return                 +------>
//                |Import     +--+-----+
//                +---------->|JS Logic|
//                            +--------+
//
// The Invoke Promising Export transition creates a suspendable stack,
// switches to it, and continues execution of wasm code there. When the callee
// frame is popped, the promise is returned to the JS caller.
//
// The Invoke Suspending Import switches stack to the main one and sets
// the suspended stack aside. It is expected that the suspending promise
// is returned by JS. The callee returns to the moment the promising call was
// instantiated.
//
// The Return from Wasm Call transition destroys the suspendable stack,
// continues execution on the main stack, and resolves the promising promise
// with the results of the call.
//
// The Promise Resolve transition is invoked when the suspending promise is
// resolved, which wakes the suspendable stack and extends the main one.
// The execution will continue on the suspendable stack that returns the
// resolution values to the wasm code as return values.
//
// The Invoke Other Import transition temporary switches to the main stack and
// invokes the JS code. The suspendable stack will not be removed from the
// chain of frames.
//
// Notice that calling wasm and then invoking a suspendable import from
// the main stack is not allowed. For example, re-exporting $imp, from
// the small example above, and calling it directly from the JS main thread
// will fail.
//
// The `new WebAssembly.Suspending(fn)` logic is implemented in a Wasm module
// generated by `SuspendingFunctionModuleFactory` utility (see WasmPI.cpp).
// The `WebAssembly.promising(wasmfn)` logic is implemented in a Wasm module
// generated by `PromisingFunctionModuleFactory` utility.

namespace js {

class PromiseObject;
class WasmStructObject;

namespace wasm {

class SuspenderContext;
class SuspenderObject;

static const uint32_t SuspenderObjectDataSlot = 0;

enum SuspenderState {
  Initial,
  Moribund,
  Active,
  Suspended,
};

class SuspenderObjectData
    : public mozilla::DoublyLinkedListElement<SuspenderObjectData> {
  void* stackMemory_;

  // Stored main stack FP register.
  void* mainFP_;

  // Stored main stack SP register.
  void* mainSP_;

  // Stored suspendable stack FP register.
  void* suspendableFP_;

  // Stored suspendable stack SP register.
  void* suspendableSP_;

  // Stored suspendable stack exit/bottom frame pointer.
  void* suspendableExitFP_;

  // Stored return address for return to suspendable stack.
  void* suspendedReturnAddress_;

  // Stored main stack exit/top frame pointer.
  void* mainExitFP_;

  SuspenderState state_;

  // Identify context that is holding suspended stack, otherwise nullptr.
  SuspenderContext* suspendedBy_;

#if defined(_WIN32)
  // The storage of main stack limits during stack switching.
  // See updateTibFields and restoreTibFields below.
  void* savedStackBase_;
  void* savedStackLimit_;
#endif

 public:
  explicit SuspenderObjectData(void* stackMemory);

  inline SuspenderState state() const { return state_; }
  void setState(SuspenderState state) { state_ = state; }

  inline bool traceable() const { return suspendedBy_ != nullptr; }
  inline SuspenderContext* suspendedBy() const { return suspendedBy_; }
  void setSuspendedBy(SuspenderContext* suspendedBy) {
    suspendedBy_ = suspendedBy;
  }

  inline void* stackMemory() const { return stackMemory_; }
  inline void* mainFP() const { return mainFP_; }
  inline void* mainSP() const { return mainSP_; }
  inline void* mainExitFP() const { return mainExitFP_; }
  inline void* suspendableFP() const { return suspendableFP_; }
  inline void* suspendableSP() const { return suspendableSP_; }
  inline void* suspendableExitFP() const { return suspendableExitFP_; }
  inline void* suspendedReturnAddress() const {
    return suspendedReturnAddress_;
  }

  void releaseStackMemory();

#if defined(_WIN32)
  void updateTIBStackFields();
  void restoreTIBStackFields();
#endif

#if defined(JS_SIMULATOR_ARM64) || defined(JS_SIMULATOR_ARM)
  void switchSimulatorToMain();
  void switchSimulatorToSuspendable();
#endif

  static constexpr size_t offsetOfMainFP() {
    return offsetof(SuspenderObjectData, mainFP_);
  }

  static constexpr size_t offsetOfMainSP() {
    return offsetof(SuspenderObjectData, mainSP_);
  }

  static constexpr size_t offsetOfSuspendableFP() {
    return offsetof(SuspenderObjectData, suspendableFP_);
  }

  static constexpr size_t offsetOfSuspendableSP() {
    return offsetof(SuspenderObjectData, suspendableSP_);
  }

  static constexpr size_t offsetOfSuspendableExitFP() {
    return offsetof(SuspenderObjectData, suspendableExitFP_);
  }

  static constexpr size_t offsetOfMainExitFP() {
    return offsetof(SuspenderObjectData, mainExitFP_);
  }

  static constexpr size_t offsetOfSuspendedReturnAddress() {
    return offsetof(SuspenderObjectData, suspendedReturnAddress_);
  }
};

#ifdef ENABLE_WASM_JSPI

using CallOnMainStackFn = bool (*)(void* data);
bool CallOnMainStack(JSContext* cx, CallOnMainStackFn fn, void* data);

JSFunction* WasmSuspendingFunctionCreate(JSContext* cx, HandleObject func,
                                         wasm::ValTypeVector&& params,
                                         wasm::ValTypeVector&& results);

JSFunction* WasmSuspendingFunctionCreate(JSContext* cx, HandleObject func,
                                         const FuncType& type);

JSFunction* WasmPromisingFunctionCreate(JSContext* cx, HandleObject func,
                                        wasm::ValTypeVector&& params,
                                        wasm::ValTypeVector&& results);

SuspenderObject* CurrentSuspender(Instance* instance, int reserved);

SuspenderObject* CreateSuspender(Instance* instance, int reserved);

PromiseObject* CreatePromisingPromise(Instance* instance,
                                      SuspenderObject* suspender);

JSObject* GetSuspendingPromiseResult(Instance* instance, void* result,
                                     SuspenderObject* suspender);

void* AddPromiseReactions(Instance* instance, SuspenderObject* suspender,
                          void* result, JSFunction* continueOnSuspendable);

void* ForwardExceptionToSuspended(Instance* instance,
                                  SuspenderObject* suspender, void* exception);

int32_t SetPromisingPromiseResults(Instance* instance,
                                   SuspenderObject* suspender,
                                   WasmStructObject* results);

void UpdateSuspenderState(Instance* instance, SuspenderObject* suspender,
                          UpdateSuspenderStateAction action);

#endif  // ENABLE_WASM_JSPI

}  // namespace wasm
}  // namespace js

#endif  // wasm_pi_h

Messung V0.5
C=68 H=100 G=85

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© 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.