1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/builtins/builtins-utils-gen.h"
6 #include "src/code-stub-assembler.h"
7 #include "src/objects-inl.h"
8 #include "src/wasm/wasm-objects.h"
9 #include "src/wasm/wasm-opcodes.h"
10
11 namespace v8 {
12 namespace internal {
13
14 class WasmBuiltinsAssembler : public CodeStubAssembler {
15 public:
WasmBuiltinsAssembler(compiler::CodeAssemblerState * state)16 explicit WasmBuiltinsAssembler(compiler::CodeAssemblerState* state)
17 : CodeStubAssembler(state) {}
18
19 protected:
UncheckedParameter(int index)20 TNode<Object> UncheckedParameter(int index) {
21 return UncheckedCast<Object>(Parameter(index));
22 }
23
LoadBuiltinFromFrame(Builtins::Name id)24 TNode<Code> LoadBuiltinFromFrame(Builtins::Name id) {
25 TNode<Object> instance = LoadInstanceFromFrame();
26 TNode<IntPtrT> roots = UncheckedCast<IntPtrT>(
27 Load(MachineType::Pointer(), instance,
28 IntPtrConstant(WasmInstanceObject::kRootsArrayAddressOffset -
29 kHeapObjectTag)));
30 TNode<Code> target = UncheckedCast<Code>(Load(
31 MachineType::TaggedPointer(), roots,
32 IntPtrConstant(Heap::roots_to_builtins_offset() + id * kPointerSize)));
33 return target;
34 }
35
LoadInstanceFromFrame()36 TNode<Object> LoadInstanceFromFrame() {
37 return UncheckedCast<Object>(
38 LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset));
39 }
40
LoadCEntryFromInstance(TNode<Object> instance)41 TNode<Code> LoadCEntryFromInstance(TNode<Object> instance) {
42 return UncheckedCast<Code>(
43 Load(MachineType::AnyTagged(), instance,
44 IntPtrConstant(WasmInstanceObject::kCEntryStubOffset -
45 kHeapObjectTag)));
46 }
47
LoadCEntryFromFrame()48 TNode<Code> LoadCEntryFromFrame() {
49 return LoadCEntryFromInstance(LoadInstanceFromFrame());
50 }
51 };
52
TF_BUILTIN(WasmAllocateHeapNumber,WasmBuiltinsAssembler)53 TF_BUILTIN(WasmAllocateHeapNumber, WasmBuiltinsAssembler) {
54 TNode<Code> target = LoadBuiltinFromFrame(Builtins::kAllocateHeapNumber);
55 TailCallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant());
56 }
57
TF_BUILTIN(WasmArgumentsAdaptor,WasmBuiltinsAssembler)58 TF_BUILTIN(WasmArgumentsAdaptor, WasmBuiltinsAssembler) {
59 TNode<Object> context = UncheckedParameter(Descriptor::kContext);
60 TNode<Object> function = UncheckedParameter(Descriptor::kTarget);
61 TNode<Object> new_target = UncheckedParameter(Descriptor::kNewTarget);
62 TNode<Object> argc1 = UncheckedParameter(Descriptor::kActualArgumentsCount);
63 TNode<Object> argc2 = UncheckedParameter(Descriptor::kExpectedArgumentsCount);
64 TNode<Code> target =
65 LoadBuiltinFromFrame(Builtins::kArgumentsAdaptorTrampoline);
66 TailCallStub(ArgumentAdaptorDescriptor{}, target, context, function,
67 new_target, argc1, argc2);
68 }
69
TF_BUILTIN(WasmCallJavaScript,WasmBuiltinsAssembler)70 TF_BUILTIN(WasmCallJavaScript, WasmBuiltinsAssembler) {
71 TNode<Object> context = UncheckedParameter(Descriptor::kContext);
72 TNode<Object> function = UncheckedParameter(Descriptor::kFunction);
73 TNode<Object> argc = UncheckedParameter(Descriptor::kActualArgumentsCount);
74 TNode<Code> target = LoadBuiltinFromFrame(Builtins::kCall_ReceiverIsAny);
75 TailCallStub(CallTrampolineDescriptor{}, target, context, function, argc);
76 }
77
TF_BUILTIN(WasmToNumber,WasmBuiltinsAssembler)78 TF_BUILTIN(WasmToNumber, WasmBuiltinsAssembler) {
79 TNode<Object> context = UncheckedParameter(Descriptor::kContext);
80 TNode<Object> argument = UncheckedParameter(Descriptor::kArgument);
81 TNode<Code> target = LoadBuiltinFromFrame(Builtins::kToNumber);
82 TailCallStub(TypeConversionDescriptor(), target, context, argument);
83 }
84
TF_BUILTIN(WasmStackGuard,WasmBuiltinsAssembler)85 TF_BUILTIN(WasmStackGuard, WasmBuiltinsAssembler) {
86 TNode<Code> centry = LoadCEntryFromFrame();
87 TailCallRuntimeWithCEntry(Runtime::kWasmStackGuard, centry,
88 NoContextConstant());
89 }
90
TF_BUILTIN(WasmGrowMemory,WasmBuiltinsAssembler)91 TF_BUILTIN(WasmGrowMemory, WasmBuiltinsAssembler) {
92 TNode<Int32T> num_pages =
93 UncheckedCast<Int32T>(Parameter(Descriptor::kNumPages));
94 Label num_pages_out_of_range(this, Label::kDeferred);
95
96 TNode<BoolT> num_pages_fits_in_smi =
97 IsValidPositiveSmi(ChangeInt32ToIntPtr(num_pages));
98 GotoIfNot(num_pages_fits_in_smi, &num_pages_out_of_range);
99
100 TNode<Smi> num_pages_smi = SmiFromInt32(num_pages);
101 TNode<Object> instance = LoadInstanceFromFrame();
102 TNode<Code> centry = LoadCEntryFromInstance(instance);
103 TNode<Smi> ret_smi = UncheckedCast<Smi>(
104 CallRuntimeWithCEntry(Runtime::kWasmGrowMemory, centry,
105 NoContextConstant(), instance, num_pages_smi));
106 TNode<Int32T> ret = SmiToInt32(ret_smi);
107 ReturnRaw(ret);
108
109 BIND(&num_pages_out_of_range);
110 ReturnRaw(Int32Constant(-1));
111 }
112
113 #define DECLARE_ENUM(name) \
114 TF_BUILTIN(ThrowWasm##name, WasmBuiltinsAssembler) { \
115 TNode<Code> centry = LoadCEntryFromFrame(); \
116 int message_id = wasm::WasmOpcodes::TrapReasonToMessageId(wasm::k##name); \
117 TailCallRuntimeWithCEntry(Runtime::kThrowWasmError, centry, \
118 NoContextConstant(), SmiConstant(message_id)); \
119 }
120 FOREACH_WASM_TRAPREASON(DECLARE_ENUM)
121 #undef DECLARE_ENUM
122
123 } // namespace internal
124 } // namespace v8
125