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 1512 : class WasmBuiltinsAssembler : public CodeStubAssembler {
15 : public:
16 : explicit WasmBuiltinsAssembler(compiler::CodeAssemblerState* state)
17 1512 : : 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 1008 : 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 1680 : LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset));
39 : }
40 :
41 1008 : TNode<Object> LoadContextFromInstance(TNode<Object> instance) {
42 : return UncheckedCast<Object>(
43 : Load(MachineType::AnyTagged(), instance,
44 2016 : IntPtrConstant(WasmInstanceObject::kNativeContextOffset -
45 3024 : kHeapObjectTag)));
46 : }
47 :
48 1176 : TNode<Code> LoadCEntryFromInstance(TNode<Object> instance) {
49 : return UncheckedCast<Code>(
50 : Load(MachineType::AnyTagged(), instance,
51 2352 : IntPtrConstant(WasmInstanceObject::kCEntryStubOffset -
52 3528 : 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 168 : TailCallStub(RecordWriteDescriptor{}, target, NoContextConstant(), object,
76 : 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(WasmStackOverflow, WasmBuiltinsAssembler) {
94 56 : TNode<Object> instance = LoadInstanceFromFrame();
95 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
96 56 : TNode<Object> context = LoadContextFromInstance(instance);
97 56 : TailCallRuntimeWithCEntry(Runtime::kThrowWasmStackOverflow, centry, context);
98 56 : }
99 :
100 224 : TF_BUILTIN(WasmThrow, WasmBuiltinsAssembler) {
101 56 : TNode<Object> exception = UncheckedParameter(Descriptor::kException);
102 56 : TNode<Object> instance = LoadInstanceFromFrame();
103 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
104 56 : TNode<Object> context = LoadContextFromInstance(instance);
105 56 : TailCallRuntimeWithCEntry(Runtime::kThrow, centry, context, exception);
106 56 : }
107 :
108 224 : TF_BUILTIN(WasmAtomicNotify, WasmBuiltinsAssembler) {
109 : TNode<Uint32T> address =
110 : UncheckedCast<Uint32T>(Parameter(Descriptor::kAddress));
111 : TNode<Uint32T> count = UncheckedCast<Uint32T>(Parameter(Descriptor::kCount));
112 :
113 : TNode<Object> instance = LoadInstanceFromFrame();
114 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
115 :
116 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kAllocateHeapNumber);
117 :
118 : // TODO(aseemgarg): Use SMIs if possible for address and count
119 : TNode<HeapNumber> address_heap = UncheckedCast<HeapNumber>(
120 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
121 112 : StoreHeapNumberValue(address_heap, ChangeUint32ToFloat64(address));
122 :
123 : TNode<HeapNumber> count_heap = UncheckedCast<HeapNumber>(
124 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
125 112 : StoreHeapNumberValue(count_heap, ChangeUint32ToFloat64(count));
126 :
127 : TNode<Smi> result_smi = UncheckedCast<Smi>(CallRuntimeWithCEntry(
128 112 : Runtime::kWasmAtomicNotify, centry, NoContextConstant(), instance,
129 : address_heap, count_heap));
130 112 : ReturnRaw(SmiToInt32(result_smi));
131 56 : }
132 :
133 224 : TF_BUILTIN(WasmI32AtomicWait, WasmBuiltinsAssembler) {
134 : TNode<Uint32T> address =
135 : UncheckedCast<Uint32T>(Parameter(Descriptor::kAddress));
136 : TNode<Int32T> expected_value =
137 : UncheckedCast<Int32T>(Parameter(Descriptor::kExpectedValue));
138 : TNode<Float64T> timeout =
139 : UncheckedCast<Float64T>(Parameter(Descriptor::kTimeout));
140 :
141 : TNode<Object> instance = LoadInstanceFromFrame();
142 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
143 :
144 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kAllocateHeapNumber);
145 :
146 : // TODO(aseemgarg): Use SMIs if possible for address and expected_value
147 : TNode<HeapNumber> address_heap = UncheckedCast<HeapNumber>(
148 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
149 112 : StoreHeapNumberValue(address_heap, ChangeUint32ToFloat64(address));
150 :
151 : TNode<HeapNumber> expected_value_heap = UncheckedCast<HeapNumber>(
152 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
153 56 : StoreHeapNumberValue(expected_value_heap,
154 168 : ChangeInt32ToFloat64(expected_value));
155 :
156 : TNode<HeapNumber> timeout_heap = UncheckedCast<HeapNumber>(
157 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
158 56 : StoreHeapNumberValue(timeout_heap, timeout);
159 :
160 : TNode<Smi> result_smi = UncheckedCast<Smi>(CallRuntimeWithCEntry(
161 112 : Runtime::kWasmI32AtomicWait, centry, NoContextConstant(), instance,
162 : address_heap, expected_value_heap, timeout_heap));
163 112 : ReturnRaw(SmiToInt32(result_smi));
164 56 : }
165 :
166 224 : TF_BUILTIN(WasmI64AtomicWait, WasmBuiltinsAssembler) {
167 : TNode<Uint32T> address =
168 : UncheckedCast<Uint32T>(Parameter(Descriptor::kAddress));
169 : TNode<Uint32T> expected_value_high =
170 : UncheckedCast<Uint32T>(Parameter(Descriptor::kExpectedValueHigh));
171 : TNode<Uint32T> expected_value_low =
172 : UncheckedCast<Uint32T>(Parameter(Descriptor::kExpectedValueLow));
173 : TNode<Float64T> timeout =
174 : UncheckedCast<Float64T>(Parameter(Descriptor::kTimeout));
175 :
176 : TNode<Object> instance = LoadInstanceFromFrame();
177 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
178 :
179 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kAllocateHeapNumber);
180 :
181 : // TODO(aseemgarg): Use SMIs if possible for address and expected_value
182 : TNode<HeapNumber> address_heap = UncheckedCast<HeapNumber>(
183 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
184 112 : StoreHeapNumberValue(address_heap, ChangeUint32ToFloat64(address));
185 :
186 : TNode<HeapNumber> expected_value_high_heap = UncheckedCast<HeapNumber>(
187 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
188 56 : StoreHeapNumberValue(expected_value_high_heap,
189 168 : ChangeUint32ToFloat64(expected_value_high));
190 :
191 : TNode<HeapNumber> expected_value_low_heap = UncheckedCast<HeapNumber>(
192 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
193 56 : StoreHeapNumberValue(expected_value_low_heap,
194 168 : ChangeUint32ToFloat64(expected_value_low));
195 :
196 : TNode<HeapNumber> timeout_heap = UncheckedCast<HeapNumber>(
197 168 : CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
198 56 : StoreHeapNumberValue(timeout_heap, timeout);
199 :
200 : TNode<Smi> result_smi = UncheckedCast<Smi>(CallRuntimeWithCEntry(
201 112 : Runtime::kWasmI64AtomicWait, centry, NoContextConstant(), instance,
202 : address_heap, expected_value_high_heap, expected_value_low_heap,
203 : timeout_heap));
204 112 : ReturnRaw(SmiToInt32(result_smi));
205 56 : }
206 :
207 224 : TF_BUILTIN(WasmMemoryGrow, WasmBuiltinsAssembler) {
208 : TNode<Int32T> num_pages =
209 : UncheckedCast<Int32T>(Parameter(Descriptor::kNumPages));
210 56 : Label num_pages_out_of_range(this, Label::kDeferred);
211 :
212 : TNode<BoolT> num_pages_fits_in_smi =
213 56 : IsValidPositiveSmi(ChangeInt32ToIntPtr(num_pages));
214 56 : GotoIfNot(num_pages_fits_in_smi, &num_pages_out_of_range);
215 :
216 56 : TNode<Smi> num_pages_smi = SmiFromInt32(num_pages);
217 : TNode<Object> instance = LoadInstanceFromFrame();
218 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
219 56 : TNode<Object> context = LoadContextFromInstance(instance);
220 : TNode<Smi> ret_smi = UncheckedCast<Smi>(CallRuntimeWithCEntry(
221 : Runtime::kWasmMemoryGrow, centry, context, instance, num_pages_smi));
222 56 : TNode<Int32T> ret = SmiToInt32(ret_smi);
223 56 : ReturnRaw(ret);
224 :
225 56 : BIND(&num_pages_out_of_range);
226 112 : ReturnRaw(Int32Constant(-1));
227 56 : }
228 :
229 280 : TF_BUILTIN(WasmTableGet, WasmBuiltinsAssembler) {
230 : TNode<Int32T> entry_index =
231 : UncheckedCast<Int32T>(Parameter(Descriptor::kEntryIndex));
232 56 : TNode<Object> instance = LoadInstanceFromFrame();
233 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
234 56 : TNode<Object> context = LoadContextFromInstance(instance);
235 56 : Label entry_index_out_of_range(this, Label::kDeferred);
236 :
237 : TNode<BoolT> entry_index_fits_in_smi =
238 56 : IsValidPositiveSmi(ChangeInt32ToIntPtr(entry_index));
239 56 : GotoIfNot(entry_index_fits_in_smi, &entry_index_out_of_range);
240 :
241 56 : TNode<Smi> entry_index_smi = SmiFromInt32(entry_index);
242 : TNode<Smi> table_index_smi =
243 56 : UncheckedCast<Smi>(Parameter(Descriptor::kTableIndex));
244 :
245 : TailCallRuntimeWithCEntry(Runtime::kWasmFunctionTableGet, centry, context,
246 56 : instance, table_index_smi, entry_index_smi);
247 :
248 56 : BIND(&entry_index_out_of_range);
249 : MessageTemplate message_id =
250 56 : wasm::WasmOpcodes::TrapReasonToMessageId(wasm::kTrapTableOutOfBounds);
251 56 : TailCallRuntimeWithCEntry(Runtime::kThrowWasmError, centry, context,
252 56 : SmiConstant(static_cast<int>(message_id)));
253 56 : }
254 :
255 336 : TF_BUILTIN(WasmTableSet, WasmBuiltinsAssembler) {
256 : TNode<Int32T> entry_index =
257 : UncheckedCast<Int32T>(Parameter(Descriptor::kEntryIndex));
258 56 : TNode<Object> instance = LoadInstanceFromFrame();
259 56 : TNode<Code> centry = LoadCEntryFromInstance(instance);
260 56 : TNode<Object> context = LoadContextFromInstance(instance);
261 56 : Label entry_index_out_of_range(this, Label::kDeferred);
262 :
263 : TNode<BoolT> entry_index_fits_in_smi =
264 56 : IsValidPositiveSmi(ChangeInt32ToIntPtr(entry_index));
265 56 : GotoIfNot(entry_index_fits_in_smi, &entry_index_out_of_range);
266 :
267 56 : TNode<Smi> entry_index_smi = SmiFromInt32(entry_index);
268 : TNode<Smi> table_index_smi =
269 56 : UncheckedCast<Smi>(Parameter(Descriptor::kTableIndex));
270 56 : TNode<Object> value = UncheckedCast<Object>(Parameter(Descriptor::kValue));
271 : TailCallRuntimeWithCEntry(Runtime::kWasmFunctionTableSet, centry, context,
272 56 : instance, table_index_smi, entry_index_smi, value);
273 :
274 56 : BIND(&entry_index_out_of_range);
275 : MessageTemplate message_id =
276 56 : wasm::WasmOpcodes::TrapReasonToMessageId(wasm::kTrapTableOutOfBounds);
277 56 : TailCallRuntimeWithCEntry(Runtime::kThrowWasmError, centry, context,
278 56 : SmiConstant(static_cast<int>(message_id)));
279 56 : }
280 :
281 280 : TF_BUILTIN(WasmI64ToBigInt, WasmBuiltinsAssembler) {
282 56 : if (!Is64()) {
283 0 : Unreachable();
284 0 : return;
285 : }
286 :
287 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kI64ToBigInt);
288 : TNode<IntPtrT> argument =
289 : UncheckedCast<IntPtrT>(Parameter(Descriptor::kArgument));
290 :
291 112 : TailCallStub(I64ToBigIntDescriptor(), target, NoContextConstant(), argument);
292 : }
293 :
294 336 : TF_BUILTIN(WasmBigIntToI64, WasmBuiltinsAssembler) {
295 56 : if (!Is64()) {
296 0 : Unreachable();
297 0 : return;
298 : }
299 :
300 : TNode<Object> context =
301 : UncheckedCast<Object>(Parameter(Descriptor::kContext));
302 56 : TNode<Code> target = LoadBuiltinFromFrame(Builtins::kBigIntToI64);
303 : TNode<IntPtrT> argument =
304 : UncheckedCast<IntPtrT>(Parameter(Descriptor::kArgument));
305 :
306 56 : TailCallStub(BigIntToI64Descriptor(), target, context, argument);
307 : }
308 :
309 : #define DECLARE_ENUM(name) \
310 : TF_BUILTIN(ThrowWasm##name, WasmBuiltinsAssembler) { \
311 : TNode<Object> instance = LoadInstanceFromFrame(); \
312 : TNode<Code> centry = LoadCEntryFromInstance(instance); \
313 : TNode<Object> context = LoadContextFromInstance(instance); \
314 : MessageTemplate message_id = \
315 : wasm::WasmOpcodes::TrapReasonToMessageId(wasm::k##name); \
316 : TailCallRuntimeWithCEntry(Runtime::kThrowWasmError, centry, context, \
317 : SmiConstant(static_cast<int>(message_id))); \
318 : }
319 3360 : FOREACH_WASM_TRAPREASON(DECLARE_ENUM)
320 : #undef DECLARE_ENUM
321 :
322 : } // namespace internal
323 59456 : } // namespace v8
|