普通文本  |  125行  |  4.86 KB

// Copyright 2017 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.

#include "src/builtins/builtins-utils-gen.h"
#include "src/code-stub-assembler.h"
#include "src/objects-inl.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-opcodes.h"

namespace v8 {
namespace internal {

class WasmBuiltinsAssembler : public CodeStubAssembler {
 public:
  explicit WasmBuiltinsAssembler(compiler::CodeAssemblerState* state)
      : CodeStubAssembler(state) {}

 protected:
  TNode<Object> UncheckedParameter(int index) {
    return UncheckedCast<Object>(Parameter(index));
  }

  TNode<Code> LoadBuiltinFromFrame(Builtins::Name id) {
    TNode<Object> instance = LoadInstanceFromFrame();
    TNode<IntPtrT> roots = UncheckedCast<IntPtrT>(
        Load(MachineType::Pointer(), instance,
             IntPtrConstant(WasmInstanceObject::kRootsArrayAddressOffset -
                            kHeapObjectTag)));
    TNode<Code> target = UncheckedCast<Code>(Load(
        MachineType::TaggedPointer(), roots,
        IntPtrConstant(Heap::roots_to_builtins_offset() + id * kPointerSize)));
    return target;
  }

  TNode<Object> LoadInstanceFromFrame() {
    return UncheckedCast<Object>(
        LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset));
  }

  TNode<Code> LoadCEntryFromInstance(TNode<Object> instance) {
    return UncheckedCast<Code>(
        Load(MachineType::AnyTagged(), instance,
             IntPtrConstant(WasmInstanceObject::kCEntryStubOffset -
                            kHeapObjectTag)));
  }

  TNode<Code> LoadCEntryFromFrame() {
    return LoadCEntryFromInstance(LoadInstanceFromFrame());
  }
};

TF_BUILTIN(WasmAllocateHeapNumber, WasmBuiltinsAssembler) {
  TNode<Code> target = LoadBuiltinFromFrame(Builtins::kAllocateHeapNumber);
  TailCallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant());
}

TF_BUILTIN(WasmArgumentsAdaptor, WasmBuiltinsAssembler) {
  TNode<Object> context = UncheckedParameter(Descriptor::kContext);
  TNode<Object> function = UncheckedParameter(Descriptor::kTarget);
  TNode<Object> new_target = UncheckedParameter(Descriptor::kNewTarget);
  TNode<Object> argc1 = UncheckedParameter(Descriptor::kActualArgumentsCount);
  TNode<Object> argc2 = UncheckedParameter(Descriptor::kExpectedArgumentsCount);
  TNode<Code> target =
      LoadBuiltinFromFrame(Builtins::kArgumentsAdaptorTrampoline);
  TailCallStub(ArgumentAdaptorDescriptor{}, target, context, function,
               new_target, argc1, argc2);
}

TF_BUILTIN(WasmCallJavaScript, WasmBuiltinsAssembler) {
  TNode<Object> context = UncheckedParameter(Descriptor::kContext);
  TNode<Object> function = UncheckedParameter(Descriptor::kFunction);
  TNode<Object> argc = UncheckedParameter(Descriptor::kActualArgumentsCount);
  TNode<Code> target = LoadBuiltinFromFrame(Builtins::kCall_ReceiverIsAny);
  TailCallStub(CallTrampolineDescriptor{}, target, context, function, argc);
}

TF_BUILTIN(WasmToNumber, WasmBuiltinsAssembler) {
  TNode<Object> context = UncheckedParameter(Descriptor::kContext);
  TNode<Object> argument = UncheckedParameter(Descriptor::kArgument);
  TNode<Code> target = LoadBuiltinFromFrame(Builtins::kToNumber);
  TailCallStub(TypeConversionDescriptor(), target, context, argument);
}

TF_BUILTIN(WasmStackGuard, WasmBuiltinsAssembler) {
  TNode<Code> centry = LoadCEntryFromFrame();
  TailCallRuntimeWithCEntry(Runtime::kWasmStackGuard, centry,
                            NoContextConstant());
}

TF_BUILTIN(WasmGrowMemory, WasmBuiltinsAssembler) {
  TNode<Int32T> num_pages =
      UncheckedCast<Int32T>(Parameter(Descriptor::kNumPages));
  Label num_pages_out_of_range(this, Label::kDeferred);

  TNode<BoolT> num_pages_fits_in_smi =
      IsValidPositiveSmi(ChangeInt32ToIntPtr(num_pages));
  GotoIfNot(num_pages_fits_in_smi, &num_pages_out_of_range);

  TNode<Smi> num_pages_smi = SmiFromInt32(num_pages);
  TNode<Object> instance = LoadInstanceFromFrame();
  TNode<Code> centry = LoadCEntryFromInstance(instance);
  TNode<Smi> ret_smi = UncheckedCast<Smi>(
      CallRuntimeWithCEntry(Runtime::kWasmGrowMemory, centry,
                            NoContextConstant(), instance, num_pages_smi));
  TNode<Int32T> ret = SmiToInt32(ret_smi);
  ReturnRaw(ret);

  BIND(&num_pages_out_of_range);
  ReturnRaw(Int32Constant(-1));
}

#define DECLARE_ENUM(name)                                                    \
  TF_BUILTIN(ThrowWasm##name, WasmBuiltinsAssembler) {                        \
    TNode<Code> centry = LoadCEntryFromFrame();                               \
    int message_id = wasm::WasmOpcodes::TrapReasonToMessageId(wasm::k##name); \
    TailCallRuntimeWithCEntry(Runtime::kThrowWasmError, centry,               \
                              NoContextConstant(), SmiConstant(message_id));  \
  }
FOREACH_WASM_TRAPREASON(DECLARE_ENUM)
#undef DECLARE_ENUM

}  // namespace internal
}  // namespace v8