%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/builtins/
Upload File :
Create Path :
Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/builtins/wasm-to-js.tq

// Copyright 2023 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

namespace runtime {
extern runtime TierUpWasmToJSWrapper(NoContext, WasmApiFunctionRef): JSAny;
}  // namespace runtime

namespace wasm {
@export
struct WasmToJSResult {
  popCount: intptr;
  result0: intptr;
  result1: intptr;
  result2: float64;
  result3: float64;
}

extern builtin CallVarargs(
    Context,
    JSAny,      // target
    int32,      // number of arguments already on the stack
    int32,      // number of arguments in the FixedArray
    FixedArray  // arguments list
    ): JSAny;

extern builtin IterableToFixedArrayForWasm(Context, JSAny, Smi): FixedArray;

extern macro StackAlignmentInBytes(): intptr;

const kSignatureOffset: constexpr intptr
    generates 'WasmToJSWrapperConstants::kSignatureOffset';

@export
transitioning macro WasmToJSWrapper(ref: WasmApiFunctionRef): WasmToJSResult {
  // Spill the signature on the stack so that it can be read by the GC. This is
  // done in the very beginning before a GC could be triggered.
  // Caller FP + return address.
  const sigSlot = LoadFramePointer() + kSignatureOffset;
  *GetRefAt<intptr>(sigSlot, 0) = BitcastTaggedToWord(ref.sig);
  const sizeOfSig = StackAlignmentInBytes() / torque_internal::SizeOf<intptr>();

  ModifyWasmToJSCounter(1);
  ModifyThreadInWasmFlag(0);
  // Trigger a wrapper tier-up when this function got called often enough.
  dcheck(ref.wrapper_budget > 0);
  ref.wrapper_budget = ref.wrapper_budget - 1;
  if (ref.wrapper_budget == 0) {
    runtime::TierUpWasmToJSWrapper(kNoContext, ref);
  }

  const signaturePod = &ref.sig.bytes;
  const serializedSig = torque_internal::unsafe::NewConstSlice<int32>(
      signaturePod.object, signaturePod.offset,
      signaturePod.length / torque_internal::SizeOf<int32>());
  const returnCount =
      Convert<intptr>(*torque_internal::unsafe::NewReference<int32>(
          serializedSig.object, serializedSig.offset));
  const paramCount: intptr = serializedSig.length - returnCount - 1;
  const returnTypes = Subslice(serializedSig, Convert<intptr>(1), returnCount)
      otherwise unreachable;
  const paramTypes = Subslice(serializedSig, returnCount + 1, paramCount)
      otherwise unreachable;

  // The number of parameters that get pushed on the stack is (at least) the
  // number of incoming parameters plus the receiver.
  const numStackParams = paramCount + 1;
  const outParams = WasmAllocateZeroedFixedArray(numStackParams);
  let nextIndex: intptr = 0;
  // Set the receiver to `Undefined` as the default. If the receiver would be
  // different, e.g. the global proxy for sloppy functions, then the CallVarargs
  // builtin takes care of it automatically
  outParams.objects[nextIndex++] = Undefined;

  // Caller FP + return address + signature.
  const stackParamStart =
      LoadFramePointer() + (2 + sizeOfSig) * torque_internal::SizeOf<intptr>();
  const inParams = torque_internal::unsafe::NewOffHeapReference(
      %RawDownCast<RawPtr<intptr>>(stackParamStart));

  let locationAllocator = LocationAllocatorForParams(inParams);

  let paramIt = paramTypes.Iterator();

  let hasTaggedParams: bool = false;
  while (!paramIt.Empty()) {
    const paramType = paramIt.NextNotEmpty();
    if (paramType == kWasmI32Type) {
      const slot = locationAllocator.GetGPSlot();
      const val = *RefCast<int32>(slot);
      outParams.objects[nextIndex++] = Convert<Number>(val);
    } else if (paramType == kWasmF32Type) {
      const slot = locationAllocator.GetFP32Slot();
      const val = *RefCast<float32>(slot);
      outParams.objects[nextIndex++] = Convert<Number>(val);
    } else if (paramType == kWasmI64Type) {
      if constexpr (Is64()) {
        const slot = locationAllocator.GetGPSlot();
        const val = *slot;
        outParams.objects[nextIndex++] = I64ToBigInt(val);
      } else {
        const lowWordSlot = locationAllocator.GetGPSlot();
        const highWordSlot = locationAllocator.GetGPSlot();
        const lowWord = *lowWordSlot;
        const highWord = *highWordSlot;
        outParams.objects[nextIndex++] = I32PairToBigInt(lowWord, highWord);
      }
    } else if (paramType == kWasmF64Type) {
      const slot = locationAllocator.GetFP64Slot();
      const val = *RefCast<float64>(slot);
      outParams.objects[nextIndex++] = Convert<Number>(val);
    } else {
      nextIndex++;
      hasTaggedParams = true;
    }
  }

  // Second loop for tagged parameters.
  if (hasTaggedParams) {
    locationAllocator.StartRefs();
    nextIndex = 1;
    paramIt = paramTypes.Iterator();
    while (!paramIt.Empty()) {
      const paramType = paramIt.NextNotEmpty();
      const paramKind = paramType & kValueTypeKindBitsMask;
      if (paramKind == ValueKind::kRef || paramKind == ValueKind::kRefNull) {
        const slot = locationAllocator.GetGPSlot();
        const rawRef = *slot;
        const value = BitcastWordToTagged(rawRef);
        outParams.objects[nextIndex] =
            WasmToJSObject(ref.native_context, value, paramType);
      }
      nextIndex++;
    }
  }
  const target = ref.callable;

  const context = ref.native_context;
  // Reset the signature on the stack, so that incoming parameters don't get
  // scanned anymore.
  *GetRefAt<intptr>(sigSlot, 0) = 0;

  const result = CallVarargs(
      context, target, 0, Convert<int32>(numStackParams), outParams);

  // Put a marker on the stack to indicate to the frame iterator that the call
  // to JavaScript is finished. For asm.js source positions it is important to
  // know if an exception happened in the call to JS, or in the ToNumber
  // conversion afterwards.
  *GetRefAt<intptr>(sigSlot, 0) = BitcastTaggedToWord(SmiConstant(-1));
  let resultFixedArray: FixedArray;
  if (returnCount > 1) {
    resultFixedArray =
        IterableToFixedArrayForWasm(context, result, Convert<Smi>(returnCount));
  } else {
    resultFixedArray = kEmptyFixedArray;
  }

  const gpRegSlots = %RawDownCast<RawPtr<intptr>>(StackSlotPtr(
      2 * torque_internal::SizeOf<intptr>(),
      torque_internal::SizeOf<intptr>()));
  const fpRegSlots = %RawDownCast<RawPtr<float64>>(StackSlotPtr(
      2 * torque_internal::SizeOf<float64>(),
      torque_internal::SizeOf<float64>()));
  // The return area on the stack starts right after the stack area.
  const stackSlots =
      locationAllocator.GetAlignedStackEnd(StackAlignmentInBytes());
  locationAllocator =
      LocationAllocatorForReturns(gpRegSlots, fpRegSlots, stackSlots);

  let returnIt = returnTypes.Iterator();
  nextIndex = 0;
  let hasTagged: bool = false;
  while (!returnIt.Empty()) {
    let retVal: JSAny;
    if (returnCount == 1) {
      retVal = result;
    } else {
      retVal = UnsafeCast<JSAny>(resultFixedArray.objects[nextIndex]);
    }
    const retType = returnIt.NextNotEmpty();
    if (retType == kWasmI32Type) {
      let toRef = locationAllocator.GetGPSlot();
      typeswitch (retVal) {
        case (smiVal: Smi): {
          *toRef = Convert<intptr>(Unsigned(SmiToInt32(smiVal)));
        }
        case (heapVal: JSAnyNotSmi): {
          *toRef = Convert<intptr>(Unsigned(WasmTaggedNonSmiToInt32(heapVal)));
        }
      }
    } else if (retType == kWasmF32Type) {
      let toRef = locationAllocator.GetFP32Slot();
      *toRef = Convert<intptr>(Bitcast<uint32>(WasmTaggedToFloat32(retVal)));
    } else if (retType == kWasmF64Type) {
      let toRef = locationAllocator.GetFP64Slot();
      *RefCast<float64>(toRef) = ChangeTaggedToFloat64(retVal);
    } else if (retType == kWasmI64Type) {
      if constexpr (Is64()) {
        let toRef = locationAllocator.GetGPSlot();
        const v = TruncateBigIntToI64(context, retVal);
        *toRef = v;
      } else {
        let toLowRef = locationAllocator.GetGPSlot();
        let toHighRef = locationAllocator.GetGPSlot();
        const bigIntVal = ToBigInt(context, retVal);
        const pair = BigIntToRawBytes(bigIntVal);
        *toLowRef = Signed(pair.low);
        *toHighRef = Signed(pair.high);
      }
    } else {
      const converted = JSToWasmObject(context, ref.instance, retType, retVal);
      let toRef = locationAllocator.GetGPSlot();
      if (returnCount == 1) {
        // There are no other values, we can write the object directly into the
        // result buffer.
        *toRef = BitcastTaggedToWord(converted);
      } else {
        // There may be other parameters that could still trigger a GC when they
        // get transformed. For now we just store the converted value back in
        // the FixedArray.
        hasTagged = true;
        resultFixedArray.objects[nextIndex] = converted;
      }
    }
    nextIndex++;
  }
  if (hasTagged) {
    returnIt = returnTypes.Iterator();
    nextIndex = 0;
    locationAllocator =
        LocationAllocatorForReturns(gpRegSlots, fpRegSlots, stackSlots);
    while (!returnIt.Empty()) {
      const retType = returnIt.NextNotEmpty();
      if (retType == kWasmI32Type) {
        locationAllocator.GetGPSlot();
      } else if (retType == kWasmF32Type) {
        locationAllocator.GetFP32Slot();
      } else if (retType == kWasmF64Type) {
        locationAllocator.GetFP64Slot();
      } else if (retType == kWasmI64Type) {
        if constexpr (Is64()) {
          locationAllocator.GetGPSlot();
        } else {
          locationAllocator.GetGPSlot();
          locationAllocator.GetGPSlot();
        }
      } else {
        let toRef = locationAllocator.GetGPSlot();
        const value = resultFixedArray.objects[nextIndex];
        *toRef = BitcastTaggedToWord(value);
      }
      nextIndex++;
    }
  }

  const popCount =
      (Convert<intptr>(stackSlots) - Convert<intptr>(stackParamStart)) /
          torque_internal::SizeOf<intptr>() +
      sizeOfSig;

  ModifyThreadInWasmFlag(1);
  ModifyWasmToJSCounter(-1);
  return WasmToJSResult{
    popCount: popCount,
    result0: *GetRefAt<intptr>(gpRegSlots, 0),
    result1: *GetRefAt<intptr>(gpRegSlots, torque_internal::SizeOf<intptr>()),
    result2: *GetRefAt<float64>(fpRegSlots, 0),
    result3: *GetRefAt<float64>(fpRegSlots, torque_internal::SizeOf<float64>())
  };
}
}  // namespace wasm

Zerion Mini Shell 1.0