Line data Source code
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:
16 : explicit WasmBuiltinsAssembler(compiler::CodeAssemblerState* state)
17 1344 : : CodeStubAssembler(state) {}
18 :
19 : protected:
20 : TNode<Object> UncheckedParameter(int index) {
21 224 : return UncheckedCast<Object>(Parameter(index));
22 : }
23 :
24 504 : TNode<Code> LoadBuiltinFromFrame(Builtins::Name id) {
25 : TNode<Object> instance = LoadInstanceFromFrame();
26 : TNode<IntPtrT> isolate_root = UncheckedCast<IntPtrT>(
27 : Load(MachineType::Pointer(), instance,
28 : IntPtrConstant(WasmInstanceObject::kIsolateRootOffset -
29 1008 : kHeapObjectTag)));
30 : TNode<Code> target = UncheckedCast<Code>(
31 : Load(MachineType::TaggedPointer(), isolate_root,
32 1008 : IntPtrConstant(IsolateData::builtin_slot_offset(id))));
33 504 : return target;
34 : }
35 :
36 : TNode<Object> LoadInstanceFromFrame() {
37 : return UncheckedCast<Object>(
38 1512 : LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset));
39 : }
40 :
41 840 : TNode<Object> LoadContextFromInstance(TNode<Object> instance) {
42 : return UncheckedCast<Object>(
43 : Load(MachineType::AnyTagged(), instance,
44 : IntPtrConstant(WasmInstanceObject::kNativeContextOffset -
45 1680 : kHeapObjectTag)));
46 : }
47 :
48 1008 : TNode<Code> LoadCEntryFromInstance(TNode<Object> instance) {
49 : return UncheckedCast<Code>(
50 : Load(MachineType::AnyTagged(), instance,
51 : IntPtrConstant(WasmInstanceObject::kCEntryStubOffset -
52 2016 : kHeapObjectTag)));
53 : }
54 : };
55 :
56 224 : TF_BUILTIN(WasmAllocateHeapNumber, WasmBuiltinsAssembler) {
57 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kAllocateHeapNumber);
58 168 : TailCallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant());
59 56 : }
60 :
61 224 : TF_BUILTIN(WasmCallJavaScript, WasmBuiltinsAssembler) {
62 : TNode<Object> context = UncheckedParameter(Descriptor::kContext);
63 : TNode<Object> function = UncheckedParameter(Descriptor::kFunction);
64 : TNode<Object> argc = UncheckedParameter(Descriptor::kActualArgumentsCount);
65 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kCall_ReceiverIsAny);
66 112 : TailCallStub(CallTrampolineDescriptor{}, target, context, function, argc);
67 56 : }
68 :
69 224 : TF_BUILTIN(WasmRecordWrite, WasmBuiltinsAssembler) {
70 : TNode<Object> object = UncheckedParameter(Descriptor::kObject);
71 : TNode<Object> slot = UncheckedParameter(Descriptor::kSlot);
72 : TNode<Object> remembered = UncheckedParameter(Descriptor::kRememberedSet);
73 : TNode<Object> fp_mode = UncheckedParameter(Descriptor::kFPMode);
74 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kRecordWrite);
75 56 : TailCallStub(RecordWriteDescriptor{}, target, NoContextConstant(), object,
76 168 : slot, remembered, fp_mode);
77 56 : }
78 :
79 224 : TF_BUILTIN(WasmToNumber, WasmBuiltinsAssembler) {
80 : TNode<Object> context = UncheckedParameter(Descriptor::kContext);
81 : TNode<Object> argument = UncheckedParameter(Descriptor::kArgument);
82 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kToNumber);
83 112 : TailCallStub(TypeConversionDescriptor(), target, context, argument);
84 56 : }
85 :
86 224 : TF_BUILTIN(WasmStackGuard, WasmBuiltinsAssembler) {
87 56 : TNode<Object> instance = LoadInstanceFromFrame();
88 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
89 56 : TNode<Object> context = LoadContextFromInstance(instance);
90 56 : TailCallRuntimeWithCEntry(Runtime::kWasmStackGuard, centry, context);
91 56 : }
92 :
93 224 : TF_BUILTIN(WasmThrow, WasmBuiltinsAssembler) {
94 56 : TNode<Object> exception = UncheckedParameter(Descriptor::kException);
95 56 : TNode<Object> instance = LoadInstanceFromFrame();
96 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
97 56 : TNode<Object> context = LoadContextFromInstance(instance);
98 56 : TailCallRuntimeWithCEntry(Runtime::kThrow, centry, context, exception);
99 56 : }
100 :
101 224 : TF_BUILTIN(WasmAtomicWake, WasmBuiltinsAssembler) {
102 : TNode<Uint32T> address =
103 : UncheckedCast<Uint32T>(Parameter(Descriptor::kAddress));
104 : TNode<Uint32T> count = UncheckedCast<Uint32T>(Parameter(Descriptor::kCount));
105 :
106 : TNode<Object> instance = LoadInstanceFromFrame();
107 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
108 :
109 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kAllocateHeapNumber);
110 :
111 : // TODO(aseemgarg): Use SMIs if possible for address and count
112 : TNode<HeapNumber> address_heap = UncheckedCast<HeapNumber>(
113 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
114 112 : StoreHeapNumberValue(address_heap, ChangeUint32ToFloat64(address));
115 :
116 : TNode<HeapNumber> count_heap = UncheckedCast<HeapNumber>(
117 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
118 112 : StoreHeapNumberValue(count_heap, ChangeUint32ToFloat64(count));
119 :
120 : TNode<Smi> result_smi = UncheckedCast<Smi>(CallRuntimeWithCEntry(
121 : Runtime::kWasmAtomicWake, centry, NoContextConstant(), instance,
122 112 : address_heap, count_heap));
123 112 : ReturnRaw(SmiToInt32(result_smi));
124 56 : }
125 :
126 224 : TF_BUILTIN(WasmI32AtomicWait, WasmBuiltinsAssembler) {
127 : TNode<Uint32T> address =
128 : UncheckedCast<Uint32T>(Parameter(Descriptor::kAddress));
129 : TNode<Int32T> expected_value =
130 : UncheckedCast<Int32T>(Parameter(Descriptor::kExpectedValue));
131 : TNode<Float64T> timeout =
132 : UncheckedCast<Float64T>(Parameter(Descriptor::kTimeout));
133 :
134 : TNode<Object> instance = LoadInstanceFromFrame();
135 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
136 :
137 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kAllocateHeapNumber);
138 :
139 : // TODO(aseemgarg): Use SMIs if possible for address and expected_value
140 : TNode<HeapNumber> address_heap = UncheckedCast<HeapNumber>(
141 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
142 112 : StoreHeapNumberValue(address_heap, ChangeUint32ToFloat64(address));
143 :
144 : TNode<HeapNumber> expected_value_heap = UncheckedCast<HeapNumber>(
145 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
146 : StoreHeapNumberValue(expected_value_heap,
147 112 : ChangeInt32ToFloat64(expected_value));
148 :
149 : TNode<HeapNumber> timeout_heap = UncheckedCast<HeapNumber>(
150 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
151 56 : StoreHeapNumberValue(timeout_heap, timeout);
152 :
153 : TNode<Smi> result_smi = UncheckedCast<Smi>(CallRuntimeWithCEntry(
154 : Runtime::kWasmI32AtomicWait, centry, NoContextConstant(), instance,
155 112 : address_heap, expected_value_heap, timeout_heap));
156 112 : ReturnRaw(SmiToInt32(result_smi));
157 56 : }
158 :
159 224 : TF_BUILTIN(WasmI64AtomicWait, WasmBuiltinsAssembler) {
160 : TNode<Uint32T> address =
161 : UncheckedCast<Uint32T>(Parameter(Descriptor::kAddress));
162 : TNode<Uint32T> expected_value_high =
163 : UncheckedCast<Uint32T>(Parameter(Descriptor::kExpectedValueHigh));
164 : TNode<Uint32T> expected_value_low =
165 : UncheckedCast<Uint32T>(Parameter(Descriptor::kExpectedValueLow));
166 : TNode<Float64T> timeout =
167 : UncheckedCast<Float64T>(Parameter(Descriptor::kTimeout));
168 :
169 : TNode<Object> instance = LoadInstanceFromFrame();
170 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
171 :
172 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kAllocateHeapNumber);
173 :
174 : // TODO(aseemgarg): Use SMIs if possible for address and expected_value
175 : TNode<HeapNumber> address_heap = UncheckedCast<HeapNumber>(
176 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
177 112 : StoreHeapNumberValue(address_heap, ChangeUint32ToFloat64(address));
178 :
179 : TNode<HeapNumber> expected_value_high_heap = UncheckedCast<HeapNumber>(
180 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
181 : StoreHeapNumberValue(expected_value_high_heap,
182 112 : ChangeUint32ToFloat64(expected_value_high));
183 :
184 : TNode<HeapNumber> expected_value_low_heap = UncheckedCast<HeapNumber>(
185 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
186 : StoreHeapNumberValue(expected_value_low_heap,
187 112 : ChangeUint32ToFloat64(expected_value_low));
188 :
189 : TNode<HeapNumber> timeout_heap = UncheckedCast<HeapNumber>(
190 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
191 56 : StoreHeapNumberValue(timeout_heap, timeout);
192 :
193 : TNode<Smi> result_smi = UncheckedCast<Smi>(CallRuntimeWithCEntry(
194 : Runtime::kWasmI64AtomicWait, centry, NoContextConstant(), instance,
195 : address_heap, expected_value_high_heap, expected_value_low_heap,
196 112 : timeout_heap));
197 112 : ReturnRaw(SmiToInt32(result_smi));
198 56 : }
199 :
200 224 : TF_BUILTIN(WasmMemoryGrow, WasmBuiltinsAssembler) {
201 : TNode<Int32T> num_pages =
202 : UncheckedCast<Int32T>(Parameter(Descriptor::kNumPages));
203 : Label num_pages_out_of_range(this, Label::kDeferred);
204 :
205 : TNode<BoolT> num_pages_fits_in_smi =
206 56 : IsValidPositiveSmi(ChangeInt32ToIntPtr(num_pages));
207 56 : GotoIfNot(num_pages_fits_in_smi, &num_pages_out_of_range);
208 :
209 56 : TNode<Smi> num_pages_smi = SmiFromInt32(num_pages);
210 : TNode<Object> instance = LoadInstanceFromFrame();
211 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
212 56 : TNode<Object> context = LoadContextFromInstance(instance);
213 : TNode<Smi> ret_smi = UncheckedCast<Smi>(CallRuntimeWithCEntry(
214 : Runtime::kWasmMemoryGrow, centry, context, instance, num_pages_smi));
215 56 : TNode<Int32T> ret = SmiToInt32(ret_smi);
216 56 : ReturnRaw(ret);
217 :
218 56 : BIND(&num_pages_out_of_range);
219 112 : ReturnRaw(Int32Constant(-1));
220 56 : }
221 :
222 280 : TF_BUILTIN(BigIntToWasmI64, WasmBuiltinsAssembler) {
223 56 : if (!Is64()) {
224 0 : Unreachable();
225 56 : return;
226 : }
227 :
228 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kI64ToBigInt);
229 : TNode<IntPtrT> argument =
230 : UncheckedCast<IntPtrT>(Parameter(Descriptor::kArgument));
231 :
232 56 : TailCallStub(BigIntToWasmI64Descriptor(), target, NoContextConstant(),
233 112 : argument);
234 : }
235 :
236 336 : TF_BUILTIN(WasmBigIntToI64, WasmBuiltinsAssembler) {
237 56 : if (!Is64()) {
238 0 : Unreachable();
239 56 : return;
240 : }
241 :
242 : TNode<Object> context =
243 : UncheckedCast<Object>(Parameter(Descriptor::kContext));
244 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kBigIntToI64);
245 : TNode<IntPtrT> argument =
246 : UncheckedCast<IntPtrT>(Parameter(Descriptor::kArgument));
247 :
248 56 : TailCallStub(BigIntToI64Descriptor(), target, context, argument);
249 : }
250 :
251 : #define DECLARE_ENUM(name) \
252 : TF_BUILTIN(ThrowWasm##name, WasmBuiltinsAssembler) { \
253 : TNode<Object> instance = LoadInstanceFromFrame(); \
254 : TNode<Code> centry = LoadCEntryFromInstance(instance); \
255 : TNode<Object> context = LoadContextFromInstance(instance); \
256 : MessageTemplate message_id = \
257 : wasm::WasmOpcodes::TrapReasonToMessageId(wasm::k##name); \
258 : TailCallRuntimeWithCEntry(Runtime::kThrowWasmError, centry, context, \
259 : SmiConstant(static_cast<int>(message_id))); \
260 : }
261 3360 : FOREACH_WASM_TRAPREASON(DECLARE_ENUM)
262 : #undef DECLARE_ENUM
263 :
264 : } // namespace internal
265 94089 : } // namespace v8
|