1 | // SHA1Hash: da39a3ee5e6b4b0d3255bfef95601890afd80709 |
2 | /* |
3 | * Copyright (C) 2019 Apple Inc. All rights reserved. |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
8 | * |
9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. |
14 | * |
15 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
18 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | |
26 | * Autogenerated from /home/ubuntu/webkit/Source/JavaScriptCore/bytecode/BytecodeList.rb, do not modify. |
27 | */ |
28 | |
29 | #pragma once |
30 | |
31 | #include "ArithProfile.h" |
32 | #include "BytecodeDumper.h" |
33 | #include "BytecodeGenerator.h" |
34 | #include "Fits.h" |
35 | #include "GetByIdMetadata.h" |
36 | #include "Instruction.h" |
37 | #include "Opcode.h" |
38 | #include "PutByIdStatus.h" |
39 | #include "PutByIdFlags.h" |
40 | #include "ToThisStatus.h" |
41 | |
42 | namespace JSC { |
43 | |
44 | struct OpCreateThis : public Instruction { |
45 | static constexpr OpcodeID opcodeID = op_create_this; |
46 | |
47 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity) |
48 | { |
49 | |
50 | auto __metadataID = gen->addMetadataFor(opcodeID); |
51 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, inlineCapacity, __metadataID) |
52 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, callee, inlineCapacity, __metadataID); |
53 | } |
54 | |
55 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
56 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity) |
57 | { |
58 | auto __metadataID = gen->addMetadataFor(opcodeID); |
59 | return emit<size, shouldAssert>(gen, dst, callee, inlineCapacity, __metadataID); |
60 | } |
61 | |
62 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
63 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity, unsigned __metadataID) |
64 | { |
65 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, inlineCapacity, __metadataID); |
66 | if (shouldAssert == Assert) |
67 | ASSERT(didEmit); |
68 | return didEmit; |
69 | } |
70 | |
71 | private: |
72 | template<OpcodeSize size, bool recordOpcode> |
73 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity, unsigned __metadataID) |
74 | { |
75 | if (size == OpcodeSize::Wide) |
76 | gen->alignWideOpcode(); |
77 | if (Fits<unsigned, size>::check(opcodeID) |
78 | && Fits<VirtualRegister, size>::check(dst) |
79 | && Fits<VirtualRegister, size>::check(callee) |
80 | && Fits<unsigned, size>::check(inlineCapacity) |
81 | && Fits<unsigned, size>::check(__metadataID) |
82 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
83 | if (recordOpcode) |
84 | gen->recordOpcode(opcodeID); |
85 | if (size == OpcodeSize::Wide) |
86 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
87 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
88 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
89 | gen->write(Fits<VirtualRegister, size>::convert(callee)); |
90 | gen->write(Fits<unsigned, size>::convert(inlineCapacity)); |
91 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
92 | return true; |
93 | } |
94 | return false; |
95 | } |
96 | |
97 | public: |
98 | template<typename Block> |
99 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
100 | { |
101 | dumper->printLocationAndOp(__location, &"*create_this" [!__isWide]); |
102 | dumper->dumpOperand(m_dst, true); |
103 | dumper->dumpOperand(m_callee, false); |
104 | dumper->dumpOperand(m_inlineCapacity, false); |
105 | } |
106 | |
107 | OpCreateThis(const uint8_t* stream) |
108 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
109 | , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
110 | , m_inlineCapacity(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
111 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
112 | { |
113 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
114 | } |
115 | |
116 | OpCreateThis(const uint32_t* stream) |
117 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
118 | , m_callee(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
119 | , m_inlineCapacity(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
120 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
121 | { |
122 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
123 | } |
124 | |
125 | static OpCreateThis decode(const uint8_t* stream) |
126 | { |
127 | if (*stream != op_wide) |
128 | return { stream }; |
129 | |
130 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
131 | return { wideStream }; |
132 | } |
133 | |
134 | template<typename Functor> |
135 | void setDst(VirtualRegister value, Functor func) |
136 | { |
137 | if (isWide()) |
138 | setDst<OpcodeSize::Wide>(value, func); |
139 | else |
140 | setDst<OpcodeSize::Narrow>(value, func); |
141 | } |
142 | |
143 | template <OpcodeSize size, typename Functor> |
144 | void setDst(VirtualRegister value, Functor func) |
145 | { |
146 | if (!Fits<VirtualRegister, size>::check(value)) |
147 | value = func(); |
148 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
149 | *stream = Fits<VirtualRegister, size>::convert(value); |
150 | } |
151 | |
152 | template<typename Functor> |
153 | void setCallee(VirtualRegister value, Functor func) |
154 | { |
155 | if (isWide()) |
156 | setCallee<OpcodeSize::Wide>(value, func); |
157 | else |
158 | setCallee<OpcodeSize::Narrow>(value, func); |
159 | } |
160 | |
161 | template <OpcodeSize size, typename Functor> |
162 | void setCallee(VirtualRegister value, Functor func) |
163 | { |
164 | if (!Fits<VirtualRegister, size>::check(value)) |
165 | value = func(); |
166 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
167 | *stream = Fits<VirtualRegister, size>::convert(value); |
168 | } |
169 | |
170 | template<typename Functor> |
171 | void setInlineCapacity(unsigned value, Functor func) |
172 | { |
173 | if (isWide()) |
174 | setInlineCapacity<OpcodeSize::Wide>(value, func); |
175 | else |
176 | setInlineCapacity<OpcodeSize::Narrow>(value, func); |
177 | } |
178 | |
179 | template <OpcodeSize size, typename Functor> |
180 | void setInlineCapacity(unsigned value, Functor func) |
181 | { |
182 | if (!Fits<unsigned, size>::check(value)) |
183 | value = func(); |
184 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
185 | *stream = Fits<unsigned, size>::convert(value); |
186 | } |
187 | |
188 | struct Metadata { |
189 | WTF_MAKE_NONCOPYABLE(Metadata); |
190 | |
191 | public: |
192 | Metadata(const OpCreateThis&) { } |
193 | |
194 | WriteBarrier<JSCell> m_cachedCallee; |
195 | }; |
196 | |
197 | Metadata& metadata(CodeBlock* codeBlock) const |
198 | { |
199 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
200 | } |
201 | |
202 | Metadata& metadata(ExecState* exec) const |
203 | { |
204 | return metadata(exec->codeBlock()); |
205 | } |
206 | |
207 | VirtualRegister m_dst; |
208 | VirtualRegister m_callee; |
209 | unsigned m_inlineCapacity; |
210 | unsigned m_metadataID; |
211 | }; |
212 | |
213 | struct OpGetArgument : public Instruction { |
214 | static constexpr OpcodeID opcodeID = op_get_argument; |
215 | |
216 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, int index) |
217 | { |
218 | |
219 | auto __metadataID = gen->addMetadataFor(opcodeID); |
220 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, index, __metadataID) |
221 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, index, __metadataID); |
222 | } |
223 | |
224 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
225 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, int index) |
226 | { |
227 | auto __metadataID = gen->addMetadataFor(opcodeID); |
228 | return emit<size, shouldAssert>(gen, dst, index, __metadataID); |
229 | } |
230 | |
231 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
232 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, int index, unsigned __metadataID) |
233 | { |
234 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, index, __metadataID); |
235 | if (shouldAssert == Assert) |
236 | ASSERT(didEmit); |
237 | return didEmit; |
238 | } |
239 | |
240 | private: |
241 | template<OpcodeSize size, bool recordOpcode> |
242 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, int index, unsigned __metadataID) |
243 | { |
244 | if (size == OpcodeSize::Wide) |
245 | gen->alignWideOpcode(); |
246 | if (Fits<unsigned, size>::check(opcodeID) |
247 | && Fits<VirtualRegister, size>::check(dst) |
248 | && Fits<int, size>::check(index) |
249 | && Fits<unsigned, size>::check(__metadataID) |
250 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
251 | if (recordOpcode) |
252 | gen->recordOpcode(opcodeID); |
253 | if (size == OpcodeSize::Wide) |
254 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
255 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
256 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
257 | gen->write(Fits<int, size>::convert(index)); |
258 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
259 | return true; |
260 | } |
261 | return false; |
262 | } |
263 | |
264 | public: |
265 | template<typename Block> |
266 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
267 | { |
268 | dumper->printLocationAndOp(__location, &"*get_argument" [!__isWide]); |
269 | dumper->dumpOperand(m_dst, true); |
270 | dumper->dumpOperand(m_index, false); |
271 | } |
272 | |
273 | OpGetArgument(const uint8_t* stream) |
274 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
275 | , m_index(Fits<int, OpcodeSize::Narrow>::convert(stream[2])) |
276 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
277 | { |
278 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
279 | } |
280 | |
281 | OpGetArgument(const uint32_t* stream) |
282 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
283 | , m_index(Fits<int, OpcodeSize::Wide>::convert(stream[2])) |
284 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
285 | { |
286 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
287 | } |
288 | |
289 | static OpGetArgument decode(const uint8_t* stream) |
290 | { |
291 | if (*stream != op_wide) |
292 | return { stream }; |
293 | |
294 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
295 | return { wideStream }; |
296 | } |
297 | |
298 | template<typename Functor> |
299 | void setDst(VirtualRegister value, Functor func) |
300 | { |
301 | if (isWide()) |
302 | setDst<OpcodeSize::Wide>(value, func); |
303 | else |
304 | setDst<OpcodeSize::Narrow>(value, func); |
305 | } |
306 | |
307 | template <OpcodeSize size, typename Functor> |
308 | void setDst(VirtualRegister value, Functor func) |
309 | { |
310 | if (!Fits<VirtualRegister, size>::check(value)) |
311 | value = func(); |
312 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
313 | *stream = Fits<VirtualRegister, size>::convert(value); |
314 | } |
315 | |
316 | template<typename Functor> |
317 | void setIndex(int value, Functor func) |
318 | { |
319 | if (isWide()) |
320 | setIndex<OpcodeSize::Wide>(value, func); |
321 | else |
322 | setIndex<OpcodeSize::Narrow>(value, func); |
323 | } |
324 | |
325 | template <OpcodeSize size, typename Functor> |
326 | void setIndex(int value, Functor func) |
327 | { |
328 | if (!Fits<int, size>::check(value)) |
329 | value = func(); |
330 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
331 | *stream = Fits<int, size>::convert(value); |
332 | } |
333 | |
334 | struct Metadata { |
335 | WTF_MAKE_NONCOPYABLE(Metadata); |
336 | |
337 | public: |
338 | Metadata(const OpGetArgument&) { } |
339 | |
340 | ValueProfile m_profile; |
341 | }; |
342 | |
343 | Metadata& metadata(CodeBlock* codeBlock) const |
344 | { |
345 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
346 | } |
347 | |
348 | Metadata& metadata(ExecState* exec) const |
349 | { |
350 | return metadata(exec->codeBlock()); |
351 | } |
352 | |
353 | VirtualRegister m_dst; |
354 | int m_index; |
355 | unsigned m_metadataID; |
356 | }; |
357 | |
358 | struct OpToThis : public Instruction { |
359 | static constexpr OpcodeID opcodeID = op_to_this; |
360 | |
361 | static void emit(BytecodeGenerator* gen, VirtualRegister srcDst) |
362 | { |
363 | |
364 | auto __metadataID = gen->addMetadataFor(opcodeID); |
365 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, srcDst, __metadataID) |
366 | || emit<OpcodeSize::Wide, Assert, true>(gen, srcDst, __metadataID); |
367 | } |
368 | |
369 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
370 | static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst) |
371 | { |
372 | auto __metadataID = gen->addMetadataFor(opcodeID); |
373 | return emit<size, shouldAssert>(gen, srcDst, __metadataID); |
374 | } |
375 | |
376 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
377 | static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned __metadataID) |
378 | { |
379 | bool didEmit = emitImpl<size, recordOpcode>(gen, srcDst, __metadataID); |
380 | if (shouldAssert == Assert) |
381 | ASSERT(didEmit); |
382 | return didEmit; |
383 | } |
384 | |
385 | private: |
386 | template<OpcodeSize size, bool recordOpcode> |
387 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned __metadataID) |
388 | { |
389 | if (size == OpcodeSize::Wide) |
390 | gen->alignWideOpcode(); |
391 | if (Fits<unsigned, size>::check(opcodeID) |
392 | && Fits<VirtualRegister, size>::check(srcDst) |
393 | && Fits<unsigned, size>::check(__metadataID) |
394 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
395 | if (recordOpcode) |
396 | gen->recordOpcode(opcodeID); |
397 | if (size == OpcodeSize::Wide) |
398 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
399 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
400 | gen->write(Fits<VirtualRegister, size>::convert(srcDst)); |
401 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
402 | return true; |
403 | } |
404 | return false; |
405 | } |
406 | |
407 | public: |
408 | template<typename Block> |
409 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
410 | { |
411 | dumper->printLocationAndOp(__location, &"*to_this" [!__isWide]); |
412 | dumper->dumpOperand(m_srcDst, true); |
413 | } |
414 | |
415 | OpToThis(const uint8_t* stream) |
416 | : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
417 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2])) |
418 | { |
419 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
420 | } |
421 | |
422 | OpToThis(const uint32_t* stream) |
423 | : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
424 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[2])) |
425 | { |
426 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
427 | } |
428 | |
429 | static OpToThis decode(const uint8_t* stream) |
430 | { |
431 | if (*stream != op_wide) |
432 | return { stream }; |
433 | |
434 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
435 | return { wideStream }; |
436 | } |
437 | |
438 | template<typename Functor> |
439 | void setSrcDst(VirtualRegister value, Functor func) |
440 | { |
441 | if (isWide()) |
442 | setSrcDst<OpcodeSize::Wide>(value, func); |
443 | else |
444 | setSrcDst<OpcodeSize::Narrow>(value, func); |
445 | } |
446 | |
447 | template <OpcodeSize size, typename Functor> |
448 | void setSrcDst(VirtualRegister value, Functor func) |
449 | { |
450 | if (!Fits<VirtualRegister, size>::check(value)) |
451 | value = func(); |
452 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
453 | *stream = Fits<VirtualRegister, size>::convert(value); |
454 | } |
455 | |
456 | struct Metadata { |
457 | WTF_MAKE_NONCOPYABLE(Metadata); |
458 | |
459 | public: |
460 | Metadata(const OpToThis&) { } |
461 | |
462 | WriteBarrierBase<Structure> m_cachedStructure; |
463 | ToThisStatus m_toThisStatus; |
464 | ValueProfile m_profile; |
465 | }; |
466 | |
467 | Metadata& metadata(CodeBlock* codeBlock) const |
468 | { |
469 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
470 | } |
471 | |
472 | Metadata& metadata(ExecState* exec) const |
473 | { |
474 | return metadata(exec->codeBlock()); |
475 | } |
476 | |
477 | VirtualRegister m_srcDst; |
478 | unsigned m_metadataID; |
479 | }; |
480 | |
481 | struct OpNewObject : public Instruction { |
482 | static constexpr OpcodeID opcodeID = op_new_object; |
483 | |
484 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity) |
485 | { |
486 | |
487 | auto __metadataID = gen->addMetadataFor(opcodeID); |
488 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, inlineCapacity, __metadataID) |
489 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, inlineCapacity, __metadataID); |
490 | } |
491 | |
492 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
493 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity) |
494 | { |
495 | auto __metadataID = gen->addMetadataFor(opcodeID); |
496 | return emit<size, shouldAssert>(gen, dst, inlineCapacity, __metadataID); |
497 | } |
498 | |
499 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
500 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity, unsigned __metadataID) |
501 | { |
502 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, inlineCapacity, __metadataID); |
503 | if (shouldAssert == Assert) |
504 | ASSERT(didEmit); |
505 | return didEmit; |
506 | } |
507 | |
508 | private: |
509 | template<OpcodeSize size, bool recordOpcode> |
510 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity, unsigned __metadataID) |
511 | { |
512 | if (size == OpcodeSize::Wide) |
513 | gen->alignWideOpcode(); |
514 | if (Fits<unsigned, size>::check(opcodeID) |
515 | && Fits<VirtualRegister, size>::check(dst) |
516 | && Fits<unsigned, size>::check(inlineCapacity) |
517 | && Fits<unsigned, size>::check(__metadataID) |
518 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
519 | if (recordOpcode) |
520 | gen->recordOpcode(opcodeID); |
521 | if (size == OpcodeSize::Wide) |
522 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
523 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
524 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
525 | gen->write(Fits<unsigned, size>::convert(inlineCapacity)); |
526 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
527 | return true; |
528 | } |
529 | return false; |
530 | } |
531 | |
532 | public: |
533 | template<typename Block> |
534 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
535 | { |
536 | dumper->printLocationAndOp(__location, &"*new_object" [!__isWide]); |
537 | dumper->dumpOperand(m_dst, true); |
538 | dumper->dumpOperand(m_inlineCapacity, false); |
539 | } |
540 | |
541 | OpNewObject(const uint8_t* stream) |
542 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
543 | , m_inlineCapacity(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2])) |
544 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
545 | { |
546 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
547 | } |
548 | |
549 | OpNewObject(const uint32_t* stream) |
550 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
551 | , m_inlineCapacity(Fits<unsigned, OpcodeSize::Wide>::convert(stream[2])) |
552 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
553 | { |
554 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
555 | } |
556 | |
557 | static OpNewObject decode(const uint8_t* stream) |
558 | { |
559 | if (*stream != op_wide) |
560 | return { stream }; |
561 | |
562 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
563 | return { wideStream }; |
564 | } |
565 | |
566 | template<typename Functor> |
567 | void setDst(VirtualRegister value, Functor func) |
568 | { |
569 | if (isWide()) |
570 | setDst<OpcodeSize::Wide>(value, func); |
571 | else |
572 | setDst<OpcodeSize::Narrow>(value, func); |
573 | } |
574 | |
575 | template <OpcodeSize size, typename Functor> |
576 | void setDst(VirtualRegister value, Functor func) |
577 | { |
578 | if (!Fits<VirtualRegister, size>::check(value)) |
579 | value = func(); |
580 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
581 | *stream = Fits<VirtualRegister, size>::convert(value); |
582 | } |
583 | |
584 | template<typename Functor> |
585 | void setInlineCapacity(unsigned value, Functor func) |
586 | { |
587 | if (isWide()) |
588 | setInlineCapacity<OpcodeSize::Wide>(value, func); |
589 | else |
590 | setInlineCapacity<OpcodeSize::Narrow>(value, func); |
591 | } |
592 | |
593 | template <OpcodeSize size, typename Functor> |
594 | void setInlineCapacity(unsigned value, Functor func) |
595 | { |
596 | if (!Fits<unsigned, size>::check(value)) |
597 | value = func(); |
598 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
599 | *stream = Fits<unsigned, size>::convert(value); |
600 | } |
601 | |
602 | struct Metadata { |
603 | WTF_MAKE_NONCOPYABLE(Metadata); |
604 | |
605 | public: |
606 | Metadata(const OpNewObject&) { } |
607 | |
608 | ObjectAllocationProfile m_objectAllocationProfile; |
609 | }; |
610 | |
611 | Metadata& metadata(CodeBlock* codeBlock) const |
612 | { |
613 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
614 | } |
615 | |
616 | Metadata& metadata(ExecState* exec) const |
617 | { |
618 | return metadata(exec->codeBlock()); |
619 | } |
620 | |
621 | VirtualRegister m_dst; |
622 | unsigned m_inlineCapacity; |
623 | unsigned m_metadataID; |
624 | }; |
625 | |
626 | struct OpNewArray : public Instruction { |
627 | static constexpr OpcodeID opcodeID = op_new_array; |
628 | |
629 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType) |
630 | { |
631 | |
632 | auto __metadataID = gen->addMetadataFor(opcodeID); |
633 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, argv, argc, recommendedIndexingType, __metadataID) |
634 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, argv, argc, recommendedIndexingType, __metadataID); |
635 | } |
636 | |
637 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
638 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType) |
639 | { |
640 | auto __metadataID = gen->addMetadataFor(opcodeID); |
641 | return emit<size, shouldAssert>(gen, dst, argv, argc, recommendedIndexingType, __metadataID); |
642 | } |
643 | |
644 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
645 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType, unsigned __metadataID) |
646 | { |
647 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, argv, argc, recommendedIndexingType, __metadataID); |
648 | if (shouldAssert == Assert) |
649 | ASSERT(didEmit); |
650 | return didEmit; |
651 | } |
652 | |
653 | private: |
654 | template<OpcodeSize size, bool recordOpcode> |
655 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType, unsigned __metadataID) |
656 | { |
657 | if (size == OpcodeSize::Wide) |
658 | gen->alignWideOpcode(); |
659 | if (Fits<unsigned, size>::check(opcodeID) |
660 | && Fits<VirtualRegister, size>::check(dst) |
661 | && Fits<VirtualRegister, size>::check(argv) |
662 | && Fits<unsigned, size>::check(argc) |
663 | && Fits<IndexingType, size>::check(recommendedIndexingType) |
664 | && Fits<unsigned, size>::check(__metadataID) |
665 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
666 | if (recordOpcode) |
667 | gen->recordOpcode(opcodeID); |
668 | if (size == OpcodeSize::Wide) |
669 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
670 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
671 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
672 | gen->write(Fits<VirtualRegister, size>::convert(argv)); |
673 | gen->write(Fits<unsigned, size>::convert(argc)); |
674 | gen->write(Fits<IndexingType, size>::convert(recommendedIndexingType)); |
675 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
676 | return true; |
677 | } |
678 | return false; |
679 | } |
680 | |
681 | public: |
682 | template<typename Block> |
683 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
684 | { |
685 | dumper->printLocationAndOp(__location, &"*new_array" [!__isWide]); |
686 | dumper->dumpOperand(m_dst, true); |
687 | dumper->dumpOperand(m_argv, false); |
688 | dumper->dumpOperand(m_argc, false); |
689 | dumper->dumpOperand(m_recommendedIndexingType, false); |
690 | } |
691 | |
692 | OpNewArray(const uint8_t* stream) |
693 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
694 | , m_argv(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
695 | , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
696 | , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Narrow>::convert(stream[4])) |
697 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
698 | { |
699 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
700 | } |
701 | |
702 | OpNewArray(const uint32_t* stream) |
703 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
704 | , m_argv(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
705 | , m_argc(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
706 | , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Wide>::convert(stream[4])) |
707 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
708 | { |
709 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
710 | } |
711 | |
712 | static OpNewArray decode(const uint8_t* stream) |
713 | { |
714 | if (*stream != op_wide) |
715 | return { stream }; |
716 | |
717 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
718 | return { wideStream }; |
719 | } |
720 | |
721 | template<typename Functor> |
722 | void setDst(VirtualRegister value, Functor func) |
723 | { |
724 | if (isWide()) |
725 | setDst<OpcodeSize::Wide>(value, func); |
726 | else |
727 | setDst<OpcodeSize::Narrow>(value, func); |
728 | } |
729 | |
730 | template <OpcodeSize size, typename Functor> |
731 | void setDst(VirtualRegister value, Functor func) |
732 | { |
733 | if (!Fits<VirtualRegister, size>::check(value)) |
734 | value = func(); |
735 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
736 | *stream = Fits<VirtualRegister, size>::convert(value); |
737 | } |
738 | |
739 | template<typename Functor> |
740 | void setArgv(VirtualRegister value, Functor func) |
741 | { |
742 | if (isWide()) |
743 | setArgv<OpcodeSize::Wide>(value, func); |
744 | else |
745 | setArgv<OpcodeSize::Narrow>(value, func); |
746 | } |
747 | |
748 | template <OpcodeSize size, typename Functor> |
749 | void setArgv(VirtualRegister value, Functor func) |
750 | { |
751 | if (!Fits<VirtualRegister, size>::check(value)) |
752 | value = func(); |
753 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
754 | *stream = Fits<VirtualRegister, size>::convert(value); |
755 | } |
756 | |
757 | template<typename Functor> |
758 | void setArgc(unsigned value, Functor func) |
759 | { |
760 | if (isWide()) |
761 | setArgc<OpcodeSize::Wide>(value, func); |
762 | else |
763 | setArgc<OpcodeSize::Narrow>(value, func); |
764 | } |
765 | |
766 | template <OpcodeSize size, typename Functor> |
767 | void setArgc(unsigned value, Functor func) |
768 | { |
769 | if (!Fits<unsigned, size>::check(value)) |
770 | value = func(); |
771 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
772 | *stream = Fits<unsigned, size>::convert(value); |
773 | } |
774 | |
775 | template<typename Functor> |
776 | void setRecommendedIndexingType(IndexingType value, Functor func) |
777 | { |
778 | if (isWide()) |
779 | setRecommendedIndexingType<OpcodeSize::Wide>(value, func); |
780 | else |
781 | setRecommendedIndexingType<OpcodeSize::Narrow>(value, func); |
782 | } |
783 | |
784 | template <OpcodeSize size, typename Functor> |
785 | void setRecommendedIndexingType(IndexingType value, Functor func) |
786 | { |
787 | if (!Fits<IndexingType, size>::check(value)) |
788 | value = func(); |
789 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
790 | *stream = Fits<IndexingType, size>::convert(value); |
791 | } |
792 | |
793 | struct Metadata { |
794 | WTF_MAKE_NONCOPYABLE(Metadata); |
795 | |
796 | public: |
797 | Metadata(const OpNewArray&) { } |
798 | |
799 | ArrayAllocationProfile m_arrayAllocationProfile; |
800 | }; |
801 | |
802 | Metadata& metadata(CodeBlock* codeBlock) const |
803 | { |
804 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
805 | } |
806 | |
807 | Metadata& metadata(ExecState* exec) const |
808 | { |
809 | return metadata(exec->codeBlock()); |
810 | } |
811 | |
812 | VirtualRegister m_dst; |
813 | VirtualRegister m_argv; |
814 | unsigned m_argc; |
815 | IndexingType m_recommendedIndexingType; |
816 | unsigned m_metadataID; |
817 | }; |
818 | |
819 | struct OpNewArrayWithSize : public Instruction { |
820 | static constexpr OpcodeID opcodeID = op_new_array_with_size; |
821 | |
822 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length) |
823 | { |
824 | |
825 | auto __metadataID = gen->addMetadataFor(opcodeID); |
826 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, length, __metadataID) |
827 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, length, __metadataID); |
828 | } |
829 | |
830 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
831 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length) |
832 | { |
833 | auto __metadataID = gen->addMetadataFor(opcodeID); |
834 | return emit<size, shouldAssert>(gen, dst, length, __metadataID); |
835 | } |
836 | |
837 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
838 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length, unsigned __metadataID) |
839 | { |
840 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, length, __metadataID); |
841 | if (shouldAssert == Assert) |
842 | ASSERT(didEmit); |
843 | return didEmit; |
844 | } |
845 | |
846 | private: |
847 | template<OpcodeSize size, bool recordOpcode> |
848 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length, unsigned __metadataID) |
849 | { |
850 | if (size == OpcodeSize::Wide) |
851 | gen->alignWideOpcode(); |
852 | if (Fits<unsigned, size>::check(opcodeID) |
853 | && Fits<VirtualRegister, size>::check(dst) |
854 | && Fits<VirtualRegister, size>::check(length) |
855 | && Fits<unsigned, size>::check(__metadataID) |
856 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
857 | if (recordOpcode) |
858 | gen->recordOpcode(opcodeID); |
859 | if (size == OpcodeSize::Wide) |
860 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
861 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
862 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
863 | gen->write(Fits<VirtualRegister, size>::convert(length)); |
864 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
865 | return true; |
866 | } |
867 | return false; |
868 | } |
869 | |
870 | public: |
871 | template<typename Block> |
872 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
873 | { |
874 | dumper->printLocationAndOp(__location, &"*new_array_with_size" [!__isWide]); |
875 | dumper->dumpOperand(m_dst, true); |
876 | dumper->dumpOperand(m_length, false); |
877 | } |
878 | |
879 | OpNewArrayWithSize(const uint8_t* stream) |
880 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
881 | , m_length(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
882 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
883 | { |
884 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
885 | } |
886 | |
887 | OpNewArrayWithSize(const uint32_t* stream) |
888 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
889 | , m_length(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
890 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
891 | { |
892 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
893 | } |
894 | |
895 | static OpNewArrayWithSize decode(const uint8_t* stream) |
896 | { |
897 | if (*stream != op_wide) |
898 | return { stream }; |
899 | |
900 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
901 | return { wideStream }; |
902 | } |
903 | |
904 | template<typename Functor> |
905 | void setDst(VirtualRegister value, Functor func) |
906 | { |
907 | if (isWide()) |
908 | setDst<OpcodeSize::Wide>(value, func); |
909 | else |
910 | setDst<OpcodeSize::Narrow>(value, func); |
911 | } |
912 | |
913 | template <OpcodeSize size, typename Functor> |
914 | void setDst(VirtualRegister value, Functor func) |
915 | { |
916 | if (!Fits<VirtualRegister, size>::check(value)) |
917 | value = func(); |
918 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
919 | *stream = Fits<VirtualRegister, size>::convert(value); |
920 | } |
921 | |
922 | template<typename Functor> |
923 | void setLength(VirtualRegister value, Functor func) |
924 | { |
925 | if (isWide()) |
926 | setLength<OpcodeSize::Wide>(value, func); |
927 | else |
928 | setLength<OpcodeSize::Narrow>(value, func); |
929 | } |
930 | |
931 | template <OpcodeSize size, typename Functor> |
932 | void setLength(VirtualRegister value, Functor func) |
933 | { |
934 | if (!Fits<VirtualRegister, size>::check(value)) |
935 | value = func(); |
936 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
937 | *stream = Fits<VirtualRegister, size>::convert(value); |
938 | } |
939 | |
940 | struct Metadata { |
941 | WTF_MAKE_NONCOPYABLE(Metadata); |
942 | |
943 | public: |
944 | Metadata(const OpNewArrayWithSize&) { } |
945 | |
946 | ArrayAllocationProfile m_arrayAllocationProfile; |
947 | }; |
948 | |
949 | Metadata& metadata(CodeBlock* codeBlock) const |
950 | { |
951 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
952 | } |
953 | |
954 | Metadata& metadata(ExecState* exec) const |
955 | { |
956 | return metadata(exec->codeBlock()); |
957 | } |
958 | |
959 | VirtualRegister m_dst; |
960 | VirtualRegister m_length; |
961 | unsigned m_metadataID; |
962 | }; |
963 | |
964 | struct OpNewArrayBuffer : public Instruction { |
965 | static constexpr OpcodeID opcodeID = op_new_array_buffer; |
966 | |
967 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType) |
968 | { |
969 | |
970 | auto __metadataID = gen->addMetadataFor(opcodeID); |
971 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID) |
972 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID); |
973 | } |
974 | |
975 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
976 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType) |
977 | { |
978 | auto __metadataID = gen->addMetadataFor(opcodeID); |
979 | return emit<size, shouldAssert>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID); |
980 | } |
981 | |
982 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
983 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType, unsigned __metadataID) |
984 | { |
985 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID); |
986 | if (shouldAssert == Assert) |
987 | ASSERT(didEmit); |
988 | return didEmit; |
989 | } |
990 | |
991 | private: |
992 | template<OpcodeSize size, bool recordOpcode> |
993 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType, unsigned __metadataID) |
994 | { |
995 | if (size == OpcodeSize::Wide) |
996 | gen->alignWideOpcode(); |
997 | if (Fits<unsigned, size>::check(opcodeID) |
998 | && Fits<VirtualRegister, size>::check(dst) |
999 | && Fits<VirtualRegister, size>::check(immutableButterfly) |
1000 | && Fits<IndexingType, size>::check(recommendedIndexingType) |
1001 | && Fits<unsigned, size>::check(__metadataID) |
1002 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
1003 | if (recordOpcode) |
1004 | gen->recordOpcode(opcodeID); |
1005 | if (size == OpcodeSize::Wide) |
1006 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
1007 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
1008 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
1009 | gen->write(Fits<VirtualRegister, size>::convert(immutableButterfly)); |
1010 | gen->write(Fits<IndexingType, size>::convert(recommendedIndexingType)); |
1011 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
1012 | return true; |
1013 | } |
1014 | return false; |
1015 | } |
1016 | |
1017 | public: |
1018 | template<typename Block> |
1019 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
1020 | { |
1021 | dumper->printLocationAndOp(__location, &"*new_array_buffer" [!__isWide]); |
1022 | dumper->dumpOperand(m_dst, true); |
1023 | dumper->dumpOperand(m_immutableButterfly, false); |
1024 | dumper->dumpOperand(m_recommendedIndexingType, false); |
1025 | } |
1026 | |
1027 | OpNewArrayBuffer(const uint8_t* stream) |
1028 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
1029 | , m_immutableButterfly(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
1030 | , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Narrow>::convert(stream[3])) |
1031 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
1032 | { |
1033 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
1034 | } |
1035 | |
1036 | OpNewArrayBuffer(const uint32_t* stream) |
1037 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
1038 | , m_immutableButterfly(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
1039 | , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Wide>::convert(stream[3])) |
1040 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
1041 | { |
1042 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
1043 | } |
1044 | |
1045 | static OpNewArrayBuffer decode(const uint8_t* stream) |
1046 | { |
1047 | if (*stream != op_wide) |
1048 | return { stream }; |
1049 | |
1050 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
1051 | return { wideStream }; |
1052 | } |
1053 | |
1054 | template<typename Functor> |
1055 | void setDst(VirtualRegister value, Functor func) |
1056 | { |
1057 | if (isWide()) |
1058 | setDst<OpcodeSize::Wide>(value, func); |
1059 | else |
1060 | setDst<OpcodeSize::Narrow>(value, func); |
1061 | } |
1062 | |
1063 | template <OpcodeSize size, typename Functor> |
1064 | void setDst(VirtualRegister value, Functor func) |
1065 | { |
1066 | if (!Fits<VirtualRegister, size>::check(value)) |
1067 | value = func(); |
1068 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
1069 | *stream = Fits<VirtualRegister, size>::convert(value); |
1070 | } |
1071 | |
1072 | template<typename Functor> |
1073 | void setImmutableButterfly(VirtualRegister value, Functor func) |
1074 | { |
1075 | if (isWide()) |
1076 | setImmutableButterfly<OpcodeSize::Wide>(value, func); |
1077 | else |
1078 | setImmutableButterfly<OpcodeSize::Narrow>(value, func); |
1079 | } |
1080 | |
1081 | template <OpcodeSize size, typename Functor> |
1082 | void setImmutableButterfly(VirtualRegister value, Functor func) |
1083 | { |
1084 | if (!Fits<VirtualRegister, size>::check(value)) |
1085 | value = func(); |
1086 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
1087 | *stream = Fits<VirtualRegister, size>::convert(value); |
1088 | } |
1089 | |
1090 | template<typename Functor> |
1091 | void setRecommendedIndexingType(IndexingType value, Functor func) |
1092 | { |
1093 | if (isWide()) |
1094 | setRecommendedIndexingType<OpcodeSize::Wide>(value, func); |
1095 | else |
1096 | setRecommendedIndexingType<OpcodeSize::Narrow>(value, func); |
1097 | } |
1098 | |
1099 | template <OpcodeSize size, typename Functor> |
1100 | void setRecommendedIndexingType(IndexingType value, Functor func) |
1101 | { |
1102 | if (!Fits<IndexingType, size>::check(value)) |
1103 | value = func(); |
1104 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
1105 | *stream = Fits<IndexingType, size>::convert(value); |
1106 | } |
1107 | |
1108 | struct Metadata { |
1109 | WTF_MAKE_NONCOPYABLE(Metadata); |
1110 | |
1111 | public: |
1112 | Metadata(const OpNewArrayBuffer&) { } |
1113 | |
1114 | ArrayAllocationProfile m_arrayAllocationProfile; |
1115 | }; |
1116 | |
1117 | Metadata& metadata(CodeBlock* codeBlock) const |
1118 | { |
1119 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
1120 | } |
1121 | |
1122 | Metadata& metadata(ExecState* exec) const |
1123 | { |
1124 | return metadata(exec->codeBlock()); |
1125 | } |
1126 | |
1127 | VirtualRegister m_dst; |
1128 | VirtualRegister m_immutableButterfly; |
1129 | IndexingType m_recommendedIndexingType; |
1130 | unsigned m_metadataID; |
1131 | }; |
1132 | |
1133 | struct OpAdd : public Instruction { |
1134 | static constexpr OpcodeID opcodeID = op_add; |
1135 | |
1136 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes) |
1137 | { |
1138 | |
1139 | auto __metadataID = gen->addMetadataFor(opcodeID); |
1140 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID) |
1141 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID); |
1142 | } |
1143 | |
1144 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
1145 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes) |
1146 | { |
1147 | auto __metadataID = gen->addMetadataFor(opcodeID); |
1148 | return emit<size, shouldAssert>(gen, dst, lhs, rhs, operandTypes, __metadataID); |
1149 | } |
1150 | |
1151 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
1152 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID) |
1153 | { |
1154 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, operandTypes, __metadataID); |
1155 | if (shouldAssert == Assert) |
1156 | ASSERT(didEmit); |
1157 | return didEmit; |
1158 | } |
1159 | |
1160 | private: |
1161 | template<OpcodeSize size, bool recordOpcode> |
1162 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID) |
1163 | { |
1164 | if (size == OpcodeSize::Wide) |
1165 | gen->alignWideOpcode(); |
1166 | if (Fits<unsigned, size>::check(opcodeID) |
1167 | && Fits<VirtualRegister, size>::check(dst) |
1168 | && Fits<VirtualRegister, size>::check(lhs) |
1169 | && Fits<VirtualRegister, size>::check(rhs) |
1170 | && Fits<OperandTypes, size>::check(operandTypes) |
1171 | && Fits<unsigned, size>::check(__metadataID) |
1172 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
1173 | if (recordOpcode) |
1174 | gen->recordOpcode(opcodeID); |
1175 | if (size == OpcodeSize::Wide) |
1176 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
1177 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
1178 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
1179 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
1180 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
1181 | gen->write(Fits<OperandTypes, size>::convert(operandTypes)); |
1182 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
1183 | return true; |
1184 | } |
1185 | return false; |
1186 | } |
1187 | |
1188 | public: |
1189 | template<typename Block> |
1190 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
1191 | { |
1192 | dumper->printLocationAndOp(__location, &"*add" [!__isWide]); |
1193 | dumper->dumpOperand(m_dst, true); |
1194 | dumper->dumpOperand(m_lhs, false); |
1195 | dumper->dumpOperand(m_rhs, false); |
1196 | dumper->dumpOperand(m_operandTypes, false); |
1197 | } |
1198 | |
1199 | OpAdd(const uint8_t* stream) |
1200 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
1201 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
1202 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
1203 | , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[4])) |
1204 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
1205 | { |
1206 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
1207 | } |
1208 | |
1209 | OpAdd(const uint32_t* stream) |
1210 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
1211 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
1212 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
1213 | , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide>::convert(stream[4])) |
1214 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
1215 | { |
1216 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
1217 | } |
1218 | |
1219 | static OpAdd decode(const uint8_t* stream) |
1220 | { |
1221 | if (*stream != op_wide) |
1222 | return { stream }; |
1223 | |
1224 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
1225 | return { wideStream }; |
1226 | } |
1227 | |
1228 | template<typename Functor> |
1229 | void setDst(VirtualRegister value, Functor func) |
1230 | { |
1231 | if (isWide()) |
1232 | setDst<OpcodeSize::Wide>(value, func); |
1233 | else |
1234 | setDst<OpcodeSize::Narrow>(value, func); |
1235 | } |
1236 | |
1237 | template <OpcodeSize size, typename Functor> |
1238 | void setDst(VirtualRegister value, Functor func) |
1239 | { |
1240 | if (!Fits<VirtualRegister, size>::check(value)) |
1241 | value = func(); |
1242 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
1243 | *stream = Fits<VirtualRegister, size>::convert(value); |
1244 | } |
1245 | |
1246 | template<typename Functor> |
1247 | void setLhs(VirtualRegister value, Functor func) |
1248 | { |
1249 | if (isWide()) |
1250 | setLhs<OpcodeSize::Wide>(value, func); |
1251 | else |
1252 | setLhs<OpcodeSize::Narrow>(value, func); |
1253 | } |
1254 | |
1255 | template <OpcodeSize size, typename Functor> |
1256 | void setLhs(VirtualRegister value, Functor func) |
1257 | { |
1258 | if (!Fits<VirtualRegister, size>::check(value)) |
1259 | value = func(); |
1260 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
1261 | *stream = Fits<VirtualRegister, size>::convert(value); |
1262 | } |
1263 | |
1264 | template<typename Functor> |
1265 | void setRhs(VirtualRegister value, Functor func) |
1266 | { |
1267 | if (isWide()) |
1268 | setRhs<OpcodeSize::Wide>(value, func); |
1269 | else |
1270 | setRhs<OpcodeSize::Narrow>(value, func); |
1271 | } |
1272 | |
1273 | template <OpcodeSize size, typename Functor> |
1274 | void setRhs(VirtualRegister value, Functor func) |
1275 | { |
1276 | if (!Fits<VirtualRegister, size>::check(value)) |
1277 | value = func(); |
1278 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
1279 | *stream = Fits<VirtualRegister, size>::convert(value); |
1280 | } |
1281 | |
1282 | template<typename Functor> |
1283 | void setOperandTypes(OperandTypes value, Functor func) |
1284 | { |
1285 | if (isWide()) |
1286 | setOperandTypes<OpcodeSize::Wide>(value, func); |
1287 | else |
1288 | setOperandTypes<OpcodeSize::Narrow>(value, func); |
1289 | } |
1290 | |
1291 | template <OpcodeSize size, typename Functor> |
1292 | void setOperandTypes(OperandTypes value, Functor func) |
1293 | { |
1294 | if (!Fits<OperandTypes, size>::check(value)) |
1295 | value = func(); |
1296 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
1297 | *stream = Fits<OperandTypes, size>::convert(value); |
1298 | } |
1299 | |
1300 | struct Metadata { |
1301 | WTF_MAKE_NONCOPYABLE(Metadata); |
1302 | |
1303 | public: |
1304 | Metadata(const OpAdd& __op) |
1305 | : m_arithProfile(__op.m_operandTypes) |
1306 | { } |
1307 | |
1308 | ArithProfile m_arithProfile; |
1309 | }; |
1310 | |
1311 | Metadata& metadata(CodeBlock* codeBlock) const |
1312 | { |
1313 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
1314 | } |
1315 | |
1316 | Metadata& metadata(ExecState* exec) const |
1317 | { |
1318 | return metadata(exec->codeBlock()); |
1319 | } |
1320 | |
1321 | VirtualRegister m_dst; |
1322 | VirtualRegister m_lhs; |
1323 | VirtualRegister m_rhs; |
1324 | OperandTypes m_operandTypes; |
1325 | unsigned m_metadataID; |
1326 | }; |
1327 | |
1328 | struct OpMul : public Instruction { |
1329 | static constexpr OpcodeID opcodeID = op_mul; |
1330 | |
1331 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes) |
1332 | { |
1333 | |
1334 | auto __metadataID = gen->addMetadataFor(opcodeID); |
1335 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID) |
1336 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID); |
1337 | } |
1338 | |
1339 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
1340 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes) |
1341 | { |
1342 | auto __metadataID = gen->addMetadataFor(opcodeID); |
1343 | return emit<size, shouldAssert>(gen, dst, lhs, rhs, operandTypes, __metadataID); |
1344 | } |
1345 | |
1346 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
1347 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID) |
1348 | { |
1349 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, operandTypes, __metadataID); |
1350 | if (shouldAssert == Assert) |
1351 | ASSERT(didEmit); |
1352 | return didEmit; |
1353 | } |
1354 | |
1355 | private: |
1356 | template<OpcodeSize size, bool recordOpcode> |
1357 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID) |
1358 | { |
1359 | if (size == OpcodeSize::Wide) |
1360 | gen->alignWideOpcode(); |
1361 | if (Fits<unsigned, size>::check(opcodeID) |
1362 | && Fits<VirtualRegister, size>::check(dst) |
1363 | && Fits<VirtualRegister, size>::check(lhs) |
1364 | && Fits<VirtualRegister, size>::check(rhs) |
1365 | && Fits<OperandTypes, size>::check(operandTypes) |
1366 | && Fits<unsigned, size>::check(__metadataID) |
1367 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
1368 | if (recordOpcode) |
1369 | gen->recordOpcode(opcodeID); |
1370 | if (size == OpcodeSize::Wide) |
1371 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
1372 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
1373 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
1374 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
1375 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
1376 | gen->write(Fits<OperandTypes, size>::convert(operandTypes)); |
1377 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
1378 | return true; |
1379 | } |
1380 | return false; |
1381 | } |
1382 | |
1383 | public: |
1384 | template<typename Block> |
1385 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
1386 | { |
1387 | dumper->printLocationAndOp(__location, &"*mul" [!__isWide]); |
1388 | dumper->dumpOperand(m_dst, true); |
1389 | dumper->dumpOperand(m_lhs, false); |
1390 | dumper->dumpOperand(m_rhs, false); |
1391 | dumper->dumpOperand(m_operandTypes, false); |
1392 | } |
1393 | |
1394 | OpMul(const uint8_t* stream) |
1395 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
1396 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
1397 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
1398 | , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[4])) |
1399 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
1400 | { |
1401 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
1402 | } |
1403 | |
1404 | OpMul(const uint32_t* stream) |
1405 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
1406 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
1407 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
1408 | , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide>::convert(stream[4])) |
1409 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
1410 | { |
1411 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
1412 | } |
1413 | |
1414 | static OpMul decode(const uint8_t* stream) |
1415 | { |
1416 | if (*stream != op_wide) |
1417 | return { stream }; |
1418 | |
1419 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
1420 | return { wideStream }; |
1421 | } |
1422 | |
1423 | template<typename Functor> |
1424 | void setDst(VirtualRegister value, Functor func) |
1425 | { |
1426 | if (isWide()) |
1427 | setDst<OpcodeSize::Wide>(value, func); |
1428 | else |
1429 | setDst<OpcodeSize::Narrow>(value, func); |
1430 | } |
1431 | |
1432 | template <OpcodeSize size, typename Functor> |
1433 | void setDst(VirtualRegister value, Functor func) |
1434 | { |
1435 | if (!Fits<VirtualRegister, size>::check(value)) |
1436 | value = func(); |
1437 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
1438 | *stream = Fits<VirtualRegister, size>::convert(value); |
1439 | } |
1440 | |
1441 | template<typename Functor> |
1442 | void setLhs(VirtualRegister value, Functor func) |
1443 | { |
1444 | if (isWide()) |
1445 | setLhs<OpcodeSize::Wide>(value, func); |
1446 | else |
1447 | setLhs<OpcodeSize::Narrow>(value, func); |
1448 | } |
1449 | |
1450 | template <OpcodeSize size, typename Functor> |
1451 | void setLhs(VirtualRegister value, Functor func) |
1452 | { |
1453 | if (!Fits<VirtualRegister, size>::check(value)) |
1454 | value = func(); |
1455 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
1456 | *stream = Fits<VirtualRegister, size>::convert(value); |
1457 | } |
1458 | |
1459 | template<typename Functor> |
1460 | void setRhs(VirtualRegister value, Functor func) |
1461 | { |
1462 | if (isWide()) |
1463 | setRhs<OpcodeSize::Wide>(value, func); |
1464 | else |
1465 | setRhs<OpcodeSize::Narrow>(value, func); |
1466 | } |
1467 | |
1468 | template <OpcodeSize size, typename Functor> |
1469 | void setRhs(VirtualRegister value, Functor func) |
1470 | { |
1471 | if (!Fits<VirtualRegister, size>::check(value)) |
1472 | value = func(); |
1473 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
1474 | *stream = Fits<VirtualRegister, size>::convert(value); |
1475 | } |
1476 | |
1477 | template<typename Functor> |
1478 | void setOperandTypes(OperandTypes value, Functor func) |
1479 | { |
1480 | if (isWide()) |
1481 | setOperandTypes<OpcodeSize::Wide>(value, func); |
1482 | else |
1483 | setOperandTypes<OpcodeSize::Narrow>(value, func); |
1484 | } |
1485 | |
1486 | template <OpcodeSize size, typename Functor> |
1487 | void setOperandTypes(OperandTypes value, Functor func) |
1488 | { |
1489 | if (!Fits<OperandTypes, size>::check(value)) |
1490 | value = func(); |
1491 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
1492 | *stream = Fits<OperandTypes, size>::convert(value); |
1493 | } |
1494 | |
1495 | struct Metadata { |
1496 | WTF_MAKE_NONCOPYABLE(Metadata); |
1497 | |
1498 | public: |
1499 | Metadata(const OpMul& __op) |
1500 | : m_arithProfile(__op.m_operandTypes) |
1501 | { } |
1502 | |
1503 | ArithProfile m_arithProfile; |
1504 | }; |
1505 | |
1506 | Metadata& metadata(CodeBlock* codeBlock) const |
1507 | { |
1508 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
1509 | } |
1510 | |
1511 | Metadata& metadata(ExecState* exec) const |
1512 | { |
1513 | return metadata(exec->codeBlock()); |
1514 | } |
1515 | |
1516 | VirtualRegister m_dst; |
1517 | VirtualRegister m_lhs; |
1518 | VirtualRegister m_rhs; |
1519 | OperandTypes m_operandTypes; |
1520 | unsigned m_metadataID; |
1521 | }; |
1522 | |
1523 | struct OpDiv : public Instruction { |
1524 | static constexpr OpcodeID opcodeID = op_div; |
1525 | |
1526 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes) |
1527 | { |
1528 | |
1529 | auto __metadataID = gen->addMetadataFor(opcodeID); |
1530 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID) |
1531 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID); |
1532 | } |
1533 | |
1534 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
1535 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes) |
1536 | { |
1537 | auto __metadataID = gen->addMetadataFor(opcodeID); |
1538 | return emit<size, shouldAssert>(gen, dst, lhs, rhs, operandTypes, __metadataID); |
1539 | } |
1540 | |
1541 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
1542 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID) |
1543 | { |
1544 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, operandTypes, __metadataID); |
1545 | if (shouldAssert == Assert) |
1546 | ASSERT(didEmit); |
1547 | return didEmit; |
1548 | } |
1549 | |
1550 | private: |
1551 | template<OpcodeSize size, bool recordOpcode> |
1552 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID) |
1553 | { |
1554 | if (size == OpcodeSize::Wide) |
1555 | gen->alignWideOpcode(); |
1556 | if (Fits<unsigned, size>::check(opcodeID) |
1557 | && Fits<VirtualRegister, size>::check(dst) |
1558 | && Fits<VirtualRegister, size>::check(lhs) |
1559 | && Fits<VirtualRegister, size>::check(rhs) |
1560 | && Fits<OperandTypes, size>::check(operandTypes) |
1561 | && Fits<unsigned, size>::check(__metadataID) |
1562 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
1563 | if (recordOpcode) |
1564 | gen->recordOpcode(opcodeID); |
1565 | if (size == OpcodeSize::Wide) |
1566 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
1567 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
1568 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
1569 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
1570 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
1571 | gen->write(Fits<OperandTypes, size>::convert(operandTypes)); |
1572 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
1573 | return true; |
1574 | } |
1575 | return false; |
1576 | } |
1577 | |
1578 | public: |
1579 | template<typename Block> |
1580 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
1581 | { |
1582 | dumper->printLocationAndOp(__location, &"*div" [!__isWide]); |
1583 | dumper->dumpOperand(m_dst, true); |
1584 | dumper->dumpOperand(m_lhs, false); |
1585 | dumper->dumpOperand(m_rhs, false); |
1586 | dumper->dumpOperand(m_operandTypes, false); |
1587 | } |
1588 | |
1589 | OpDiv(const uint8_t* stream) |
1590 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
1591 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
1592 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
1593 | , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[4])) |
1594 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
1595 | { |
1596 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
1597 | } |
1598 | |
1599 | OpDiv(const uint32_t* stream) |
1600 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
1601 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
1602 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
1603 | , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide>::convert(stream[4])) |
1604 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
1605 | { |
1606 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
1607 | } |
1608 | |
1609 | static OpDiv decode(const uint8_t* stream) |
1610 | { |
1611 | if (*stream != op_wide) |
1612 | return { stream }; |
1613 | |
1614 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
1615 | return { wideStream }; |
1616 | } |
1617 | |
1618 | template<typename Functor> |
1619 | void setDst(VirtualRegister value, Functor func) |
1620 | { |
1621 | if (isWide()) |
1622 | setDst<OpcodeSize::Wide>(value, func); |
1623 | else |
1624 | setDst<OpcodeSize::Narrow>(value, func); |
1625 | } |
1626 | |
1627 | template <OpcodeSize size, typename Functor> |
1628 | void setDst(VirtualRegister value, Functor func) |
1629 | { |
1630 | if (!Fits<VirtualRegister, size>::check(value)) |
1631 | value = func(); |
1632 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
1633 | *stream = Fits<VirtualRegister, size>::convert(value); |
1634 | } |
1635 | |
1636 | template<typename Functor> |
1637 | void setLhs(VirtualRegister value, Functor func) |
1638 | { |
1639 | if (isWide()) |
1640 | setLhs<OpcodeSize::Wide>(value, func); |
1641 | else |
1642 | setLhs<OpcodeSize::Narrow>(value, func); |
1643 | } |
1644 | |
1645 | template <OpcodeSize size, typename Functor> |
1646 | void setLhs(VirtualRegister value, Functor func) |
1647 | { |
1648 | if (!Fits<VirtualRegister, size>::check(value)) |
1649 | value = func(); |
1650 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
1651 | *stream = Fits<VirtualRegister, size>::convert(value); |
1652 | } |
1653 | |
1654 | template<typename Functor> |
1655 | void setRhs(VirtualRegister value, Functor func) |
1656 | { |
1657 | if (isWide()) |
1658 | setRhs<OpcodeSize::Wide>(value, func); |
1659 | else |
1660 | setRhs<OpcodeSize::Narrow>(value, func); |
1661 | } |
1662 | |
1663 | template <OpcodeSize size, typename Functor> |
1664 | void setRhs(VirtualRegister value, Functor func) |
1665 | { |
1666 | if (!Fits<VirtualRegister, size>::check(value)) |
1667 | value = func(); |
1668 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
1669 | *stream = Fits<VirtualRegister, size>::convert(value); |
1670 | } |
1671 | |
1672 | template<typename Functor> |
1673 | void setOperandTypes(OperandTypes value, Functor func) |
1674 | { |
1675 | if (isWide()) |
1676 | setOperandTypes<OpcodeSize::Wide>(value, func); |
1677 | else |
1678 | setOperandTypes<OpcodeSize::Narrow>(value, func); |
1679 | } |
1680 | |
1681 | template <OpcodeSize size, typename Functor> |
1682 | void setOperandTypes(OperandTypes value, Functor func) |
1683 | { |
1684 | if (!Fits<OperandTypes, size>::check(value)) |
1685 | value = func(); |
1686 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
1687 | *stream = Fits<OperandTypes, size>::convert(value); |
1688 | } |
1689 | |
1690 | struct Metadata { |
1691 | WTF_MAKE_NONCOPYABLE(Metadata); |
1692 | |
1693 | public: |
1694 | Metadata(const OpDiv& __op) |
1695 | : m_arithProfile(__op.m_operandTypes) |
1696 | { } |
1697 | |
1698 | ArithProfile m_arithProfile; |
1699 | }; |
1700 | |
1701 | Metadata& metadata(CodeBlock* codeBlock) const |
1702 | { |
1703 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
1704 | } |
1705 | |
1706 | Metadata& metadata(ExecState* exec) const |
1707 | { |
1708 | return metadata(exec->codeBlock()); |
1709 | } |
1710 | |
1711 | VirtualRegister m_dst; |
1712 | VirtualRegister m_lhs; |
1713 | VirtualRegister m_rhs; |
1714 | OperandTypes m_operandTypes; |
1715 | unsigned m_metadataID; |
1716 | }; |
1717 | |
1718 | struct OpSub : public Instruction { |
1719 | static constexpr OpcodeID opcodeID = op_sub; |
1720 | |
1721 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes) |
1722 | { |
1723 | |
1724 | auto __metadataID = gen->addMetadataFor(opcodeID); |
1725 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID) |
1726 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID); |
1727 | } |
1728 | |
1729 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
1730 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes) |
1731 | { |
1732 | auto __metadataID = gen->addMetadataFor(opcodeID); |
1733 | return emit<size, shouldAssert>(gen, dst, lhs, rhs, operandTypes, __metadataID); |
1734 | } |
1735 | |
1736 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
1737 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID) |
1738 | { |
1739 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, operandTypes, __metadataID); |
1740 | if (shouldAssert == Assert) |
1741 | ASSERT(didEmit); |
1742 | return didEmit; |
1743 | } |
1744 | |
1745 | private: |
1746 | template<OpcodeSize size, bool recordOpcode> |
1747 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID) |
1748 | { |
1749 | if (size == OpcodeSize::Wide) |
1750 | gen->alignWideOpcode(); |
1751 | if (Fits<unsigned, size>::check(opcodeID) |
1752 | && Fits<VirtualRegister, size>::check(dst) |
1753 | && Fits<VirtualRegister, size>::check(lhs) |
1754 | && Fits<VirtualRegister, size>::check(rhs) |
1755 | && Fits<OperandTypes, size>::check(operandTypes) |
1756 | && Fits<unsigned, size>::check(__metadataID) |
1757 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
1758 | if (recordOpcode) |
1759 | gen->recordOpcode(opcodeID); |
1760 | if (size == OpcodeSize::Wide) |
1761 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
1762 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
1763 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
1764 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
1765 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
1766 | gen->write(Fits<OperandTypes, size>::convert(operandTypes)); |
1767 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
1768 | return true; |
1769 | } |
1770 | return false; |
1771 | } |
1772 | |
1773 | public: |
1774 | template<typename Block> |
1775 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
1776 | { |
1777 | dumper->printLocationAndOp(__location, &"*sub" [!__isWide]); |
1778 | dumper->dumpOperand(m_dst, true); |
1779 | dumper->dumpOperand(m_lhs, false); |
1780 | dumper->dumpOperand(m_rhs, false); |
1781 | dumper->dumpOperand(m_operandTypes, false); |
1782 | } |
1783 | |
1784 | OpSub(const uint8_t* stream) |
1785 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
1786 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
1787 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
1788 | , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[4])) |
1789 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
1790 | { |
1791 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
1792 | } |
1793 | |
1794 | OpSub(const uint32_t* stream) |
1795 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
1796 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
1797 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
1798 | , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide>::convert(stream[4])) |
1799 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
1800 | { |
1801 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
1802 | } |
1803 | |
1804 | static OpSub decode(const uint8_t* stream) |
1805 | { |
1806 | if (*stream != op_wide) |
1807 | return { stream }; |
1808 | |
1809 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
1810 | return { wideStream }; |
1811 | } |
1812 | |
1813 | template<typename Functor> |
1814 | void setDst(VirtualRegister value, Functor func) |
1815 | { |
1816 | if (isWide()) |
1817 | setDst<OpcodeSize::Wide>(value, func); |
1818 | else |
1819 | setDst<OpcodeSize::Narrow>(value, func); |
1820 | } |
1821 | |
1822 | template <OpcodeSize size, typename Functor> |
1823 | void setDst(VirtualRegister value, Functor func) |
1824 | { |
1825 | if (!Fits<VirtualRegister, size>::check(value)) |
1826 | value = func(); |
1827 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
1828 | *stream = Fits<VirtualRegister, size>::convert(value); |
1829 | } |
1830 | |
1831 | template<typename Functor> |
1832 | void setLhs(VirtualRegister value, Functor func) |
1833 | { |
1834 | if (isWide()) |
1835 | setLhs<OpcodeSize::Wide>(value, func); |
1836 | else |
1837 | setLhs<OpcodeSize::Narrow>(value, func); |
1838 | } |
1839 | |
1840 | template <OpcodeSize size, typename Functor> |
1841 | void setLhs(VirtualRegister value, Functor func) |
1842 | { |
1843 | if (!Fits<VirtualRegister, size>::check(value)) |
1844 | value = func(); |
1845 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
1846 | *stream = Fits<VirtualRegister, size>::convert(value); |
1847 | } |
1848 | |
1849 | template<typename Functor> |
1850 | void setRhs(VirtualRegister value, Functor func) |
1851 | { |
1852 | if (isWide()) |
1853 | setRhs<OpcodeSize::Wide>(value, func); |
1854 | else |
1855 | setRhs<OpcodeSize::Narrow>(value, func); |
1856 | } |
1857 | |
1858 | template <OpcodeSize size, typename Functor> |
1859 | void setRhs(VirtualRegister value, Functor func) |
1860 | { |
1861 | if (!Fits<VirtualRegister, size>::check(value)) |
1862 | value = func(); |
1863 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
1864 | *stream = Fits<VirtualRegister, size>::convert(value); |
1865 | } |
1866 | |
1867 | template<typename Functor> |
1868 | void setOperandTypes(OperandTypes value, Functor func) |
1869 | { |
1870 | if (isWide()) |
1871 | setOperandTypes<OpcodeSize::Wide>(value, func); |
1872 | else |
1873 | setOperandTypes<OpcodeSize::Narrow>(value, func); |
1874 | } |
1875 | |
1876 | template <OpcodeSize size, typename Functor> |
1877 | void setOperandTypes(OperandTypes value, Functor func) |
1878 | { |
1879 | if (!Fits<OperandTypes, size>::check(value)) |
1880 | value = func(); |
1881 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
1882 | *stream = Fits<OperandTypes, size>::convert(value); |
1883 | } |
1884 | |
1885 | struct Metadata { |
1886 | WTF_MAKE_NONCOPYABLE(Metadata); |
1887 | |
1888 | public: |
1889 | Metadata(const OpSub& __op) |
1890 | : m_arithProfile(__op.m_operandTypes) |
1891 | { } |
1892 | |
1893 | ArithProfile m_arithProfile; |
1894 | }; |
1895 | |
1896 | Metadata& metadata(CodeBlock* codeBlock) const |
1897 | { |
1898 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
1899 | } |
1900 | |
1901 | Metadata& metadata(ExecState* exec) const |
1902 | { |
1903 | return metadata(exec->codeBlock()); |
1904 | } |
1905 | |
1906 | VirtualRegister m_dst; |
1907 | VirtualRegister m_lhs; |
1908 | VirtualRegister m_rhs; |
1909 | OperandTypes m_operandTypes; |
1910 | unsigned m_metadataID; |
1911 | }; |
1912 | |
1913 | struct OpBitand : public Instruction { |
1914 | static constexpr OpcodeID opcodeID = op_bitand; |
1915 | |
1916 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
1917 | { |
1918 | |
1919 | auto __metadataID = gen->addMetadataFor(opcodeID); |
1920 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, __metadataID) |
1921 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs, __metadataID); |
1922 | } |
1923 | |
1924 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
1925 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
1926 | { |
1927 | auto __metadataID = gen->addMetadataFor(opcodeID); |
1928 | return emit<size, shouldAssert>(gen, dst, lhs, rhs, __metadataID); |
1929 | } |
1930 | |
1931 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
1932 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID) |
1933 | { |
1934 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, __metadataID); |
1935 | if (shouldAssert == Assert) |
1936 | ASSERT(didEmit); |
1937 | return didEmit; |
1938 | } |
1939 | |
1940 | private: |
1941 | template<OpcodeSize size, bool recordOpcode> |
1942 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID) |
1943 | { |
1944 | if (size == OpcodeSize::Wide) |
1945 | gen->alignWideOpcode(); |
1946 | if (Fits<unsigned, size>::check(opcodeID) |
1947 | && Fits<VirtualRegister, size>::check(dst) |
1948 | && Fits<VirtualRegister, size>::check(lhs) |
1949 | && Fits<VirtualRegister, size>::check(rhs) |
1950 | && Fits<unsigned, size>::check(__metadataID) |
1951 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
1952 | if (recordOpcode) |
1953 | gen->recordOpcode(opcodeID); |
1954 | if (size == OpcodeSize::Wide) |
1955 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
1956 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
1957 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
1958 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
1959 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
1960 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
1961 | return true; |
1962 | } |
1963 | return false; |
1964 | } |
1965 | |
1966 | public: |
1967 | template<typename Block> |
1968 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
1969 | { |
1970 | dumper->printLocationAndOp(__location, &"*bitand" [!__isWide]); |
1971 | dumper->dumpOperand(m_dst, true); |
1972 | dumper->dumpOperand(m_lhs, false); |
1973 | dumper->dumpOperand(m_rhs, false); |
1974 | } |
1975 | |
1976 | OpBitand(const uint8_t* stream) |
1977 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
1978 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
1979 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
1980 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
1981 | { |
1982 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
1983 | } |
1984 | |
1985 | OpBitand(const uint32_t* stream) |
1986 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
1987 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
1988 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
1989 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
1990 | { |
1991 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
1992 | } |
1993 | |
1994 | static OpBitand decode(const uint8_t* stream) |
1995 | { |
1996 | if (*stream != op_wide) |
1997 | return { stream }; |
1998 | |
1999 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
2000 | return { wideStream }; |
2001 | } |
2002 | |
2003 | template<typename Functor> |
2004 | void setDst(VirtualRegister value, Functor func) |
2005 | { |
2006 | if (isWide()) |
2007 | setDst<OpcodeSize::Wide>(value, func); |
2008 | else |
2009 | setDst<OpcodeSize::Narrow>(value, func); |
2010 | } |
2011 | |
2012 | template <OpcodeSize size, typename Functor> |
2013 | void setDst(VirtualRegister value, Functor func) |
2014 | { |
2015 | if (!Fits<VirtualRegister, size>::check(value)) |
2016 | value = func(); |
2017 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
2018 | *stream = Fits<VirtualRegister, size>::convert(value); |
2019 | } |
2020 | |
2021 | template<typename Functor> |
2022 | void setLhs(VirtualRegister value, Functor func) |
2023 | { |
2024 | if (isWide()) |
2025 | setLhs<OpcodeSize::Wide>(value, func); |
2026 | else |
2027 | setLhs<OpcodeSize::Narrow>(value, func); |
2028 | } |
2029 | |
2030 | template <OpcodeSize size, typename Functor> |
2031 | void setLhs(VirtualRegister value, Functor func) |
2032 | { |
2033 | if (!Fits<VirtualRegister, size>::check(value)) |
2034 | value = func(); |
2035 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
2036 | *stream = Fits<VirtualRegister, size>::convert(value); |
2037 | } |
2038 | |
2039 | template<typename Functor> |
2040 | void setRhs(VirtualRegister value, Functor func) |
2041 | { |
2042 | if (isWide()) |
2043 | setRhs<OpcodeSize::Wide>(value, func); |
2044 | else |
2045 | setRhs<OpcodeSize::Narrow>(value, func); |
2046 | } |
2047 | |
2048 | template <OpcodeSize size, typename Functor> |
2049 | void setRhs(VirtualRegister value, Functor func) |
2050 | { |
2051 | if (!Fits<VirtualRegister, size>::check(value)) |
2052 | value = func(); |
2053 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
2054 | *stream = Fits<VirtualRegister, size>::convert(value); |
2055 | } |
2056 | |
2057 | struct Metadata { |
2058 | WTF_MAKE_NONCOPYABLE(Metadata); |
2059 | |
2060 | public: |
2061 | Metadata(const OpBitand&) { } |
2062 | |
2063 | ValueProfile m_profile; |
2064 | }; |
2065 | |
2066 | Metadata& metadata(CodeBlock* codeBlock) const |
2067 | { |
2068 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
2069 | } |
2070 | |
2071 | Metadata& metadata(ExecState* exec) const |
2072 | { |
2073 | return metadata(exec->codeBlock()); |
2074 | } |
2075 | |
2076 | VirtualRegister m_dst; |
2077 | VirtualRegister m_lhs; |
2078 | VirtualRegister m_rhs; |
2079 | unsigned m_metadataID; |
2080 | }; |
2081 | |
2082 | struct OpBitor : public Instruction { |
2083 | static constexpr OpcodeID opcodeID = op_bitor; |
2084 | |
2085 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
2086 | { |
2087 | |
2088 | auto __metadataID = gen->addMetadataFor(opcodeID); |
2089 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, __metadataID) |
2090 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs, __metadataID); |
2091 | } |
2092 | |
2093 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
2094 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
2095 | { |
2096 | auto __metadataID = gen->addMetadataFor(opcodeID); |
2097 | return emit<size, shouldAssert>(gen, dst, lhs, rhs, __metadataID); |
2098 | } |
2099 | |
2100 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
2101 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID) |
2102 | { |
2103 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, __metadataID); |
2104 | if (shouldAssert == Assert) |
2105 | ASSERT(didEmit); |
2106 | return didEmit; |
2107 | } |
2108 | |
2109 | private: |
2110 | template<OpcodeSize size, bool recordOpcode> |
2111 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID) |
2112 | { |
2113 | if (size == OpcodeSize::Wide) |
2114 | gen->alignWideOpcode(); |
2115 | if (Fits<unsigned, size>::check(opcodeID) |
2116 | && Fits<VirtualRegister, size>::check(dst) |
2117 | && Fits<VirtualRegister, size>::check(lhs) |
2118 | && Fits<VirtualRegister, size>::check(rhs) |
2119 | && Fits<unsigned, size>::check(__metadataID) |
2120 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
2121 | if (recordOpcode) |
2122 | gen->recordOpcode(opcodeID); |
2123 | if (size == OpcodeSize::Wide) |
2124 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
2125 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
2126 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
2127 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
2128 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
2129 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
2130 | return true; |
2131 | } |
2132 | return false; |
2133 | } |
2134 | |
2135 | public: |
2136 | template<typename Block> |
2137 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
2138 | { |
2139 | dumper->printLocationAndOp(__location, &"*bitor" [!__isWide]); |
2140 | dumper->dumpOperand(m_dst, true); |
2141 | dumper->dumpOperand(m_lhs, false); |
2142 | dumper->dumpOperand(m_rhs, false); |
2143 | } |
2144 | |
2145 | OpBitor(const uint8_t* stream) |
2146 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
2147 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
2148 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
2149 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
2150 | { |
2151 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
2152 | } |
2153 | |
2154 | OpBitor(const uint32_t* stream) |
2155 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
2156 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
2157 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
2158 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
2159 | { |
2160 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
2161 | } |
2162 | |
2163 | static OpBitor decode(const uint8_t* stream) |
2164 | { |
2165 | if (*stream != op_wide) |
2166 | return { stream }; |
2167 | |
2168 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
2169 | return { wideStream }; |
2170 | } |
2171 | |
2172 | template<typename Functor> |
2173 | void setDst(VirtualRegister value, Functor func) |
2174 | { |
2175 | if (isWide()) |
2176 | setDst<OpcodeSize::Wide>(value, func); |
2177 | else |
2178 | setDst<OpcodeSize::Narrow>(value, func); |
2179 | } |
2180 | |
2181 | template <OpcodeSize size, typename Functor> |
2182 | void setDst(VirtualRegister value, Functor func) |
2183 | { |
2184 | if (!Fits<VirtualRegister, size>::check(value)) |
2185 | value = func(); |
2186 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
2187 | *stream = Fits<VirtualRegister, size>::convert(value); |
2188 | } |
2189 | |
2190 | template<typename Functor> |
2191 | void setLhs(VirtualRegister value, Functor func) |
2192 | { |
2193 | if (isWide()) |
2194 | setLhs<OpcodeSize::Wide>(value, func); |
2195 | else |
2196 | setLhs<OpcodeSize::Narrow>(value, func); |
2197 | } |
2198 | |
2199 | template <OpcodeSize size, typename Functor> |
2200 | void setLhs(VirtualRegister value, Functor func) |
2201 | { |
2202 | if (!Fits<VirtualRegister, size>::check(value)) |
2203 | value = func(); |
2204 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
2205 | *stream = Fits<VirtualRegister, size>::convert(value); |
2206 | } |
2207 | |
2208 | template<typename Functor> |
2209 | void setRhs(VirtualRegister value, Functor func) |
2210 | { |
2211 | if (isWide()) |
2212 | setRhs<OpcodeSize::Wide>(value, func); |
2213 | else |
2214 | setRhs<OpcodeSize::Narrow>(value, func); |
2215 | } |
2216 | |
2217 | template <OpcodeSize size, typename Functor> |
2218 | void setRhs(VirtualRegister value, Functor func) |
2219 | { |
2220 | if (!Fits<VirtualRegister, size>::check(value)) |
2221 | value = func(); |
2222 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
2223 | *stream = Fits<VirtualRegister, size>::convert(value); |
2224 | } |
2225 | |
2226 | struct Metadata { |
2227 | WTF_MAKE_NONCOPYABLE(Metadata); |
2228 | |
2229 | public: |
2230 | Metadata(const OpBitor&) { } |
2231 | |
2232 | ValueProfile m_profile; |
2233 | }; |
2234 | |
2235 | Metadata& metadata(CodeBlock* codeBlock) const |
2236 | { |
2237 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
2238 | } |
2239 | |
2240 | Metadata& metadata(ExecState* exec) const |
2241 | { |
2242 | return metadata(exec->codeBlock()); |
2243 | } |
2244 | |
2245 | VirtualRegister m_dst; |
2246 | VirtualRegister m_lhs; |
2247 | VirtualRegister m_rhs; |
2248 | unsigned m_metadataID; |
2249 | }; |
2250 | |
2251 | struct OpBitxor : public Instruction { |
2252 | static constexpr OpcodeID opcodeID = op_bitxor; |
2253 | |
2254 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
2255 | { |
2256 | |
2257 | auto __metadataID = gen->addMetadataFor(opcodeID); |
2258 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, __metadataID) |
2259 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs, __metadataID); |
2260 | } |
2261 | |
2262 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
2263 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
2264 | { |
2265 | auto __metadataID = gen->addMetadataFor(opcodeID); |
2266 | return emit<size, shouldAssert>(gen, dst, lhs, rhs, __metadataID); |
2267 | } |
2268 | |
2269 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
2270 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID) |
2271 | { |
2272 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, __metadataID); |
2273 | if (shouldAssert == Assert) |
2274 | ASSERT(didEmit); |
2275 | return didEmit; |
2276 | } |
2277 | |
2278 | private: |
2279 | template<OpcodeSize size, bool recordOpcode> |
2280 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID) |
2281 | { |
2282 | if (size == OpcodeSize::Wide) |
2283 | gen->alignWideOpcode(); |
2284 | if (Fits<unsigned, size>::check(opcodeID) |
2285 | && Fits<VirtualRegister, size>::check(dst) |
2286 | && Fits<VirtualRegister, size>::check(lhs) |
2287 | && Fits<VirtualRegister, size>::check(rhs) |
2288 | && Fits<unsigned, size>::check(__metadataID) |
2289 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
2290 | if (recordOpcode) |
2291 | gen->recordOpcode(opcodeID); |
2292 | if (size == OpcodeSize::Wide) |
2293 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
2294 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
2295 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
2296 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
2297 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
2298 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
2299 | return true; |
2300 | } |
2301 | return false; |
2302 | } |
2303 | |
2304 | public: |
2305 | template<typename Block> |
2306 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
2307 | { |
2308 | dumper->printLocationAndOp(__location, &"*bitxor" [!__isWide]); |
2309 | dumper->dumpOperand(m_dst, true); |
2310 | dumper->dumpOperand(m_lhs, false); |
2311 | dumper->dumpOperand(m_rhs, false); |
2312 | } |
2313 | |
2314 | OpBitxor(const uint8_t* stream) |
2315 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
2316 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
2317 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
2318 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
2319 | { |
2320 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
2321 | } |
2322 | |
2323 | OpBitxor(const uint32_t* stream) |
2324 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
2325 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
2326 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
2327 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
2328 | { |
2329 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
2330 | } |
2331 | |
2332 | static OpBitxor decode(const uint8_t* stream) |
2333 | { |
2334 | if (*stream != op_wide) |
2335 | return { stream }; |
2336 | |
2337 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
2338 | return { wideStream }; |
2339 | } |
2340 | |
2341 | template<typename Functor> |
2342 | void setDst(VirtualRegister value, Functor func) |
2343 | { |
2344 | if (isWide()) |
2345 | setDst<OpcodeSize::Wide>(value, func); |
2346 | else |
2347 | setDst<OpcodeSize::Narrow>(value, func); |
2348 | } |
2349 | |
2350 | template <OpcodeSize size, typename Functor> |
2351 | void setDst(VirtualRegister value, Functor func) |
2352 | { |
2353 | if (!Fits<VirtualRegister, size>::check(value)) |
2354 | value = func(); |
2355 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
2356 | *stream = Fits<VirtualRegister, size>::convert(value); |
2357 | } |
2358 | |
2359 | template<typename Functor> |
2360 | void setLhs(VirtualRegister value, Functor func) |
2361 | { |
2362 | if (isWide()) |
2363 | setLhs<OpcodeSize::Wide>(value, func); |
2364 | else |
2365 | setLhs<OpcodeSize::Narrow>(value, func); |
2366 | } |
2367 | |
2368 | template <OpcodeSize size, typename Functor> |
2369 | void setLhs(VirtualRegister value, Functor func) |
2370 | { |
2371 | if (!Fits<VirtualRegister, size>::check(value)) |
2372 | value = func(); |
2373 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
2374 | *stream = Fits<VirtualRegister, size>::convert(value); |
2375 | } |
2376 | |
2377 | template<typename Functor> |
2378 | void setRhs(VirtualRegister value, Functor func) |
2379 | { |
2380 | if (isWide()) |
2381 | setRhs<OpcodeSize::Wide>(value, func); |
2382 | else |
2383 | setRhs<OpcodeSize::Narrow>(value, func); |
2384 | } |
2385 | |
2386 | template <OpcodeSize size, typename Functor> |
2387 | void setRhs(VirtualRegister value, Functor func) |
2388 | { |
2389 | if (!Fits<VirtualRegister, size>::check(value)) |
2390 | value = func(); |
2391 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
2392 | *stream = Fits<VirtualRegister, size>::convert(value); |
2393 | } |
2394 | |
2395 | struct Metadata { |
2396 | WTF_MAKE_NONCOPYABLE(Metadata); |
2397 | |
2398 | public: |
2399 | Metadata(const OpBitxor&) { } |
2400 | |
2401 | ValueProfile m_profile; |
2402 | }; |
2403 | |
2404 | Metadata& metadata(CodeBlock* codeBlock) const |
2405 | { |
2406 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
2407 | } |
2408 | |
2409 | Metadata& metadata(ExecState* exec) const |
2410 | { |
2411 | return metadata(exec->codeBlock()); |
2412 | } |
2413 | |
2414 | VirtualRegister m_dst; |
2415 | VirtualRegister m_lhs; |
2416 | VirtualRegister m_rhs; |
2417 | unsigned m_metadataID; |
2418 | }; |
2419 | |
2420 | struct OpBitnot : public Instruction { |
2421 | static constexpr OpcodeID opcodeID = op_bitnot; |
2422 | |
2423 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
2424 | { |
2425 | |
2426 | auto __metadataID = gen->addMetadataFor(opcodeID); |
2427 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand, __metadataID) |
2428 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand, __metadataID); |
2429 | } |
2430 | |
2431 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
2432 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
2433 | { |
2434 | auto __metadataID = gen->addMetadataFor(opcodeID); |
2435 | return emit<size, shouldAssert>(gen, dst, operand, __metadataID); |
2436 | } |
2437 | |
2438 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
2439 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID) |
2440 | { |
2441 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand, __metadataID); |
2442 | if (shouldAssert == Assert) |
2443 | ASSERT(didEmit); |
2444 | return didEmit; |
2445 | } |
2446 | |
2447 | private: |
2448 | template<OpcodeSize size, bool recordOpcode> |
2449 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID) |
2450 | { |
2451 | if (size == OpcodeSize::Wide) |
2452 | gen->alignWideOpcode(); |
2453 | if (Fits<unsigned, size>::check(opcodeID) |
2454 | && Fits<VirtualRegister, size>::check(dst) |
2455 | && Fits<VirtualRegister, size>::check(operand) |
2456 | && Fits<unsigned, size>::check(__metadataID) |
2457 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
2458 | if (recordOpcode) |
2459 | gen->recordOpcode(opcodeID); |
2460 | if (size == OpcodeSize::Wide) |
2461 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
2462 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
2463 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
2464 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
2465 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
2466 | return true; |
2467 | } |
2468 | return false; |
2469 | } |
2470 | |
2471 | public: |
2472 | template<typename Block> |
2473 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
2474 | { |
2475 | dumper->printLocationAndOp(__location, &"*bitnot" [!__isWide]); |
2476 | dumper->dumpOperand(m_dst, true); |
2477 | dumper->dumpOperand(m_operand, false); |
2478 | } |
2479 | |
2480 | OpBitnot(const uint8_t* stream) |
2481 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
2482 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
2483 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
2484 | { |
2485 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
2486 | } |
2487 | |
2488 | OpBitnot(const uint32_t* stream) |
2489 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
2490 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
2491 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
2492 | { |
2493 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
2494 | } |
2495 | |
2496 | static OpBitnot decode(const uint8_t* stream) |
2497 | { |
2498 | if (*stream != op_wide) |
2499 | return { stream }; |
2500 | |
2501 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
2502 | return { wideStream }; |
2503 | } |
2504 | |
2505 | template<typename Functor> |
2506 | void setDst(VirtualRegister value, Functor func) |
2507 | { |
2508 | if (isWide()) |
2509 | setDst<OpcodeSize::Wide>(value, func); |
2510 | else |
2511 | setDst<OpcodeSize::Narrow>(value, func); |
2512 | } |
2513 | |
2514 | template <OpcodeSize size, typename Functor> |
2515 | void setDst(VirtualRegister value, Functor func) |
2516 | { |
2517 | if (!Fits<VirtualRegister, size>::check(value)) |
2518 | value = func(); |
2519 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
2520 | *stream = Fits<VirtualRegister, size>::convert(value); |
2521 | } |
2522 | |
2523 | template<typename Functor> |
2524 | void setOperand(VirtualRegister value, Functor func) |
2525 | { |
2526 | if (isWide()) |
2527 | setOperand<OpcodeSize::Wide>(value, func); |
2528 | else |
2529 | setOperand<OpcodeSize::Narrow>(value, func); |
2530 | } |
2531 | |
2532 | template <OpcodeSize size, typename Functor> |
2533 | void setOperand(VirtualRegister value, Functor func) |
2534 | { |
2535 | if (!Fits<VirtualRegister, size>::check(value)) |
2536 | value = func(); |
2537 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
2538 | *stream = Fits<VirtualRegister, size>::convert(value); |
2539 | } |
2540 | |
2541 | struct Metadata { |
2542 | WTF_MAKE_NONCOPYABLE(Metadata); |
2543 | |
2544 | public: |
2545 | Metadata(const OpBitnot&) { } |
2546 | |
2547 | ValueProfile m_profile; |
2548 | }; |
2549 | |
2550 | Metadata& metadata(CodeBlock* codeBlock) const |
2551 | { |
2552 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
2553 | } |
2554 | |
2555 | Metadata& metadata(ExecState* exec) const |
2556 | { |
2557 | return metadata(exec->codeBlock()); |
2558 | } |
2559 | |
2560 | VirtualRegister m_dst; |
2561 | VirtualRegister m_operand; |
2562 | unsigned m_metadataID; |
2563 | }; |
2564 | |
2565 | struct OpToObject : public Instruction { |
2566 | static constexpr OpcodeID opcodeID = op_to_object; |
2567 | |
2568 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message) |
2569 | { |
2570 | |
2571 | auto __metadataID = gen->addMetadataFor(opcodeID); |
2572 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand, message, __metadataID) |
2573 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand, message, __metadataID); |
2574 | } |
2575 | |
2576 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
2577 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message) |
2578 | { |
2579 | auto __metadataID = gen->addMetadataFor(opcodeID); |
2580 | return emit<size, shouldAssert>(gen, dst, operand, message, __metadataID); |
2581 | } |
2582 | |
2583 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
2584 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message, unsigned __metadataID) |
2585 | { |
2586 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand, message, __metadataID); |
2587 | if (shouldAssert == Assert) |
2588 | ASSERT(didEmit); |
2589 | return didEmit; |
2590 | } |
2591 | |
2592 | private: |
2593 | template<OpcodeSize size, bool recordOpcode> |
2594 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message, unsigned __metadataID) |
2595 | { |
2596 | if (size == OpcodeSize::Wide) |
2597 | gen->alignWideOpcode(); |
2598 | if (Fits<unsigned, size>::check(opcodeID) |
2599 | && Fits<VirtualRegister, size>::check(dst) |
2600 | && Fits<VirtualRegister, size>::check(operand) |
2601 | && Fits<unsigned, size>::check(message) |
2602 | && Fits<unsigned, size>::check(__metadataID) |
2603 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
2604 | if (recordOpcode) |
2605 | gen->recordOpcode(opcodeID); |
2606 | if (size == OpcodeSize::Wide) |
2607 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
2608 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
2609 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
2610 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
2611 | gen->write(Fits<unsigned, size>::convert(message)); |
2612 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
2613 | return true; |
2614 | } |
2615 | return false; |
2616 | } |
2617 | |
2618 | public: |
2619 | template<typename Block> |
2620 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
2621 | { |
2622 | dumper->printLocationAndOp(__location, &"*to_object" [!__isWide]); |
2623 | dumper->dumpOperand(m_dst, true); |
2624 | dumper->dumpOperand(m_operand, false); |
2625 | dumper->dumpOperand(m_message, false); |
2626 | } |
2627 | |
2628 | OpToObject(const uint8_t* stream) |
2629 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
2630 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
2631 | , m_message(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
2632 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
2633 | { |
2634 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
2635 | } |
2636 | |
2637 | OpToObject(const uint32_t* stream) |
2638 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
2639 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
2640 | , m_message(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
2641 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
2642 | { |
2643 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
2644 | } |
2645 | |
2646 | static OpToObject decode(const uint8_t* stream) |
2647 | { |
2648 | if (*stream != op_wide) |
2649 | return { stream }; |
2650 | |
2651 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
2652 | return { wideStream }; |
2653 | } |
2654 | |
2655 | template<typename Functor> |
2656 | void setDst(VirtualRegister value, Functor func) |
2657 | { |
2658 | if (isWide()) |
2659 | setDst<OpcodeSize::Wide>(value, func); |
2660 | else |
2661 | setDst<OpcodeSize::Narrow>(value, func); |
2662 | } |
2663 | |
2664 | template <OpcodeSize size, typename Functor> |
2665 | void setDst(VirtualRegister value, Functor func) |
2666 | { |
2667 | if (!Fits<VirtualRegister, size>::check(value)) |
2668 | value = func(); |
2669 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
2670 | *stream = Fits<VirtualRegister, size>::convert(value); |
2671 | } |
2672 | |
2673 | template<typename Functor> |
2674 | void setOperand(VirtualRegister value, Functor func) |
2675 | { |
2676 | if (isWide()) |
2677 | setOperand<OpcodeSize::Wide>(value, func); |
2678 | else |
2679 | setOperand<OpcodeSize::Narrow>(value, func); |
2680 | } |
2681 | |
2682 | template <OpcodeSize size, typename Functor> |
2683 | void setOperand(VirtualRegister value, Functor func) |
2684 | { |
2685 | if (!Fits<VirtualRegister, size>::check(value)) |
2686 | value = func(); |
2687 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
2688 | *stream = Fits<VirtualRegister, size>::convert(value); |
2689 | } |
2690 | |
2691 | template<typename Functor> |
2692 | void setMessage(unsigned value, Functor func) |
2693 | { |
2694 | if (isWide()) |
2695 | setMessage<OpcodeSize::Wide>(value, func); |
2696 | else |
2697 | setMessage<OpcodeSize::Narrow>(value, func); |
2698 | } |
2699 | |
2700 | template <OpcodeSize size, typename Functor> |
2701 | void setMessage(unsigned value, Functor func) |
2702 | { |
2703 | if (!Fits<unsigned, size>::check(value)) |
2704 | value = func(); |
2705 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
2706 | *stream = Fits<unsigned, size>::convert(value); |
2707 | } |
2708 | |
2709 | struct Metadata { |
2710 | WTF_MAKE_NONCOPYABLE(Metadata); |
2711 | |
2712 | public: |
2713 | Metadata(const OpToObject&) { } |
2714 | |
2715 | ValueProfile m_profile; |
2716 | }; |
2717 | |
2718 | Metadata& metadata(CodeBlock* codeBlock) const |
2719 | { |
2720 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
2721 | } |
2722 | |
2723 | Metadata& metadata(ExecState* exec) const |
2724 | { |
2725 | return metadata(exec->codeBlock()); |
2726 | } |
2727 | |
2728 | VirtualRegister m_dst; |
2729 | VirtualRegister m_operand; |
2730 | unsigned m_message; |
2731 | unsigned m_metadataID; |
2732 | }; |
2733 | |
2734 | struct OpToNumber : public Instruction { |
2735 | static constexpr OpcodeID opcodeID = op_to_number; |
2736 | |
2737 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
2738 | { |
2739 | |
2740 | auto __metadataID = gen->addMetadataFor(opcodeID); |
2741 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand, __metadataID) |
2742 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand, __metadataID); |
2743 | } |
2744 | |
2745 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
2746 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
2747 | { |
2748 | auto __metadataID = gen->addMetadataFor(opcodeID); |
2749 | return emit<size, shouldAssert>(gen, dst, operand, __metadataID); |
2750 | } |
2751 | |
2752 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
2753 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID) |
2754 | { |
2755 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand, __metadataID); |
2756 | if (shouldAssert == Assert) |
2757 | ASSERT(didEmit); |
2758 | return didEmit; |
2759 | } |
2760 | |
2761 | private: |
2762 | template<OpcodeSize size, bool recordOpcode> |
2763 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID) |
2764 | { |
2765 | if (size == OpcodeSize::Wide) |
2766 | gen->alignWideOpcode(); |
2767 | if (Fits<unsigned, size>::check(opcodeID) |
2768 | && Fits<VirtualRegister, size>::check(dst) |
2769 | && Fits<VirtualRegister, size>::check(operand) |
2770 | && Fits<unsigned, size>::check(__metadataID) |
2771 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
2772 | if (recordOpcode) |
2773 | gen->recordOpcode(opcodeID); |
2774 | if (size == OpcodeSize::Wide) |
2775 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
2776 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
2777 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
2778 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
2779 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
2780 | return true; |
2781 | } |
2782 | return false; |
2783 | } |
2784 | |
2785 | public: |
2786 | template<typename Block> |
2787 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
2788 | { |
2789 | dumper->printLocationAndOp(__location, &"*to_number" [!__isWide]); |
2790 | dumper->dumpOperand(m_dst, true); |
2791 | dumper->dumpOperand(m_operand, false); |
2792 | } |
2793 | |
2794 | OpToNumber(const uint8_t* stream) |
2795 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
2796 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
2797 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
2798 | { |
2799 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
2800 | } |
2801 | |
2802 | OpToNumber(const uint32_t* stream) |
2803 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
2804 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
2805 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
2806 | { |
2807 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
2808 | } |
2809 | |
2810 | static OpToNumber decode(const uint8_t* stream) |
2811 | { |
2812 | if (*stream != op_wide) |
2813 | return { stream }; |
2814 | |
2815 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
2816 | return { wideStream }; |
2817 | } |
2818 | |
2819 | template<typename Functor> |
2820 | void setDst(VirtualRegister value, Functor func) |
2821 | { |
2822 | if (isWide()) |
2823 | setDst<OpcodeSize::Wide>(value, func); |
2824 | else |
2825 | setDst<OpcodeSize::Narrow>(value, func); |
2826 | } |
2827 | |
2828 | template <OpcodeSize size, typename Functor> |
2829 | void setDst(VirtualRegister value, Functor func) |
2830 | { |
2831 | if (!Fits<VirtualRegister, size>::check(value)) |
2832 | value = func(); |
2833 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
2834 | *stream = Fits<VirtualRegister, size>::convert(value); |
2835 | } |
2836 | |
2837 | template<typename Functor> |
2838 | void setOperand(VirtualRegister value, Functor func) |
2839 | { |
2840 | if (isWide()) |
2841 | setOperand<OpcodeSize::Wide>(value, func); |
2842 | else |
2843 | setOperand<OpcodeSize::Narrow>(value, func); |
2844 | } |
2845 | |
2846 | template <OpcodeSize size, typename Functor> |
2847 | void setOperand(VirtualRegister value, Functor func) |
2848 | { |
2849 | if (!Fits<VirtualRegister, size>::check(value)) |
2850 | value = func(); |
2851 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
2852 | *stream = Fits<VirtualRegister, size>::convert(value); |
2853 | } |
2854 | |
2855 | struct Metadata { |
2856 | WTF_MAKE_NONCOPYABLE(Metadata); |
2857 | |
2858 | public: |
2859 | Metadata(const OpToNumber&) { } |
2860 | |
2861 | ValueProfile m_profile; |
2862 | }; |
2863 | |
2864 | Metadata& metadata(CodeBlock* codeBlock) const |
2865 | { |
2866 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
2867 | } |
2868 | |
2869 | Metadata& metadata(ExecState* exec) const |
2870 | { |
2871 | return metadata(exec->codeBlock()); |
2872 | } |
2873 | |
2874 | VirtualRegister m_dst; |
2875 | VirtualRegister m_operand; |
2876 | unsigned m_metadataID; |
2877 | }; |
2878 | |
2879 | struct OpNegate : public Instruction { |
2880 | static constexpr OpcodeID opcodeID = op_negate; |
2881 | |
2882 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, OperandTypes operandTypes) |
2883 | { |
2884 | |
2885 | auto __metadataID = gen->addMetadataFor(opcodeID); |
2886 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand, operandTypes, __metadataID) |
2887 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand, operandTypes, __metadataID); |
2888 | } |
2889 | |
2890 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
2891 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, OperandTypes operandTypes) |
2892 | { |
2893 | auto __metadataID = gen->addMetadataFor(opcodeID); |
2894 | return emit<size, shouldAssert>(gen, dst, operand, operandTypes, __metadataID); |
2895 | } |
2896 | |
2897 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
2898 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, OperandTypes operandTypes, unsigned __metadataID) |
2899 | { |
2900 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand, operandTypes, __metadataID); |
2901 | if (shouldAssert == Assert) |
2902 | ASSERT(didEmit); |
2903 | return didEmit; |
2904 | } |
2905 | |
2906 | private: |
2907 | template<OpcodeSize size, bool recordOpcode> |
2908 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, OperandTypes operandTypes, unsigned __metadataID) |
2909 | { |
2910 | if (size == OpcodeSize::Wide) |
2911 | gen->alignWideOpcode(); |
2912 | if (Fits<unsigned, size>::check(opcodeID) |
2913 | && Fits<VirtualRegister, size>::check(dst) |
2914 | && Fits<VirtualRegister, size>::check(operand) |
2915 | && Fits<OperandTypes, size>::check(operandTypes) |
2916 | && Fits<unsigned, size>::check(__metadataID) |
2917 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
2918 | if (recordOpcode) |
2919 | gen->recordOpcode(opcodeID); |
2920 | if (size == OpcodeSize::Wide) |
2921 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
2922 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
2923 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
2924 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
2925 | gen->write(Fits<OperandTypes, size>::convert(operandTypes)); |
2926 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
2927 | return true; |
2928 | } |
2929 | return false; |
2930 | } |
2931 | |
2932 | public: |
2933 | template<typename Block> |
2934 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
2935 | { |
2936 | dumper->printLocationAndOp(__location, &"*negate" [!__isWide]); |
2937 | dumper->dumpOperand(m_dst, true); |
2938 | dumper->dumpOperand(m_operand, false); |
2939 | dumper->dumpOperand(m_operandTypes, false); |
2940 | } |
2941 | |
2942 | OpNegate(const uint8_t* stream) |
2943 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
2944 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
2945 | , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[3])) |
2946 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
2947 | { |
2948 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
2949 | } |
2950 | |
2951 | OpNegate(const uint32_t* stream) |
2952 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
2953 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
2954 | , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide>::convert(stream[3])) |
2955 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
2956 | { |
2957 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
2958 | } |
2959 | |
2960 | static OpNegate decode(const uint8_t* stream) |
2961 | { |
2962 | if (*stream != op_wide) |
2963 | return { stream }; |
2964 | |
2965 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
2966 | return { wideStream }; |
2967 | } |
2968 | |
2969 | template<typename Functor> |
2970 | void setDst(VirtualRegister value, Functor func) |
2971 | { |
2972 | if (isWide()) |
2973 | setDst<OpcodeSize::Wide>(value, func); |
2974 | else |
2975 | setDst<OpcodeSize::Narrow>(value, func); |
2976 | } |
2977 | |
2978 | template <OpcodeSize size, typename Functor> |
2979 | void setDst(VirtualRegister value, Functor func) |
2980 | { |
2981 | if (!Fits<VirtualRegister, size>::check(value)) |
2982 | value = func(); |
2983 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
2984 | *stream = Fits<VirtualRegister, size>::convert(value); |
2985 | } |
2986 | |
2987 | template<typename Functor> |
2988 | void setOperand(VirtualRegister value, Functor func) |
2989 | { |
2990 | if (isWide()) |
2991 | setOperand<OpcodeSize::Wide>(value, func); |
2992 | else |
2993 | setOperand<OpcodeSize::Narrow>(value, func); |
2994 | } |
2995 | |
2996 | template <OpcodeSize size, typename Functor> |
2997 | void setOperand(VirtualRegister value, Functor func) |
2998 | { |
2999 | if (!Fits<VirtualRegister, size>::check(value)) |
3000 | value = func(); |
3001 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
3002 | *stream = Fits<VirtualRegister, size>::convert(value); |
3003 | } |
3004 | |
3005 | template<typename Functor> |
3006 | void setOperandTypes(OperandTypes value, Functor func) |
3007 | { |
3008 | if (isWide()) |
3009 | setOperandTypes<OpcodeSize::Wide>(value, func); |
3010 | else |
3011 | setOperandTypes<OpcodeSize::Narrow>(value, func); |
3012 | } |
3013 | |
3014 | template <OpcodeSize size, typename Functor> |
3015 | void setOperandTypes(OperandTypes value, Functor func) |
3016 | { |
3017 | if (!Fits<OperandTypes, size>::check(value)) |
3018 | value = func(); |
3019 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
3020 | *stream = Fits<OperandTypes, size>::convert(value); |
3021 | } |
3022 | |
3023 | struct Metadata { |
3024 | WTF_MAKE_NONCOPYABLE(Metadata); |
3025 | |
3026 | public: |
3027 | Metadata(const OpNegate& __op) |
3028 | : m_arithProfile(__op.m_operandTypes) |
3029 | { } |
3030 | |
3031 | ArithProfile m_arithProfile; |
3032 | }; |
3033 | |
3034 | Metadata& metadata(CodeBlock* codeBlock) const |
3035 | { |
3036 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
3037 | } |
3038 | |
3039 | Metadata& metadata(ExecState* exec) const |
3040 | { |
3041 | return metadata(exec->codeBlock()); |
3042 | } |
3043 | |
3044 | VirtualRegister m_dst; |
3045 | VirtualRegister m_operand; |
3046 | OperandTypes m_operandTypes; |
3047 | unsigned m_metadataID; |
3048 | }; |
3049 | |
3050 | struct OpInByVal : public Instruction { |
3051 | static constexpr OpcodeID opcodeID = op_in_by_val; |
3052 | |
3053 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property) |
3054 | { |
3055 | |
3056 | auto __metadataID = gen->addMetadataFor(opcodeID); |
3057 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, __metadataID) |
3058 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, property, __metadataID); |
3059 | } |
3060 | |
3061 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
3062 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property) |
3063 | { |
3064 | auto __metadataID = gen->addMetadataFor(opcodeID); |
3065 | return emit<size, shouldAssert>(gen, dst, base, property, __metadataID); |
3066 | } |
3067 | |
3068 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
3069 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID) |
3070 | { |
3071 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, __metadataID); |
3072 | if (shouldAssert == Assert) |
3073 | ASSERT(didEmit); |
3074 | return didEmit; |
3075 | } |
3076 | |
3077 | private: |
3078 | template<OpcodeSize size, bool recordOpcode> |
3079 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID) |
3080 | { |
3081 | if (size == OpcodeSize::Wide) |
3082 | gen->alignWideOpcode(); |
3083 | if (Fits<unsigned, size>::check(opcodeID) |
3084 | && Fits<VirtualRegister, size>::check(dst) |
3085 | && Fits<VirtualRegister, size>::check(base) |
3086 | && Fits<VirtualRegister, size>::check(property) |
3087 | && Fits<unsigned, size>::check(__metadataID) |
3088 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
3089 | if (recordOpcode) |
3090 | gen->recordOpcode(opcodeID); |
3091 | if (size == OpcodeSize::Wide) |
3092 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
3093 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
3094 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
3095 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
3096 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
3097 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
3098 | return true; |
3099 | } |
3100 | return false; |
3101 | } |
3102 | |
3103 | public: |
3104 | template<typename Block> |
3105 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
3106 | { |
3107 | dumper->printLocationAndOp(__location, &"*in_by_val" [!__isWide]); |
3108 | dumper->dumpOperand(m_dst, true); |
3109 | dumper->dumpOperand(m_base, false); |
3110 | dumper->dumpOperand(m_property, false); |
3111 | } |
3112 | |
3113 | OpInByVal(const uint8_t* stream) |
3114 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
3115 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
3116 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
3117 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
3118 | { |
3119 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
3120 | } |
3121 | |
3122 | OpInByVal(const uint32_t* stream) |
3123 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
3124 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
3125 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
3126 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
3127 | { |
3128 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
3129 | } |
3130 | |
3131 | static OpInByVal decode(const uint8_t* stream) |
3132 | { |
3133 | if (*stream != op_wide) |
3134 | return { stream }; |
3135 | |
3136 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
3137 | return { wideStream }; |
3138 | } |
3139 | |
3140 | template<typename Functor> |
3141 | void setDst(VirtualRegister value, Functor func) |
3142 | { |
3143 | if (isWide()) |
3144 | setDst<OpcodeSize::Wide>(value, func); |
3145 | else |
3146 | setDst<OpcodeSize::Narrow>(value, func); |
3147 | } |
3148 | |
3149 | template <OpcodeSize size, typename Functor> |
3150 | void setDst(VirtualRegister value, Functor func) |
3151 | { |
3152 | if (!Fits<VirtualRegister, size>::check(value)) |
3153 | value = func(); |
3154 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
3155 | *stream = Fits<VirtualRegister, size>::convert(value); |
3156 | } |
3157 | |
3158 | template<typename Functor> |
3159 | void setBase(VirtualRegister value, Functor func) |
3160 | { |
3161 | if (isWide()) |
3162 | setBase<OpcodeSize::Wide>(value, func); |
3163 | else |
3164 | setBase<OpcodeSize::Narrow>(value, func); |
3165 | } |
3166 | |
3167 | template <OpcodeSize size, typename Functor> |
3168 | void setBase(VirtualRegister value, Functor func) |
3169 | { |
3170 | if (!Fits<VirtualRegister, size>::check(value)) |
3171 | value = func(); |
3172 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
3173 | *stream = Fits<VirtualRegister, size>::convert(value); |
3174 | } |
3175 | |
3176 | template<typename Functor> |
3177 | void setProperty(VirtualRegister value, Functor func) |
3178 | { |
3179 | if (isWide()) |
3180 | setProperty<OpcodeSize::Wide>(value, func); |
3181 | else |
3182 | setProperty<OpcodeSize::Narrow>(value, func); |
3183 | } |
3184 | |
3185 | template <OpcodeSize size, typename Functor> |
3186 | void setProperty(VirtualRegister value, Functor func) |
3187 | { |
3188 | if (!Fits<VirtualRegister, size>::check(value)) |
3189 | value = func(); |
3190 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
3191 | *stream = Fits<VirtualRegister, size>::convert(value); |
3192 | } |
3193 | |
3194 | struct Metadata { |
3195 | WTF_MAKE_NONCOPYABLE(Metadata); |
3196 | |
3197 | public: |
3198 | Metadata(const OpInByVal&) { } |
3199 | |
3200 | ArrayProfile m_arrayProfile; |
3201 | }; |
3202 | |
3203 | Metadata& metadata(CodeBlock* codeBlock) const |
3204 | { |
3205 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
3206 | } |
3207 | |
3208 | Metadata& metadata(ExecState* exec) const |
3209 | { |
3210 | return metadata(exec->codeBlock()); |
3211 | } |
3212 | |
3213 | VirtualRegister m_dst; |
3214 | VirtualRegister m_base; |
3215 | VirtualRegister m_property; |
3216 | unsigned m_metadataID; |
3217 | }; |
3218 | |
3219 | struct OpGetById : public Instruction { |
3220 | static constexpr OpcodeID opcodeID = op_get_by_id; |
3221 | |
3222 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property) |
3223 | { |
3224 | |
3225 | auto __metadataID = gen->addMetadataFor(opcodeID); |
3226 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, __metadataID) |
3227 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, property, __metadataID); |
3228 | } |
3229 | |
3230 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
3231 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property) |
3232 | { |
3233 | auto __metadataID = gen->addMetadataFor(opcodeID); |
3234 | return emit<size, shouldAssert>(gen, dst, base, property, __metadataID); |
3235 | } |
3236 | |
3237 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
3238 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID) |
3239 | { |
3240 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, __metadataID); |
3241 | if (shouldAssert == Assert) |
3242 | ASSERT(didEmit); |
3243 | return didEmit; |
3244 | } |
3245 | |
3246 | private: |
3247 | template<OpcodeSize size, bool recordOpcode> |
3248 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID) |
3249 | { |
3250 | if (size == OpcodeSize::Wide) |
3251 | gen->alignWideOpcode(); |
3252 | if (Fits<unsigned, size>::check(opcodeID) |
3253 | && Fits<VirtualRegister, size>::check(dst) |
3254 | && Fits<VirtualRegister, size>::check(base) |
3255 | && Fits<unsigned, size>::check(property) |
3256 | && Fits<unsigned, size>::check(__metadataID) |
3257 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
3258 | if (recordOpcode) |
3259 | gen->recordOpcode(opcodeID); |
3260 | if (size == OpcodeSize::Wide) |
3261 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
3262 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
3263 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
3264 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
3265 | gen->write(Fits<unsigned, size>::convert(property)); |
3266 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
3267 | return true; |
3268 | } |
3269 | return false; |
3270 | } |
3271 | |
3272 | public: |
3273 | template<typename Block> |
3274 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
3275 | { |
3276 | dumper->printLocationAndOp(__location, &"*get_by_id" [!__isWide]); |
3277 | dumper->dumpOperand(m_dst, true); |
3278 | dumper->dumpOperand(m_base, false); |
3279 | dumper->dumpOperand(m_property, false); |
3280 | } |
3281 | |
3282 | OpGetById(const uint8_t* stream) |
3283 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
3284 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
3285 | , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
3286 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
3287 | { |
3288 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
3289 | } |
3290 | |
3291 | OpGetById(const uint32_t* stream) |
3292 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
3293 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
3294 | , m_property(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
3295 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
3296 | { |
3297 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
3298 | } |
3299 | |
3300 | static OpGetById decode(const uint8_t* stream) |
3301 | { |
3302 | if (*stream != op_wide) |
3303 | return { stream }; |
3304 | |
3305 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
3306 | return { wideStream }; |
3307 | } |
3308 | |
3309 | template<typename Functor> |
3310 | void setDst(VirtualRegister value, Functor func) |
3311 | { |
3312 | if (isWide()) |
3313 | setDst<OpcodeSize::Wide>(value, func); |
3314 | else |
3315 | setDst<OpcodeSize::Narrow>(value, func); |
3316 | } |
3317 | |
3318 | template <OpcodeSize size, typename Functor> |
3319 | void setDst(VirtualRegister value, Functor func) |
3320 | { |
3321 | if (!Fits<VirtualRegister, size>::check(value)) |
3322 | value = func(); |
3323 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
3324 | *stream = Fits<VirtualRegister, size>::convert(value); |
3325 | } |
3326 | |
3327 | template<typename Functor> |
3328 | void setBase(VirtualRegister value, Functor func) |
3329 | { |
3330 | if (isWide()) |
3331 | setBase<OpcodeSize::Wide>(value, func); |
3332 | else |
3333 | setBase<OpcodeSize::Narrow>(value, func); |
3334 | } |
3335 | |
3336 | template <OpcodeSize size, typename Functor> |
3337 | void setBase(VirtualRegister value, Functor func) |
3338 | { |
3339 | if (!Fits<VirtualRegister, size>::check(value)) |
3340 | value = func(); |
3341 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
3342 | *stream = Fits<VirtualRegister, size>::convert(value); |
3343 | } |
3344 | |
3345 | template<typename Functor> |
3346 | void setProperty(unsigned value, Functor func) |
3347 | { |
3348 | if (isWide()) |
3349 | setProperty<OpcodeSize::Wide>(value, func); |
3350 | else |
3351 | setProperty<OpcodeSize::Narrow>(value, func); |
3352 | } |
3353 | |
3354 | template <OpcodeSize size, typename Functor> |
3355 | void setProperty(unsigned value, Functor func) |
3356 | { |
3357 | if (!Fits<unsigned, size>::check(value)) |
3358 | value = func(); |
3359 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
3360 | *stream = Fits<unsigned, size>::convert(value); |
3361 | } |
3362 | |
3363 | struct Metadata { |
3364 | WTF_MAKE_NONCOPYABLE(Metadata); |
3365 | |
3366 | public: |
3367 | Metadata(const OpGetById&) { } |
3368 | |
3369 | GetByIdMode m_mode; |
3370 | unsigned m_hitCountForLLIntCaching; |
3371 | GetByIdModeMetadata m_modeMetadata; |
3372 | ValueProfile m_profile; |
3373 | }; |
3374 | |
3375 | Metadata& metadata(CodeBlock* codeBlock) const |
3376 | { |
3377 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
3378 | } |
3379 | |
3380 | Metadata& metadata(ExecState* exec) const |
3381 | { |
3382 | return metadata(exec->codeBlock()); |
3383 | } |
3384 | |
3385 | VirtualRegister m_dst; |
3386 | VirtualRegister m_base; |
3387 | unsigned m_property; |
3388 | unsigned m_metadataID; |
3389 | }; |
3390 | |
3391 | struct OpGetByIdWithThis : public Instruction { |
3392 | static constexpr OpcodeID opcodeID = op_get_by_id_with_this; |
3393 | |
3394 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property) |
3395 | { |
3396 | |
3397 | auto __metadataID = gen->addMetadataFor(opcodeID); |
3398 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID) |
3399 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, thisValue, property, __metadataID); |
3400 | } |
3401 | |
3402 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
3403 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property) |
3404 | { |
3405 | auto __metadataID = gen->addMetadataFor(opcodeID); |
3406 | return emit<size, shouldAssert>(gen, dst, base, thisValue, property, __metadataID); |
3407 | } |
3408 | |
3409 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
3410 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property, unsigned __metadataID) |
3411 | { |
3412 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, thisValue, property, __metadataID); |
3413 | if (shouldAssert == Assert) |
3414 | ASSERT(didEmit); |
3415 | return didEmit; |
3416 | } |
3417 | |
3418 | private: |
3419 | template<OpcodeSize size, bool recordOpcode> |
3420 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property, unsigned __metadataID) |
3421 | { |
3422 | if (size == OpcodeSize::Wide) |
3423 | gen->alignWideOpcode(); |
3424 | if (Fits<unsigned, size>::check(opcodeID) |
3425 | && Fits<VirtualRegister, size>::check(dst) |
3426 | && Fits<VirtualRegister, size>::check(base) |
3427 | && Fits<VirtualRegister, size>::check(thisValue) |
3428 | && Fits<unsigned, size>::check(property) |
3429 | && Fits<unsigned, size>::check(__metadataID) |
3430 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
3431 | if (recordOpcode) |
3432 | gen->recordOpcode(opcodeID); |
3433 | if (size == OpcodeSize::Wide) |
3434 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
3435 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
3436 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
3437 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
3438 | gen->write(Fits<VirtualRegister, size>::convert(thisValue)); |
3439 | gen->write(Fits<unsigned, size>::convert(property)); |
3440 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
3441 | return true; |
3442 | } |
3443 | return false; |
3444 | } |
3445 | |
3446 | public: |
3447 | template<typename Block> |
3448 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
3449 | { |
3450 | dumper->printLocationAndOp(__location, &"*get_by_id_with_this" [!__isWide]); |
3451 | dumper->dumpOperand(m_dst, true); |
3452 | dumper->dumpOperand(m_base, false); |
3453 | dumper->dumpOperand(m_thisValue, false); |
3454 | dumper->dumpOperand(m_property, false); |
3455 | } |
3456 | |
3457 | OpGetByIdWithThis(const uint8_t* stream) |
3458 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
3459 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
3460 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
3461 | , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
3462 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
3463 | { |
3464 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
3465 | } |
3466 | |
3467 | OpGetByIdWithThis(const uint32_t* stream) |
3468 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
3469 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
3470 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
3471 | , m_property(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
3472 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
3473 | { |
3474 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
3475 | } |
3476 | |
3477 | static OpGetByIdWithThis decode(const uint8_t* stream) |
3478 | { |
3479 | if (*stream != op_wide) |
3480 | return { stream }; |
3481 | |
3482 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
3483 | return { wideStream }; |
3484 | } |
3485 | |
3486 | template<typename Functor> |
3487 | void setDst(VirtualRegister value, Functor func) |
3488 | { |
3489 | if (isWide()) |
3490 | setDst<OpcodeSize::Wide>(value, func); |
3491 | else |
3492 | setDst<OpcodeSize::Narrow>(value, func); |
3493 | } |
3494 | |
3495 | template <OpcodeSize size, typename Functor> |
3496 | void setDst(VirtualRegister value, Functor func) |
3497 | { |
3498 | if (!Fits<VirtualRegister, size>::check(value)) |
3499 | value = func(); |
3500 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
3501 | *stream = Fits<VirtualRegister, size>::convert(value); |
3502 | } |
3503 | |
3504 | template<typename Functor> |
3505 | void setBase(VirtualRegister value, Functor func) |
3506 | { |
3507 | if (isWide()) |
3508 | setBase<OpcodeSize::Wide>(value, func); |
3509 | else |
3510 | setBase<OpcodeSize::Narrow>(value, func); |
3511 | } |
3512 | |
3513 | template <OpcodeSize size, typename Functor> |
3514 | void setBase(VirtualRegister value, Functor func) |
3515 | { |
3516 | if (!Fits<VirtualRegister, size>::check(value)) |
3517 | value = func(); |
3518 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
3519 | *stream = Fits<VirtualRegister, size>::convert(value); |
3520 | } |
3521 | |
3522 | template<typename Functor> |
3523 | void setThisValue(VirtualRegister value, Functor func) |
3524 | { |
3525 | if (isWide()) |
3526 | setThisValue<OpcodeSize::Wide>(value, func); |
3527 | else |
3528 | setThisValue<OpcodeSize::Narrow>(value, func); |
3529 | } |
3530 | |
3531 | template <OpcodeSize size, typename Functor> |
3532 | void setThisValue(VirtualRegister value, Functor func) |
3533 | { |
3534 | if (!Fits<VirtualRegister, size>::check(value)) |
3535 | value = func(); |
3536 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
3537 | *stream = Fits<VirtualRegister, size>::convert(value); |
3538 | } |
3539 | |
3540 | template<typename Functor> |
3541 | void setProperty(unsigned value, Functor func) |
3542 | { |
3543 | if (isWide()) |
3544 | setProperty<OpcodeSize::Wide>(value, func); |
3545 | else |
3546 | setProperty<OpcodeSize::Narrow>(value, func); |
3547 | } |
3548 | |
3549 | template <OpcodeSize size, typename Functor> |
3550 | void setProperty(unsigned value, Functor func) |
3551 | { |
3552 | if (!Fits<unsigned, size>::check(value)) |
3553 | value = func(); |
3554 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
3555 | *stream = Fits<unsigned, size>::convert(value); |
3556 | } |
3557 | |
3558 | struct Metadata { |
3559 | WTF_MAKE_NONCOPYABLE(Metadata); |
3560 | |
3561 | public: |
3562 | Metadata(const OpGetByIdWithThis&) { } |
3563 | |
3564 | ValueProfile m_profile; |
3565 | }; |
3566 | |
3567 | Metadata& metadata(CodeBlock* codeBlock) const |
3568 | { |
3569 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
3570 | } |
3571 | |
3572 | Metadata& metadata(ExecState* exec) const |
3573 | { |
3574 | return metadata(exec->codeBlock()); |
3575 | } |
3576 | |
3577 | VirtualRegister m_dst; |
3578 | VirtualRegister m_base; |
3579 | VirtualRegister m_thisValue; |
3580 | unsigned m_property; |
3581 | unsigned m_metadataID; |
3582 | }; |
3583 | |
3584 | struct OpGetByValWithThis : public Instruction { |
3585 | static constexpr OpcodeID opcodeID = op_get_by_val_with_this; |
3586 | |
3587 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property) |
3588 | { |
3589 | |
3590 | auto __metadataID = gen->addMetadataFor(opcodeID); |
3591 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID) |
3592 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, thisValue, property, __metadataID); |
3593 | } |
3594 | |
3595 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
3596 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property) |
3597 | { |
3598 | auto __metadataID = gen->addMetadataFor(opcodeID); |
3599 | return emit<size, shouldAssert>(gen, dst, base, thisValue, property, __metadataID); |
3600 | } |
3601 | |
3602 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
3603 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, unsigned __metadataID) |
3604 | { |
3605 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, thisValue, property, __metadataID); |
3606 | if (shouldAssert == Assert) |
3607 | ASSERT(didEmit); |
3608 | return didEmit; |
3609 | } |
3610 | |
3611 | private: |
3612 | template<OpcodeSize size, bool recordOpcode> |
3613 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, unsigned __metadataID) |
3614 | { |
3615 | if (size == OpcodeSize::Wide) |
3616 | gen->alignWideOpcode(); |
3617 | if (Fits<unsigned, size>::check(opcodeID) |
3618 | && Fits<VirtualRegister, size>::check(dst) |
3619 | && Fits<VirtualRegister, size>::check(base) |
3620 | && Fits<VirtualRegister, size>::check(thisValue) |
3621 | && Fits<VirtualRegister, size>::check(property) |
3622 | && Fits<unsigned, size>::check(__metadataID) |
3623 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
3624 | if (recordOpcode) |
3625 | gen->recordOpcode(opcodeID); |
3626 | if (size == OpcodeSize::Wide) |
3627 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
3628 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
3629 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
3630 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
3631 | gen->write(Fits<VirtualRegister, size>::convert(thisValue)); |
3632 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
3633 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
3634 | return true; |
3635 | } |
3636 | return false; |
3637 | } |
3638 | |
3639 | public: |
3640 | template<typename Block> |
3641 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
3642 | { |
3643 | dumper->printLocationAndOp(__location, &"*get_by_val_with_this" [!__isWide]); |
3644 | dumper->dumpOperand(m_dst, true); |
3645 | dumper->dumpOperand(m_base, false); |
3646 | dumper->dumpOperand(m_thisValue, false); |
3647 | dumper->dumpOperand(m_property, false); |
3648 | } |
3649 | |
3650 | OpGetByValWithThis(const uint8_t* stream) |
3651 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
3652 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
3653 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
3654 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
3655 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
3656 | { |
3657 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
3658 | } |
3659 | |
3660 | OpGetByValWithThis(const uint32_t* stream) |
3661 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
3662 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
3663 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
3664 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
3665 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
3666 | { |
3667 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
3668 | } |
3669 | |
3670 | static OpGetByValWithThis decode(const uint8_t* stream) |
3671 | { |
3672 | if (*stream != op_wide) |
3673 | return { stream }; |
3674 | |
3675 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
3676 | return { wideStream }; |
3677 | } |
3678 | |
3679 | template<typename Functor> |
3680 | void setDst(VirtualRegister value, Functor func) |
3681 | { |
3682 | if (isWide()) |
3683 | setDst<OpcodeSize::Wide>(value, func); |
3684 | else |
3685 | setDst<OpcodeSize::Narrow>(value, func); |
3686 | } |
3687 | |
3688 | template <OpcodeSize size, typename Functor> |
3689 | void setDst(VirtualRegister value, Functor func) |
3690 | { |
3691 | if (!Fits<VirtualRegister, size>::check(value)) |
3692 | value = func(); |
3693 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
3694 | *stream = Fits<VirtualRegister, size>::convert(value); |
3695 | } |
3696 | |
3697 | template<typename Functor> |
3698 | void setBase(VirtualRegister value, Functor func) |
3699 | { |
3700 | if (isWide()) |
3701 | setBase<OpcodeSize::Wide>(value, func); |
3702 | else |
3703 | setBase<OpcodeSize::Narrow>(value, func); |
3704 | } |
3705 | |
3706 | template <OpcodeSize size, typename Functor> |
3707 | void setBase(VirtualRegister value, Functor func) |
3708 | { |
3709 | if (!Fits<VirtualRegister, size>::check(value)) |
3710 | value = func(); |
3711 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
3712 | *stream = Fits<VirtualRegister, size>::convert(value); |
3713 | } |
3714 | |
3715 | template<typename Functor> |
3716 | void setThisValue(VirtualRegister value, Functor func) |
3717 | { |
3718 | if (isWide()) |
3719 | setThisValue<OpcodeSize::Wide>(value, func); |
3720 | else |
3721 | setThisValue<OpcodeSize::Narrow>(value, func); |
3722 | } |
3723 | |
3724 | template <OpcodeSize size, typename Functor> |
3725 | void setThisValue(VirtualRegister value, Functor func) |
3726 | { |
3727 | if (!Fits<VirtualRegister, size>::check(value)) |
3728 | value = func(); |
3729 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
3730 | *stream = Fits<VirtualRegister, size>::convert(value); |
3731 | } |
3732 | |
3733 | template<typename Functor> |
3734 | void setProperty(VirtualRegister value, Functor func) |
3735 | { |
3736 | if (isWide()) |
3737 | setProperty<OpcodeSize::Wide>(value, func); |
3738 | else |
3739 | setProperty<OpcodeSize::Narrow>(value, func); |
3740 | } |
3741 | |
3742 | template <OpcodeSize size, typename Functor> |
3743 | void setProperty(VirtualRegister value, Functor func) |
3744 | { |
3745 | if (!Fits<VirtualRegister, size>::check(value)) |
3746 | value = func(); |
3747 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
3748 | *stream = Fits<VirtualRegister, size>::convert(value); |
3749 | } |
3750 | |
3751 | struct Metadata { |
3752 | WTF_MAKE_NONCOPYABLE(Metadata); |
3753 | |
3754 | public: |
3755 | Metadata(const OpGetByValWithThis&) { } |
3756 | |
3757 | ValueProfile m_profile; |
3758 | }; |
3759 | |
3760 | Metadata& metadata(CodeBlock* codeBlock) const |
3761 | { |
3762 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
3763 | } |
3764 | |
3765 | Metadata& metadata(ExecState* exec) const |
3766 | { |
3767 | return metadata(exec->codeBlock()); |
3768 | } |
3769 | |
3770 | VirtualRegister m_dst; |
3771 | VirtualRegister m_base; |
3772 | VirtualRegister m_thisValue; |
3773 | VirtualRegister m_property; |
3774 | unsigned m_metadataID; |
3775 | }; |
3776 | |
3777 | struct OpGetByIdDirect : public Instruction { |
3778 | static constexpr OpcodeID opcodeID = op_get_by_id_direct; |
3779 | |
3780 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property) |
3781 | { |
3782 | |
3783 | auto __metadataID = gen->addMetadataFor(opcodeID); |
3784 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, __metadataID) |
3785 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, property, __metadataID); |
3786 | } |
3787 | |
3788 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
3789 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property) |
3790 | { |
3791 | auto __metadataID = gen->addMetadataFor(opcodeID); |
3792 | return emit<size, shouldAssert>(gen, dst, base, property, __metadataID); |
3793 | } |
3794 | |
3795 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
3796 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID) |
3797 | { |
3798 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, __metadataID); |
3799 | if (shouldAssert == Assert) |
3800 | ASSERT(didEmit); |
3801 | return didEmit; |
3802 | } |
3803 | |
3804 | private: |
3805 | template<OpcodeSize size, bool recordOpcode> |
3806 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID) |
3807 | { |
3808 | if (size == OpcodeSize::Wide) |
3809 | gen->alignWideOpcode(); |
3810 | if (Fits<unsigned, size>::check(opcodeID) |
3811 | && Fits<VirtualRegister, size>::check(dst) |
3812 | && Fits<VirtualRegister, size>::check(base) |
3813 | && Fits<unsigned, size>::check(property) |
3814 | && Fits<unsigned, size>::check(__metadataID) |
3815 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
3816 | if (recordOpcode) |
3817 | gen->recordOpcode(opcodeID); |
3818 | if (size == OpcodeSize::Wide) |
3819 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
3820 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
3821 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
3822 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
3823 | gen->write(Fits<unsigned, size>::convert(property)); |
3824 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
3825 | return true; |
3826 | } |
3827 | return false; |
3828 | } |
3829 | |
3830 | public: |
3831 | template<typename Block> |
3832 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
3833 | { |
3834 | dumper->printLocationAndOp(__location, &"*get_by_id_direct" [!__isWide]); |
3835 | dumper->dumpOperand(m_dst, true); |
3836 | dumper->dumpOperand(m_base, false); |
3837 | dumper->dumpOperand(m_property, false); |
3838 | } |
3839 | |
3840 | OpGetByIdDirect(const uint8_t* stream) |
3841 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
3842 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
3843 | , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
3844 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
3845 | { |
3846 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
3847 | } |
3848 | |
3849 | OpGetByIdDirect(const uint32_t* stream) |
3850 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
3851 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
3852 | , m_property(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
3853 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
3854 | { |
3855 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
3856 | } |
3857 | |
3858 | static OpGetByIdDirect decode(const uint8_t* stream) |
3859 | { |
3860 | if (*stream != op_wide) |
3861 | return { stream }; |
3862 | |
3863 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
3864 | return { wideStream }; |
3865 | } |
3866 | |
3867 | template<typename Functor> |
3868 | void setDst(VirtualRegister value, Functor func) |
3869 | { |
3870 | if (isWide()) |
3871 | setDst<OpcodeSize::Wide>(value, func); |
3872 | else |
3873 | setDst<OpcodeSize::Narrow>(value, func); |
3874 | } |
3875 | |
3876 | template <OpcodeSize size, typename Functor> |
3877 | void setDst(VirtualRegister value, Functor func) |
3878 | { |
3879 | if (!Fits<VirtualRegister, size>::check(value)) |
3880 | value = func(); |
3881 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
3882 | *stream = Fits<VirtualRegister, size>::convert(value); |
3883 | } |
3884 | |
3885 | template<typename Functor> |
3886 | void setBase(VirtualRegister value, Functor func) |
3887 | { |
3888 | if (isWide()) |
3889 | setBase<OpcodeSize::Wide>(value, func); |
3890 | else |
3891 | setBase<OpcodeSize::Narrow>(value, func); |
3892 | } |
3893 | |
3894 | template <OpcodeSize size, typename Functor> |
3895 | void setBase(VirtualRegister value, Functor func) |
3896 | { |
3897 | if (!Fits<VirtualRegister, size>::check(value)) |
3898 | value = func(); |
3899 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
3900 | *stream = Fits<VirtualRegister, size>::convert(value); |
3901 | } |
3902 | |
3903 | template<typename Functor> |
3904 | void setProperty(unsigned value, Functor func) |
3905 | { |
3906 | if (isWide()) |
3907 | setProperty<OpcodeSize::Wide>(value, func); |
3908 | else |
3909 | setProperty<OpcodeSize::Narrow>(value, func); |
3910 | } |
3911 | |
3912 | template <OpcodeSize size, typename Functor> |
3913 | void setProperty(unsigned value, Functor func) |
3914 | { |
3915 | if (!Fits<unsigned, size>::check(value)) |
3916 | value = func(); |
3917 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
3918 | *stream = Fits<unsigned, size>::convert(value); |
3919 | } |
3920 | |
3921 | struct Metadata { |
3922 | WTF_MAKE_NONCOPYABLE(Metadata); |
3923 | |
3924 | public: |
3925 | Metadata(const OpGetByIdDirect&) { } |
3926 | |
3927 | ValueProfile m_profile; |
3928 | StructureID m_structureID; |
3929 | unsigned m_offset; |
3930 | }; |
3931 | |
3932 | Metadata& metadata(CodeBlock* codeBlock) const |
3933 | { |
3934 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
3935 | } |
3936 | |
3937 | Metadata& metadata(ExecState* exec) const |
3938 | { |
3939 | return metadata(exec->codeBlock()); |
3940 | } |
3941 | |
3942 | VirtualRegister m_dst; |
3943 | VirtualRegister m_base; |
3944 | unsigned m_property; |
3945 | unsigned m_metadataID; |
3946 | }; |
3947 | |
3948 | struct OpTryGetById : public Instruction { |
3949 | static constexpr OpcodeID opcodeID = op_try_get_by_id; |
3950 | |
3951 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property) |
3952 | { |
3953 | |
3954 | auto __metadataID = gen->addMetadataFor(opcodeID); |
3955 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, __metadataID) |
3956 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, property, __metadataID); |
3957 | } |
3958 | |
3959 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
3960 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property) |
3961 | { |
3962 | auto __metadataID = gen->addMetadataFor(opcodeID); |
3963 | return emit<size, shouldAssert>(gen, dst, base, property, __metadataID); |
3964 | } |
3965 | |
3966 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
3967 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID) |
3968 | { |
3969 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, __metadataID); |
3970 | if (shouldAssert == Assert) |
3971 | ASSERT(didEmit); |
3972 | return didEmit; |
3973 | } |
3974 | |
3975 | private: |
3976 | template<OpcodeSize size, bool recordOpcode> |
3977 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID) |
3978 | { |
3979 | if (size == OpcodeSize::Wide) |
3980 | gen->alignWideOpcode(); |
3981 | if (Fits<unsigned, size>::check(opcodeID) |
3982 | && Fits<VirtualRegister, size>::check(dst) |
3983 | && Fits<VirtualRegister, size>::check(base) |
3984 | && Fits<unsigned, size>::check(property) |
3985 | && Fits<unsigned, size>::check(__metadataID) |
3986 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
3987 | if (recordOpcode) |
3988 | gen->recordOpcode(opcodeID); |
3989 | if (size == OpcodeSize::Wide) |
3990 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
3991 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
3992 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
3993 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
3994 | gen->write(Fits<unsigned, size>::convert(property)); |
3995 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
3996 | return true; |
3997 | } |
3998 | return false; |
3999 | } |
4000 | |
4001 | public: |
4002 | template<typename Block> |
4003 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
4004 | { |
4005 | dumper->printLocationAndOp(__location, &"*try_get_by_id" [!__isWide]); |
4006 | dumper->dumpOperand(m_dst, true); |
4007 | dumper->dumpOperand(m_base, false); |
4008 | dumper->dumpOperand(m_property, false); |
4009 | } |
4010 | |
4011 | OpTryGetById(const uint8_t* stream) |
4012 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
4013 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
4014 | , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
4015 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
4016 | { |
4017 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
4018 | } |
4019 | |
4020 | OpTryGetById(const uint32_t* stream) |
4021 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
4022 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
4023 | , m_property(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
4024 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
4025 | { |
4026 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
4027 | } |
4028 | |
4029 | static OpTryGetById decode(const uint8_t* stream) |
4030 | { |
4031 | if (*stream != op_wide) |
4032 | return { stream }; |
4033 | |
4034 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
4035 | return { wideStream }; |
4036 | } |
4037 | |
4038 | template<typename Functor> |
4039 | void setDst(VirtualRegister value, Functor func) |
4040 | { |
4041 | if (isWide()) |
4042 | setDst<OpcodeSize::Wide>(value, func); |
4043 | else |
4044 | setDst<OpcodeSize::Narrow>(value, func); |
4045 | } |
4046 | |
4047 | template <OpcodeSize size, typename Functor> |
4048 | void setDst(VirtualRegister value, Functor func) |
4049 | { |
4050 | if (!Fits<VirtualRegister, size>::check(value)) |
4051 | value = func(); |
4052 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
4053 | *stream = Fits<VirtualRegister, size>::convert(value); |
4054 | } |
4055 | |
4056 | template<typename Functor> |
4057 | void setBase(VirtualRegister value, Functor func) |
4058 | { |
4059 | if (isWide()) |
4060 | setBase<OpcodeSize::Wide>(value, func); |
4061 | else |
4062 | setBase<OpcodeSize::Narrow>(value, func); |
4063 | } |
4064 | |
4065 | template <OpcodeSize size, typename Functor> |
4066 | void setBase(VirtualRegister value, Functor func) |
4067 | { |
4068 | if (!Fits<VirtualRegister, size>::check(value)) |
4069 | value = func(); |
4070 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
4071 | *stream = Fits<VirtualRegister, size>::convert(value); |
4072 | } |
4073 | |
4074 | template<typename Functor> |
4075 | void setProperty(unsigned value, Functor func) |
4076 | { |
4077 | if (isWide()) |
4078 | setProperty<OpcodeSize::Wide>(value, func); |
4079 | else |
4080 | setProperty<OpcodeSize::Narrow>(value, func); |
4081 | } |
4082 | |
4083 | template <OpcodeSize size, typename Functor> |
4084 | void setProperty(unsigned value, Functor func) |
4085 | { |
4086 | if (!Fits<unsigned, size>::check(value)) |
4087 | value = func(); |
4088 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
4089 | *stream = Fits<unsigned, size>::convert(value); |
4090 | } |
4091 | |
4092 | struct Metadata { |
4093 | WTF_MAKE_NONCOPYABLE(Metadata); |
4094 | |
4095 | public: |
4096 | Metadata(const OpTryGetById&) { } |
4097 | |
4098 | ValueProfile m_profile; |
4099 | }; |
4100 | |
4101 | Metadata& metadata(CodeBlock* codeBlock) const |
4102 | { |
4103 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
4104 | } |
4105 | |
4106 | Metadata& metadata(ExecState* exec) const |
4107 | { |
4108 | return metadata(exec->codeBlock()); |
4109 | } |
4110 | |
4111 | VirtualRegister m_dst; |
4112 | VirtualRegister m_base; |
4113 | unsigned m_property; |
4114 | unsigned m_metadataID; |
4115 | }; |
4116 | |
4117 | struct OpPutById : public Instruction { |
4118 | static constexpr OpcodeID opcodeID = op_put_by_id; |
4119 | |
4120 | static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags) |
4121 | { |
4122 | |
4123 | auto __metadataID = gen->addMetadataFor(opcodeID); |
4124 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, value, flags, __metadataID) |
4125 | || emit<OpcodeSize::Wide, Assert, true>(gen, base, property, value, flags, __metadataID); |
4126 | } |
4127 | |
4128 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
4129 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags) |
4130 | { |
4131 | auto __metadataID = gen->addMetadataFor(opcodeID); |
4132 | return emit<size, shouldAssert>(gen, base, property, value, flags, __metadataID); |
4133 | } |
4134 | |
4135 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
4136 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags, unsigned __metadataID) |
4137 | { |
4138 | bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, value, flags, __metadataID); |
4139 | if (shouldAssert == Assert) |
4140 | ASSERT(didEmit); |
4141 | return didEmit; |
4142 | } |
4143 | |
4144 | private: |
4145 | template<OpcodeSize size, bool recordOpcode> |
4146 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags, unsigned __metadataID) |
4147 | { |
4148 | if (size == OpcodeSize::Wide) |
4149 | gen->alignWideOpcode(); |
4150 | if (Fits<unsigned, size>::check(opcodeID) |
4151 | && Fits<VirtualRegister, size>::check(base) |
4152 | && Fits<unsigned, size>::check(property) |
4153 | && Fits<VirtualRegister, size>::check(value) |
4154 | && Fits<PutByIdFlags, size>::check(flags) |
4155 | && Fits<unsigned, size>::check(__metadataID) |
4156 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
4157 | if (recordOpcode) |
4158 | gen->recordOpcode(opcodeID); |
4159 | if (size == OpcodeSize::Wide) |
4160 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
4161 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
4162 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
4163 | gen->write(Fits<unsigned, size>::convert(property)); |
4164 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
4165 | gen->write(Fits<PutByIdFlags, size>::convert(flags)); |
4166 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
4167 | return true; |
4168 | } |
4169 | return false; |
4170 | } |
4171 | |
4172 | public: |
4173 | template<typename Block> |
4174 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
4175 | { |
4176 | dumper->printLocationAndOp(__location, &"*put_by_id" [!__isWide]); |
4177 | dumper->dumpOperand(m_base, true); |
4178 | dumper->dumpOperand(m_property, false); |
4179 | dumper->dumpOperand(m_value, false); |
4180 | dumper->dumpOperand(m_flags, false); |
4181 | } |
4182 | |
4183 | OpPutById(const uint8_t* stream) |
4184 | : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
4185 | , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2])) |
4186 | , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
4187 | , m_flags(Fits<PutByIdFlags, OpcodeSize::Narrow>::convert(stream[4])) |
4188 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
4189 | { |
4190 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
4191 | } |
4192 | |
4193 | OpPutById(const uint32_t* stream) |
4194 | : m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
4195 | , m_property(Fits<unsigned, OpcodeSize::Wide>::convert(stream[2])) |
4196 | , m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
4197 | , m_flags(Fits<PutByIdFlags, OpcodeSize::Wide>::convert(stream[4])) |
4198 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
4199 | { |
4200 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
4201 | } |
4202 | |
4203 | static OpPutById decode(const uint8_t* stream) |
4204 | { |
4205 | if (*stream != op_wide) |
4206 | return { stream }; |
4207 | |
4208 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
4209 | return { wideStream }; |
4210 | } |
4211 | |
4212 | template<typename Functor> |
4213 | void setBase(VirtualRegister value, Functor func) |
4214 | { |
4215 | if (isWide()) |
4216 | setBase<OpcodeSize::Wide>(value, func); |
4217 | else |
4218 | setBase<OpcodeSize::Narrow>(value, func); |
4219 | } |
4220 | |
4221 | template <OpcodeSize size, typename Functor> |
4222 | void setBase(VirtualRegister value, Functor func) |
4223 | { |
4224 | if (!Fits<VirtualRegister, size>::check(value)) |
4225 | value = func(); |
4226 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
4227 | *stream = Fits<VirtualRegister, size>::convert(value); |
4228 | } |
4229 | |
4230 | template<typename Functor> |
4231 | void setProperty(unsigned value, Functor func) |
4232 | { |
4233 | if (isWide()) |
4234 | setProperty<OpcodeSize::Wide>(value, func); |
4235 | else |
4236 | setProperty<OpcodeSize::Narrow>(value, func); |
4237 | } |
4238 | |
4239 | template <OpcodeSize size, typename Functor> |
4240 | void setProperty(unsigned value, Functor func) |
4241 | { |
4242 | if (!Fits<unsigned, size>::check(value)) |
4243 | value = func(); |
4244 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
4245 | *stream = Fits<unsigned, size>::convert(value); |
4246 | } |
4247 | |
4248 | template<typename Functor> |
4249 | void setValue(VirtualRegister value, Functor func) |
4250 | { |
4251 | if (isWide()) |
4252 | setValue<OpcodeSize::Wide>(value, func); |
4253 | else |
4254 | setValue<OpcodeSize::Narrow>(value, func); |
4255 | } |
4256 | |
4257 | template <OpcodeSize size, typename Functor> |
4258 | void setValue(VirtualRegister value, Functor func) |
4259 | { |
4260 | if (!Fits<VirtualRegister, size>::check(value)) |
4261 | value = func(); |
4262 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
4263 | *stream = Fits<VirtualRegister, size>::convert(value); |
4264 | } |
4265 | |
4266 | template<typename Functor> |
4267 | void setFlags(PutByIdFlags value, Functor func) |
4268 | { |
4269 | if (isWide()) |
4270 | setFlags<OpcodeSize::Wide>(value, func); |
4271 | else |
4272 | setFlags<OpcodeSize::Narrow>(value, func); |
4273 | } |
4274 | |
4275 | template <OpcodeSize size, typename Functor> |
4276 | void setFlags(PutByIdFlags value, Functor func) |
4277 | { |
4278 | if (!Fits<PutByIdFlags, size>::check(value)) |
4279 | value = func(); |
4280 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
4281 | *stream = Fits<PutByIdFlags, size>::convert(value); |
4282 | } |
4283 | |
4284 | struct Metadata { |
4285 | WTF_MAKE_NONCOPYABLE(Metadata); |
4286 | |
4287 | public: |
4288 | Metadata(const OpPutById&) { } |
4289 | |
4290 | StructureID m_oldStructureID; |
4291 | unsigned m_offset; |
4292 | StructureID m_newStructureID; |
4293 | WriteBarrierBase<StructureChain> m_structureChain; |
4294 | }; |
4295 | |
4296 | Metadata& metadata(CodeBlock* codeBlock) const |
4297 | { |
4298 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
4299 | } |
4300 | |
4301 | Metadata& metadata(ExecState* exec) const |
4302 | { |
4303 | return metadata(exec->codeBlock()); |
4304 | } |
4305 | |
4306 | VirtualRegister m_base; |
4307 | unsigned m_property; |
4308 | VirtualRegister m_value; |
4309 | PutByIdFlags m_flags; |
4310 | unsigned m_metadataID; |
4311 | }; |
4312 | |
4313 | struct OpGetByVal : public Instruction { |
4314 | static constexpr OpcodeID opcodeID = op_get_by_val; |
4315 | |
4316 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property) |
4317 | { |
4318 | |
4319 | auto __metadataID = gen->addMetadataFor(opcodeID); |
4320 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, __metadataID) |
4321 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, property, __metadataID); |
4322 | } |
4323 | |
4324 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
4325 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property) |
4326 | { |
4327 | auto __metadataID = gen->addMetadataFor(opcodeID); |
4328 | return emit<size, shouldAssert>(gen, dst, base, property, __metadataID); |
4329 | } |
4330 | |
4331 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
4332 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID) |
4333 | { |
4334 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, __metadataID); |
4335 | if (shouldAssert == Assert) |
4336 | ASSERT(didEmit); |
4337 | return didEmit; |
4338 | } |
4339 | |
4340 | private: |
4341 | template<OpcodeSize size, bool recordOpcode> |
4342 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID) |
4343 | { |
4344 | if (size == OpcodeSize::Wide) |
4345 | gen->alignWideOpcode(); |
4346 | if (Fits<unsigned, size>::check(opcodeID) |
4347 | && Fits<VirtualRegister, size>::check(dst) |
4348 | && Fits<VirtualRegister, size>::check(base) |
4349 | && Fits<VirtualRegister, size>::check(property) |
4350 | && Fits<unsigned, size>::check(__metadataID) |
4351 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
4352 | if (recordOpcode) |
4353 | gen->recordOpcode(opcodeID); |
4354 | if (size == OpcodeSize::Wide) |
4355 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
4356 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
4357 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
4358 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
4359 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
4360 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
4361 | return true; |
4362 | } |
4363 | return false; |
4364 | } |
4365 | |
4366 | public: |
4367 | template<typename Block> |
4368 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
4369 | { |
4370 | dumper->printLocationAndOp(__location, &"*get_by_val" [!__isWide]); |
4371 | dumper->dumpOperand(m_dst, true); |
4372 | dumper->dumpOperand(m_base, false); |
4373 | dumper->dumpOperand(m_property, false); |
4374 | } |
4375 | |
4376 | OpGetByVal(const uint8_t* stream) |
4377 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
4378 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
4379 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
4380 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
4381 | { |
4382 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
4383 | } |
4384 | |
4385 | OpGetByVal(const uint32_t* stream) |
4386 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
4387 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
4388 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
4389 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
4390 | { |
4391 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
4392 | } |
4393 | |
4394 | static OpGetByVal decode(const uint8_t* stream) |
4395 | { |
4396 | if (*stream != op_wide) |
4397 | return { stream }; |
4398 | |
4399 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
4400 | return { wideStream }; |
4401 | } |
4402 | |
4403 | template<typename Functor> |
4404 | void setDst(VirtualRegister value, Functor func) |
4405 | { |
4406 | if (isWide()) |
4407 | setDst<OpcodeSize::Wide>(value, func); |
4408 | else |
4409 | setDst<OpcodeSize::Narrow>(value, func); |
4410 | } |
4411 | |
4412 | template <OpcodeSize size, typename Functor> |
4413 | void setDst(VirtualRegister value, Functor func) |
4414 | { |
4415 | if (!Fits<VirtualRegister, size>::check(value)) |
4416 | value = func(); |
4417 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
4418 | *stream = Fits<VirtualRegister, size>::convert(value); |
4419 | } |
4420 | |
4421 | template<typename Functor> |
4422 | void setBase(VirtualRegister value, Functor func) |
4423 | { |
4424 | if (isWide()) |
4425 | setBase<OpcodeSize::Wide>(value, func); |
4426 | else |
4427 | setBase<OpcodeSize::Narrow>(value, func); |
4428 | } |
4429 | |
4430 | template <OpcodeSize size, typename Functor> |
4431 | void setBase(VirtualRegister value, Functor func) |
4432 | { |
4433 | if (!Fits<VirtualRegister, size>::check(value)) |
4434 | value = func(); |
4435 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
4436 | *stream = Fits<VirtualRegister, size>::convert(value); |
4437 | } |
4438 | |
4439 | template<typename Functor> |
4440 | void setProperty(VirtualRegister value, Functor func) |
4441 | { |
4442 | if (isWide()) |
4443 | setProperty<OpcodeSize::Wide>(value, func); |
4444 | else |
4445 | setProperty<OpcodeSize::Narrow>(value, func); |
4446 | } |
4447 | |
4448 | template <OpcodeSize size, typename Functor> |
4449 | void setProperty(VirtualRegister value, Functor func) |
4450 | { |
4451 | if (!Fits<VirtualRegister, size>::check(value)) |
4452 | value = func(); |
4453 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
4454 | *stream = Fits<VirtualRegister, size>::convert(value); |
4455 | } |
4456 | |
4457 | struct Metadata { |
4458 | WTF_MAKE_NONCOPYABLE(Metadata); |
4459 | |
4460 | public: |
4461 | Metadata(const OpGetByVal&) { } |
4462 | |
4463 | ValueProfile m_profile; |
4464 | ArrayProfile m_arrayProfile; |
4465 | }; |
4466 | |
4467 | Metadata& metadata(CodeBlock* codeBlock) const |
4468 | { |
4469 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
4470 | } |
4471 | |
4472 | Metadata& metadata(ExecState* exec) const |
4473 | { |
4474 | return metadata(exec->codeBlock()); |
4475 | } |
4476 | |
4477 | VirtualRegister m_dst; |
4478 | VirtualRegister m_base; |
4479 | VirtualRegister m_property; |
4480 | unsigned m_metadataID; |
4481 | }; |
4482 | |
4483 | struct OpPutByVal : public Instruction { |
4484 | static constexpr OpcodeID opcodeID = op_put_by_val; |
4485 | |
4486 | static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value) |
4487 | { |
4488 | |
4489 | auto __metadataID = gen->addMetadataFor(opcodeID); |
4490 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, value, __metadataID) |
4491 | || emit<OpcodeSize::Wide, Assert, true>(gen, base, property, value, __metadataID); |
4492 | } |
4493 | |
4494 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
4495 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value) |
4496 | { |
4497 | auto __metadataID = gen->addMetadataFor(opcodeID); |
4498 | return emit<size, shouldAssert>(gen, base, property, value, __metadataID); |
4499 | } |
4500 | |
4501 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
4502 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, unsigned __metadataID) |
4503 | { |
4504 | bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, value, __metadataID); |
4505 | if (shouldAssert == Assert) |
4506 | ASSERT(didEmit); |
4507 | return didEmit; |
4508 | } |
4509 | |
4510 | private: |
4511 | template<OpcodeSize size, bool recordOpcode> |
4512 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, unsigned __metadataID) |
4513 | { |
4514 | if (size == OpcodeSize::Wide) |
4515 | gen->alignWideOpcode(); |
4516 | if (Fits<unsigned, size>::check(opcodeID) |
4517 | && Fits<VirtualRegister, size>::check(base) |
4518 | && Fits<VirtualRegister, size>::check(property) |
4519 | && Fits<VirtualRegister, size>::check(value) |
4520 | && Fits<unsigned, size>::check(__metadataID) |
4521 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
4522 | if (recordOpcode) |
4523 | gen->recordOpcode(opcodeID); |
4524 | if (size == OpcodeSize::Wide) |
4525 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
4526 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
4527 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
4528 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
4529 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
4530 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
4531 | return true; |
4532 | } |
4533 | return false; |
4534 | } |
4535 | |
4536 | public: |
4537 | template<typename Block> |
4538 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
4539 | { |
4540 | dumper->printLocationAndOp(__location, &"*put_by_val" [!__isWide]); |
4541 | dumper->dumpOperand(m_base, true); |
4542 | dumper->dumpOperand(m_property, false); |
4543 | dumper->dumpOperand(m_value, false); |
4544 | } |
4545 | |
4546 | OpPutByVal(const uint8_t* stream) |
4547 | : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
4548 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
4549 | , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
4550 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
4551 | { |
4552 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
4553 | } |
4554 | |
4555 | OpPutByVal(const uint32_t* stream) |
4556 | : m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
4557 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
4558 | , m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
4559 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
4560 | { |
4561 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
4562 | } |
4563 | |
4564 | static OpPutByVal decode(const uint8_t* stream) |
4565 | { |
4566 | if (*stream != op_wide) |
4567 | return { stream }; |
4568 | |
4569 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
4570 | return { wideStream }; |
4571 | } |
4572 | |
4573 | template<typename Functor> |
4574 | void setBase(VirtualRegister value, Functor func) |
4575 | { |
4576 | if (isWide()) |
4577 | setBase<OpcodeSize::Wide>(value, func); |
4578 | else |
4579 | setBase<OpcodeSize::Narrow>(value, func); |
4580 | } |
4581 | |
4582 | template <OpcodeSize size, typename Functor> |
4583 | void setBase(VirtualRegister value, Functor func) |
4584 | { |
4585 | if (!Fits<VirtualRegister, size>::check(value)) |
4586 | value = func(); |
4587 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
4588 | *stream = Fits<VirtualRegister, size>::convert(value); |
4589 | } |
4590 | |
4591 | template<typename Functor> |
4592 | void setProperty(VirtualRegister value, Functor func) |
4593 | { |
4594 | if (isWide()) |
4595 | setProperty<OpcodeSize::Wide>(value, func); |
4596 | else |
4597 | setProperty<OpcodeSize::Narrow>(value, func); |
4598 | } |
4599 | |
4600 | template <OpcodeSize size, typename Functor> |
4601 | void setProperty(VirtualRegister value, Functor func) |
4602 | { |
4603 | if (!Fits<VirtualRegister, size>::check(value)) |
4604 | value = func(); |
4605 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
4606 | *stream = Fits<VirtualRegister, size>::convert(value); |
4607 | } |
4608 | |
4609 | template<typename Functor> |
4610 | void setValue(VirtualRegister value, Functor func) |
4611 | { |
4612 | if (isWide()) |
4613 | setValue<OpcodeSize::Wide>(value, func); |
4614 | else |
4615 | setValue<OpcodeSize::Narrow>(value, func); |
4616 | } |
4617 | |
4618 | template <OpcodeSize size, typename Functor> |
4619 | void setValue(VirtualRegister value, Functor func) |
4620 | { |
4621 | if (!Fits<VirtualRegister, size>::check(value)) |
4622 | value = func(); |
4623 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
4624 | *stream = Fits<VirtualRegister, size>::convert(value); |
4625 | } |
4626 | |
4627 | struct Metadata { |
4628 | WTF_MAKE_NONCOPYABLE(Metadata); |
4629 | |
4630 | public: |
4631 | Metadata(const OpPutByVal&) { } |
4632 | |
4633 | ArrayProfile m_arrayProfile; |
4634 | }; |
4635 | |
4636 | Metadata& metadata(CodeBlock* codeBlock) const |
4637 | { |
4638 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
4639 | } |
4640 | |
4641 | Metadata& metadata(ExecState* exec) const |
4642 | { |
4643 | return metadata(exec->codeBlock()); |
4644 | } |
4645 | |
4646 | VirtualRegister m_base; |
4647 | VirtualRegister m_property; |
4648 | VirtualRegister m_value; |
4649 | unsigned m_metadataID; |
4650 | }; |
4651 | |
4652 | struct OpPutByValDirect : public Instruction { |
4653 | static constexpr OpcodeID opcodeID = op_put_by_val_direct; |
4654 | |
4655 | static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value) |
4656 | { |
4657 | |
4658 | auto __metadataID = gen->addMetadataFor(opcodeID); |
4659 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, value, __metadataID) |
4660 | || emit<OpcodeSize::Wide, Assert, true>(gen, base, property, value, __metadataID); |
4661 | } |
4662 | |
4663 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
4664 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value) |
4665 | { |
4666 | auto __metadataID = gen->addMetadataFor(opcodeID); |
4667 | return emit<size, shouldAssert>(gen, base, property, value, __metadataID); |
4668 | } |
4669 | |
4670 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
4671 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, unsigned __metadataID) |
4672 | { |
4673 | bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, value, __metadataID); |
4674 | if (shouldAssert == Assert) |
4675 | ASSERT(didEmit); |
4676 | return didEmit; |
4677 | } |
4678 | |
4679 | private: |
4680 | template<OpcodeSize size, bool recordOpcode> |
4681 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, unsigned __metadataID) |
4682 | { |
4683 | if (size == OpcodeSize::Wide) |
4684 | gen->alignWideOpcode(); |
4685 | if (Fits<unsigned, size>::check(opcodeID) |
4686 | && Fits<VirtualRegister, size>::check(base) |
4687 | && Fits<VirtualRegister, size>::check(property) |
4688 | && Fits<VirtualRegister, size>::check(value) |
4689 | && Fits<unsigned, size>::check(__metadataID) |
4690 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
4691 | if (recordOpcode) |
4692 | gen->recordOpcode(opcodeID); |
4693 | if (size == OpcodeSize::Wide) |
4694 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
4695 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
4696 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
4697 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
4698 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
4699 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
4700 | return true; |
4701 | } |
4702 | return false; |
4703 | } |
4704 | |
4705 | public: |
4706 | template<typename Block> |
4707 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
4708 | { |
4709 | dumper->printLocationAndOp(__location, &"*put_by_val_direct" [!__isWide]); |
4710 | dumper->dumpOperand(m_base, true); |
4711 | dumper->dumpOperand(m_property, false); |
4712 | dumper->dumpOperand(m_value, false); |
4713 | } |
4714 | |
4715 | OpPutByValDirect(const uint8_t* stream) |
4716 | : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
4717 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
4718 | , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
4719 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
4720 | { |
4721 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
4722 | } |
4723 | |
4724 | OpPutByValDirect(const uint32_t* stream) |
4725 | : m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
4726 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
4727 | , m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
4728 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
4729 | { |
4730 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
4731 | } |
4732 | |
4733 | static OpPutByValDirect decode(const uint8_t* stream) |
4734 | { |
4735 | if (*stream != op_wide) |
4736 | return { stream }; |
4737 | |
4738 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
4739 | return { wideStream }; |
4740 | } |
4741 | |
4742 | template<typename Functor> |
4743 | void setBase(VirtualRegister value, Functor func) |
4744 | { |
4745 | if (isWide()) |
4746 | setBase<OpcodeSize::Wide>(value, func); |
4747 | else |
4748 | setBase<OpcodeSize::Narrow>(value, func); |
4749 | } |
4750 | |
4751 | template <OpcodeSize size, typename Functor> |
4752 | void setBase(VirtualRegister value, Functor func) |
4753 | { |
4754 | if (!Fits<VirtualRegister, size>::check(value)) |
4755 | value = func(); |
4756 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
4757 | *stream = Fits<VirtualRegister, size>::convert(value); |
4758 | } |
4759 | |
4760 | template<typename Functor> |
4761 | void setProperty(VirtualRegister value, Functor func) |
4762 | { |
4763 | if (isWide()) |
4764 | setProperty<OpcodeSize::Wide>(value, func); |
4765 | else |
4766 | setProperty<OpcodeSize::Narrow>(value, func); |
4767 | } |
4768 | |
4769 | template <OpcodeSize size, typename Functor> |
4770 | void setProperty(VirtualRegister value, Functor func) |
4771 | { |
4772 | if (!Fits<VirtualRegister, size>::check(value)) |
4773 | value = func(); |
4774 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
4775 | *stream = Fits<VirtualRegister, size>::convert(value); |
4776 | } |
4777 | |
4778 | template<typename Functor> |
4779 | void setValue(VirtualRegister value, Functor func) |
4780 | { |
4781 | if (isWide()) |
4782 | setValue<OpcodeSize::Wide>(value, func); |
4783 | else |
4784 | setValue<OpcodeSize::Narrow>(value, func); |
4785 | } |
4786 | |
4787 | template <OpcodeSize size, typename Functor> |
4788 | void setValue(VirtualRegister value, Functor func) |
4789 | { |
4790 | if (!Fits<VirtualRegister, size>::check(value)) |
4791 | value = func(); |
4792 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
4793 | *stream = Fits<VirtualRegister, size>::convert(value); |
4794 | } |
4795 | |
4796 | struct Metadata { |
4797 | WTF_MAKE_NONCOPYABLE(Metadata); |
4798 | |
4799 | public: |
4800 | Metadata(const OpPutByValDirect&) { } |
4801 | |
4802 | ArrayProfile m_arrayProfile; |
4803 | }; |
4804 | |
4805 | Metadata& metadata(CodeBlock* codeBlock) const |
4806 | { |
4807 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
4808 | } |
4809 | |
4810 | Metadata& metadata(ExecState* exec) const |
4811 | { |
4812 | return metadata(exec->codeBlock()); |
4813 | } |
4814 | |
4815 | VirtualRegister m_base; |
4816 | VirtualRegister m_property; |
4817 | VirtualRegister m_value; |
4818 | unsigned m_metadataID; |
4819 | }; |
4820 | |
4821 | struct OpJneqPtr : public Instruction { |
4822 | static constexpr OpcodeID opcodeID = op_jneq_ptr; |
4823 | |
4824 | static void emit(BytecodeGenerator* gen, VirtualRegister value, Special::Pointer specialPointer, BoundLabel targetLabel) |
4825 | { |
4826 | |
4827 | auto __metadataID = gen->addMetadataFor(opcodeID); |
4828 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, value, specialPointer, targetLabel, __metadataID) |
4829 | || emit<OpcodeSize::Wide, Assert, true>(gen, value, specialPointer, targetLabel, __metadataID); |
4830 | } |
4831 | |
4832 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
4833 | static bool emit(BytecodeGenerator* gen, VirtualRegister value, Special::Pointer specialPointer, BoundLabel targetLabel) |
4834 | { |
4835 | auto __metadataID = gen->addMetadataFor(opcodeID); |
4836 | return emit<size, shouldAssert>(gen, value, specialPointer, targetLabel, __metadataID); |
4837 | } |
4838 | |
4839 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
4840 | static bool emit(BytecodeGenerator* gen, VirtualRegister value, Special::Pointer specialPointer, BoundLabel targetLabel, unsigned __metadataID) |
4841 | { |
4842 | bool didEmit = emitImpl<size, recordOpcode>(gen, value, specialPointer, targetLabel, __metadataID); |
4843 | if (shouldAssert == Assert) |
4844 | ASSERT(didEmit); |
4845 | return didEmit; |
4846 | } |
4847 | |
4848 | private: |
4849 | template<OpcodeSize size, bool recordOpcode> |
4850 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value, Special::Pointer specialPointer, BoundLabel targetLabel, unsigned __metadataID) |
4851 | { |
4852 | if (size == OpcodeSize::Wide) |
4853 | gen->alignWideOpcode(); |
4854 | if (Fits<unsigned, size>::check(opcodeID) |
4855 | && Fits<VirtualRegister, size>::check(value) |
4856 | && Fits<Special::Pointer, size>::check(specialPointer) |
4857 | && Fits<BoundLabel, size>::check(targetLabel) |
4858 | && Fits<unsigned, size>::check(__metadataID) |
4859 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
4860 | if (recordOpcode) |
4861 | gen->recordOpcode(opcodeID); |
4862 | if (size == OpcodeSize::Wide) |
4863 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
4864 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
4865 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
4866 | gen->write(Fits<Special::Pointer, size>::convert(specialPointer)); |
4867 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
4868 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
4869 | return true; |
4870 | } |
4871 | return false; |
4872 | } |
4873 | |
4874 | public: |
4875 | template<typename Block> |
4876 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
4877 | { |
4878 | dumper->printLocationAndOp(__location, &"*jneq_ptr" [!__isWide]); |
4879 | dumper->dumpOperand(m_value, true); |
4880 | dumper->dumpOperand(m_specialPointer, false); |
4881 | dumper->dumpOperand(m_targetLabel, false); |
4882 | } |
4883 | |
4884 | OpJneqPtr(const uint8_t* stream) |
4885 | : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
4886 | , m_specialPointer(Fits<Special::Pointer, OpcodeSize::Narrow>::convert(stream[2])) |
4887 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
4888 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
4889 | { |
4890 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
4891 | } |
4892 | |
4893 | OpJneqPtr(const uint32_t* stream) |
4894 | : m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
4895 | , m_specialPointer(Fits<Special::Pointer, OpcodeSize::Wide>::convert(stream[2])) |
4896 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
4897 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
4898 | { |
4899 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
4900 | } |
4901 | |
4902 | static OpJneqPtr decode(const uint8_t* stream) |
4903 | { |
4904 | if (*stream != op_wide) |
4905 | return { stream }; |
4906 | |
4907 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
4908 | return { wideStream }; |
4909 | } |
4910 | |
4911 | template<typename Functor> |
4912 | void setValue(VirtualRegister value, Functor func) |
4913 | { |
4914 | if (isWide()) |
4915 | setValue<OpcodeSize::Wide>(value, func); |
4916 | else |
4917 | setValue<OpcodeSize::Narrow>(value, func); |
4918 | } |
4919 | |
4920 | template <OpcodeSize size, typename Functor> |
4921 | void setValue(VirtualRegister value, Functor func) |
4922 | { |
4923 | if (!Fits<VirtualRegister, size>::check(value)) |
4924 | value = func(); |
4925 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
4926 | *stream = Fits<VirtualRegister, size>::convert(value); |
4927 | } |
4928 | |
4929 | template<typename Functor> |
4930 | void setSpecialPointer(Special::Pointer value, Functor func) |
4931 | { |
4932 | if (isWide()) |
4933 | setSpecialPointer<OpcodeSize::Wide>(value, func); |
4934 | else |
4935 | setSpecialPointer<OpcodeSize::Narrow>(value, func); |
4936 | } |
4937 | |
4938 | template <OpcodeSize size, typename Functor> |
4939 | void setSpecialPointer(Special::Pointer value, Functor func) |
4940 | { |
4941 | if (!Fits<Special::Pointer, size>::check(value)) |
4942 | value = func(); |
4943 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
4944 | *stream = Fits<Special::Pointer, size>::convert(value); |
4945 | } |
4946 | |
4947 | template<typename Functor> |
4948 | void setTargetLabel(BoundLabel value, Functor func) |
4949 | { |
4950 | if (isWide()) |
4951 | setTargetLabel<OpcodeSize::Wide>(value, func); |
4952 | else |
4953 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
4954 | } |
4955 | |
4956 | template <OpcodeSize size, typename Functor> |
4957 | void setTargetLabel(BoundLabel value, Functor func) |
4958 | { |
4959 | if (!Fits<BoundLabel, size>::check(value)) |
4960 | value = func(); |
4961 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
4962 | *stream = Fits<BoundLabel, size>::convert(value); |
4963 | } |
4964 | |
4965 | struct Metadata { |
4966 | WTF_MAKE_NONCOPYABLE(Metadata); |
4967 | |
4968 | public: |
4969 | Metadata(const OpJneqPtr&) { } |
4970 | |
4971 | bool m_hasJumped; |
4972 | }; |
4973 | |
4974 | Metadata& metadata(CodeBlock* codeBlock) const |
4975 | { |
4976 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
4977 | } |
4978 | |
4979 | Metadata& metadata(ExecState* exec) const |
4980 | { |
4981 | return metadata(exec->codeBlock()); |
4982 | } |
4983 | |
4984 | VirtualRegister m_value; |
4985 | Special::Pointer m_specialPointer; |
4986 | BoundLabel m_targetLabel; |
4987 | unsigned m_metadataID; |
4988 | }; |
4989 | |
4990 | struct OpCall : public Instruction { |
4991 | static constexpr OpcodeID opcodeID = op_call; |
4992 | |
4993 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv) |
4994 | { |
4995 | |
4996 | auto __metadataID = gen->addMetadataFor(opcodeID); |
4997 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID) |
4998 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, callee, argc, argv, __metadataID); |
4999 | } |
5000 | |
5001 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
5002 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv) |
5003 | { |
5004 | auto __metadataID = gen->addMetadataFor(opcodeID); |
5005 | return emit<size, shouldAssert>(gen, dst, callee, argc, argv, __metadataID); |
5006 | } |
5007 | |
5008 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
5009 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID) |
5010 | { |
5011 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, argc, argv, __metadataID); |
5012 | if (shouldAssert == Assert) |
5013 | ASSERT(didEmit); |
5014 | return didEmit; |
5015 | } |
5016 | |
5017 | private: |
5018 | template<OpcodeSize size, bool recordOpcode> |
5019 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID) |
5020 | { |
5021 | if (size == OpcodeSize::Wide) |
5022 | gen->alignWideOpcode(); |
5023 | if (Fits<unsigned, size>::check(opcodeID) |
5024 | && Fits<VirtualRegister, size>::check(dst) |
5025 | && Fits<VirtualRegister, size>::check(callee) |
5026 | && Fits<unsigned, size>::check(argc) |
5027 | && Fits<unsigned, size>::check(argv) |
5028 | && Fits<unsigned, size>::check(__metadataID) |
5029 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
5030 | if (recordOpcode) |
5031 | gen->recordOpcode(opcodeID); |
5032 | if (size == OpcodeSize::Wide) |
5033 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
5034 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
5035 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
5036 | gen->write(Fits<VirtualRegister, size>::convert(callee)); |
5037 | gen->write(Fits<unsigned, size>::convert(argc)); |
5038 | gen->write(Fits<unsigned, size>::convert(argv)); |
5039 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
5040 | return true; |
5041 | } |
5042 | return false; |
5043 | } |
5044 | |
5045 | public: |
5046 | template<typename Block> |
5047 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
5048 | { |
5049 | dumper->printLocationAndOp(__location, &"*call" [!__isWide]); |
5050 | dumper->dumpOperand(m_dst, true); |
5051 | dumper->dumpOperand(m_callee, false); |
5052 | dumper->dumpOperand(m_argc, false); |
5053 | dumper->dumpOperand(m_argv, false); |
5054 | } |
5055 | |
5056 | OpCall(const uint8_t* stream) |
5057 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
5058 | , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
5059 | , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
5060 | , m_argv(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
5061 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
5062 | { |
5063 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
5064 | } |
5065 | |
5066 | OpCall(const uint32_t* stream) |
5067 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
5068 | , m_callee(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
5069 | , m_argc(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
5070 | , m_argv(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
5071 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
5072 | { |
5073 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
5074 | } |
5075 | |
5076 | static OpCall decode(const uint8_t* stream) |
5077 | { |
5078 | if (*stream != op_wide) |
5079 | return { stream }; |
5080 | |
5081 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
5082 | return { wideStream }; |
5083 | } |
5084 | |
5085 | template<typename Functor> |
5086 | void setDst(VirtualRegister value, Functor func) |
5087 | { |
5088 | if (isWide()) |
5089 | setDst<OpcodeSize::Wide>(value, func); |
5090 | else |
5091 | setDst<OpcodeSize::Narrow>(value, func); |
5092 | } |
5093 | |
5094 | template <OpcodeSize size, typename Functor> |
5095 | void setDst(VirtualRegister value, Functor func) |
5096 | { |
5097 | if (!Fits<VirtualRegister, size>::check(value)) |
5098 | value = func(); |
5099 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
5100 | *stream = Fits<VirtualRegister, size>::convert(value); |
5101 | } |
5102 | |
5103 | template<typename Functor> |
5104 | void setCallee(VirtualRegister value, Functor func) |
5105 | { |
5106 | if (isWide()) |
5107 | setCallee<OpcodeSize::Wide>(value, func); |
5108 | else |
5109 | setCallee<OpcodeSize::Narrow>(value, func); |
5110 | } |
5111 | |
5112 | template <OpcodeSize size, typename Functor> |
5113 | void setCallee(VirtualRegister value, Functor func) |
5114 | { |
5115 | if (!Fits<VirtualRegister, size>::check(value)) |
5116 | value = func(); |
5117 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
5118 | *stream = Fits<VirtualRegister, size>::convert(value); |
5119 | } |
5120 | |
5121 | template<typename Functor> |
5122 | void setArgc(unsigned value, Functor func) |
5123 | { |
5124 | if (isWide()) |
5125 | setArgc<OpcodeSize::Wide>(value, func); |
5126 | else |
5127 | setArgc<OpcodeSize::Narrow>(value, func); |
5128 | } |
5129 | |
5130 | template <OpcodeSize size, typename Functor> |
5131 | void setArgc(unsigned value, Functor func) |
5132 | { |
5133 | if (!Fits<unsigned, size>::check(value)) |
5134 | value = func(); |
5135 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
5136 | *stream = Fits<unsigned, size>::convert(value); |
5137 | } |
5138 | |
5139 | template<typename Functor> |
5140 | void setArgv(unsigned value, Functor func) |
5141 | { |
5142 | if (isWide()) |
5143 | setArgv<OpcodeSize::Wide>(value, func); |
5144 | else |
5145 | setArgv<OpcodeSize::Narrow>(value, func); |
5146 | } |
5147 | |
5148 | template <OpcodeSize size, typename Functor> |
5149 | void setArgv(unsigned value, Functor func) |
5150 | { |
5151 | if (!Fits<unsigned, size>::check(value)) |
5152 | value = func(); |
5153 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
5154 | *stream = Fits<unsigned, size>::convert(value); |
5155 | } |
5156 | |
5157 | struct Metadata { |
5158 | WTF_MAKE_NONCOPYABLE(Metadata); |
5159 | |
5160 | public: |
5161 | Metadata(const OpCall&) { } |
5162 | |
5163 | LLIntCallLinkInfo m_callLinkInfo; |
5164 | ArrayProfile m_arrayProfile; |
5165 | ValueProfile m_profile; |
5166 | }; |
5167 | |
5168 | Metadata& metadata(CodeBlock* codeBlock) const |
5169 | { |
5170 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
5171 | } |
5172 | |
5173 | Metadata& metadata(ExecState* exec) const |
5174 | { |
5175 | return metadata(exec->codeBlock()); |
5176 | } |
5177 | |
5178 | VirtualRegister m_dst; |
5179 | VirtualRegister m_callee; |
5180 | unsigned m_argc; |
5181 | unsigned m_argv; |
5182 | unsigned m_metadataID; |
5183 | }; |
5184 | |
5185 | struct OpTailCall : public Instruction { |
5186 | static constexpr OpcodeID opcodeID = op_tail_call; |
5187 | |
5188 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv) |
5189 | { |
5190 | |
5191 | auto __metadataID = gen->addMetadataFor(opcodeID); |
5192 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID) |
5193 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, callee, argc, argv, __metadataID); |
5194 | } |
5195 | |
5196 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
5197 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv) |
5198 | { |
5199 | auto __metadataID = gen->addMetadataFor(opcodeID); |
5200 | return emit<size, shouldAssert>(gen, dst, callee, argc, argv, __metadataID); |
5201 | } |
5202 | |
5203 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
5204 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID) |
5205 | { |
5206 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, argc, argv, __metadataID); |
5207 | if (shouldAssert == Assert) |
5208 | ASSERT(didEmit); |
5209 | return didEmit; |
5210 | } |
5211 | |
5212 | private: |
5213 | template<OpcodeSize size, bool recordOpcode> |
5214 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID) |
5215 | { |
5216 | if (size == OpcodeSize::Wide) |
5217 | gen->alignWideOpcode(); |
5218 | if (Fits<unsigned, size>::check(opcodeID) |
5219 | && Fits<VirtualRegister, size>::check(dst) |
5220 | && Fits<VirtualRegister, size>::check(callee) |
5221 | && Fits<unsigned, size>::check(argc) |
5222 | && Fits<unsigned, size>::check(argv) |
5223 | && Fits<unsigned, size>::check(__metadataID) |
5224 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
5225 | if (recordOpcode) |
5226 | gen->recordOpcode(opcodeID); |
5227 | if (size == OpcodeSize::Wide) |
5228 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
5229 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
5230 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
5231 | gen->write(Fits<VirtualRegister, size>::convert(callee)); |
5232 | gen->write(Fits<unsigned, size>::convert(argc)); |
5233 | gen->write(Fits<unsigned, size>::convert(argv)); |
5234 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
5235 | return true; |
5236 | } |
5237 | return false; |
5238 | } |
5239 | |
5240 | public: |
5241 | template<typename Block> |
5242 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
5243 | { |
5244 | dumper->printLocationAndOp(__location, &"*tail_call" [!__isWide]); |
5245 | dumper->dumpOperand(m_dst, true); |
5246 | dumper->dumpOperand(m_callee, false); |
5247 | dumper->dumpOperand(m_argc, false); |
5248 | dumper->dumpOperand(m_argv, false); |
5249 | } |
5250 | |
5251 | OpTailCall(const uint8_t* stream) |
5252 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
5253 | , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
5254 | , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
5255 | , m_argv(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
5256 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
5257 | { |
5258 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
5259 | } |
5260 | |
5261 | OpTailCall(const uint32_t* stream) |
5262 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
5263 | , m_callee(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
5264 | , m_argc(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
5265 | , m_argv(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
5266 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
5267 | { |
5268 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
5269 | } |
5270 | |
5271 | static OpTailCall decode(const uint8_t* stream) |
5272 | { |
5273 | if (*stream != op_wide) |
5274 | return { stream }; |
5275 | |
5276 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
5277 | return { wideStream }; |
5278 | } |
5279 | |
5280 | template<typename Functor> |
5281 | void setDst(VirtualRegister value, Functor func) |
5282 | { |
5283 | if (isWide()) |
5284 | setDst<OpcodeSize::Wide>(value, func); |
5285 | else |
5286 | setDst<OpcodeSize::Narrow>(value, func); |
5287 | } |
5288 | |
5289 | template <OpcodeSize size, typename Functor> |
5290 | void setDst(VirtualRegister value, Functor func) |
5291 | { |
5292 | if (!Fits<VirtualRegister, size>::check(value)) |
5293 | value = func(); |
5294 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
5295 | *stream = Fits<VirtualRegister, size>::convert(value); |
5296 | } |
5297 | |
5298 | template<typename Functor> |
5299 | void setCallee(VirtualRegister value, Functor func) |
5300 | { |
5301 | if (isWide()) |
5302 | setCallee<OpcodeSize::Wide>(value, func); |
5303 | else |
5304 | setCallee<OpcodeSize::Narrow>(value, func); |
5305 | } |
5306 | |
5307 | template <OpcodeSize size, typename Functor> |
5308 | void setCallee(VirtualRegister value, Functor func) |
5309 | { |
5310 | if (!Fits<VirtualRegister, size>::check(value)) |
5311 | value = func(); |
5312 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
5313 | *stream = Fits<VirtualRegister, size>::convert(value); |
5314 | } |
5315 | |
5316 | template<typename Functor> |
5317 | void setArgc(unsigned value, Functor func) |
5318 | { |
5319 | if (isWide()) |
5320 | setArgc<OpcodeSize::Wide>(value, func); |
5321 | else |
5322 | setArgc<OpcodeSize::Narrow>(value, func); |
5323 | } |
5324 | |
5325 | template <OpcodeSize size, typename Functor> |
5326 | void setArgc(unsigned value, Functor func) |
5327 | { |
5328 | if (!Fits<unsigned, size>::check(value)) |
5329 | value = func(); |
5330 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
5331 | *stream = Fits<unsigned, size>::convert(value); |
5332 | } |
5333 | |
5334 | template<typename Functor> |
5335 | void setArgv(unsigned value, Functor func) |
5336 | { |
5337 | if (isWide()) |
5338 | setArgv<OpcodeSize::Wide>(value, func); |
5339 | else |
5340 | setArgv<OpcodeSize::Narrow>(value, func); |
5341 | } |
5342 | |
5343 | template <OpcodeSize size, typename Functor> |
5344 | void setArgv(unsigned value, Functor func) |
5345 | { |
5346 | if (!Fits<unsigned, size>::check(value)) |
5347 | value = func(); |
5348 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
5349 | *stream = Fits<unsigned, size>::convert(value); |
5350 | } |
5351 | |
5352 | struct Metadata { |
5353 | WTF_MAKE_NONCOPYABLE(Metadata); |
5354 | |
5355 | public: |
5356 | Metadata(const OpTailCall&) { } |
5357 | |
5358 | LLIntCallLinkInfo m_callLinkInfo; |
5359 | ArrayProfile m_arrayProfile; |
5360 | ValueProfile m_profile; |
5361 | }; |
5362 | |
5363 | Metadata& metadata(CodeBlock* codeBlock) const |
5364 | { |
5365 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
5366 | } |
5367 | |
5368 | Metadata& metadata(ExecState* exec) const |
5369 | { |
5370 | return metadata(exec->codeBlock()); |
5371 | } |
5372 | |
5373 | VirtualRegister m_dst; |
5374 | VirtualRegister m_callee; |
5375 | unsigned m_argc; |
5376 | unsigned m_argv; |
5377 | unsigned m_metadataID; |
5378 | }; |
5379 | |
5380 | struct OpCallEval : public Instruction { |
5381 | static constexpr OpcodeID opcodeID = op_call_eval; |
5382 | |
5383 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv) |
5384 | { |
5385 | |
5386 | auto __metadataID = gen->addMetadataFor(opcodeID); |
5387 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID) |
5388 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, callee, argc, argv, __metadataID); |
5389 | } |
5390 | |
5391 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
5392 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv) |
5393 | { |
5394 | auto __metadataID = gen->addMetadataFor(opcodeID); |
5395 | return emit<size, shouldAssert>(gen, dst, callee, argc, argv, __metadataID); |
5396 | } |
5397 | |
5398 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
5399 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID) |
5400 | { |
5401 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, argc, argv, __metadataID); |
5402 | if (shouldAssert == Assert) |
5403 | ASSERT(didEmit); |
5404 | return didEmit; |
5405 | } |
5406 | |
5407 | private: |
5408 | template<OpcodeSize size, bool recordOpcode> |
5409 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID) |
5410 | { |
5411 | if (size == OpcodeSize::Wide) |
5412 | gen->alignWideOpcode(); |
5413 | if (Fits<unsigned, size>::check(opcodeID) |
5414 | && Fits<VirtualRegister, size>::check(dst) |
5415 | && Fits<VirtualRegister, size>::check(callee) |
5416 | && Fits<unsigned, size>::check(argc) |
5417 | && Fits<unsigned, size>::check(argv) |
5418 | && Fits<unsigned, size>::check(__metadataID) |
5419 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
5420 | if (recordOpcode) |
5421 | gen->recordOpcode(opcodeID); |
5422 | if (size == OpcodeSize::Wide) |
5423 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
5424 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
5425 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
5426 | gen->write(Fits<VirtualRegister, size>::convert(callee)); |
5427 | gen->write(Fits<unsigned, size>::convert(argc)); |
5428 | gen->write(Fits<unsigned, size>::convert(argv)); |
5429 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
5430 | return true; |
5431 | } |
5432 | return false; |
5433 | } |
5434 | |
5435 | public: |
5436 | template<typename Block> |
5437 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
5438 | { |
5439 | dumper->printLocationAndOp(__location, &"*call_eval" [!__isWide]); |
5440 | dumper->dumpOperand(m_dst, true); |
5441 | dumper->dumpOperand(m_callee, false); |
5442 | dumper->dumpOperand(m_argc, false); |
5443 | dumper->dumpOperand(m_argv, false); |
5444 | } |
5445 | |
5446 | OpCallEval(const uint8_t* stream) |
5447 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
5448 | , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
5449 | , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
5450 | , m_argv(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
5451 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
5452 | { |
5453 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
5454 | } |
5455 | |
5456 | OpCallEval(const uint32_t* stream) |
5457 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
5458 | , m_callee(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
5459 | , m_argc(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
5460 | , m_argv(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
5461 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
5462 | { |
5463 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
5464 | } |
5465 | |
5466 | static OpCallEval decode(const uint8_t* stream) |
5467 | { |
5468 | if (*stream != op_wide) |
5469 | return { stream }; |
5470 | |
5471 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
5472 | return { wideStream }; |
5473 | } |
5474 | |
5475 | template<typename Functor> |
5476 | void setDst(VirtualRegister value, Functor func) |
5477 | { |
5478 | if (isWide()) |
5479 | setDst<OpcodeSize::Wide>(value, func); |
5480 | else |
5481 | setDst<OpcodeSize::Narrow>(value, func); |
5482 | } |
5483 | |
5484 | template <OpcodeSize size, typename Functor> |
5485 | void setDst(VirtualRegister value, Functor func) |
5486 | { |
5487 | if (!Fits<VirtualRegister, size>::check(value)) |
5488 | value = func(); |
5489 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
5490 | *stream = Fits<VirtualRegister, size>::convert(value); |
5491 | } |
5492 | |
5493 | template<typename Functor> |
5494 | void setCallee(VirtualRegister value, Functor func) |
5495 | { |
5496 | if (isWide()) |
5497 | setCallee<OpcodeSize::Wide>(value, func); |
5498 | else |
5499 | setCallee<OpcodeSize::Narrow>(value, func); |
5500 | } |
5501 | |
5502 | template <OpcodeSize size, typename Functor> |
5503 | void setCallee(VirtualRegister value, Functor func) |
5504 | { |
5505 | if (!Fits<VirtualRegister, size>::check(value)) |
5506 | value = func(); |
5507 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
5508 | *stream = Fits<VirtualRegister, size>::convert(value); |
5509 | } |
5510 | |
5511 | template<typename Functor> |
5512 | void setArgc(unsigned value, Functor func) |
5513 | { |
5514 | if (isWide()) |
5515 | setArgc<OpcodeSize::Wide>(value, func); |
5516 | else |
5517 | setArgc<OpcodeSize::Narrow>(value, func); |
5518 | } |
5519 | |
5520 | template <OpcodeSize size, typename Functor> |
5521 | void setArgc(unsigned value, Functor func) |
5522 | { |
5523 | if (!Fits<unsigned, size>::check(value)) |
5524 | value = func(); |
5525 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
5526 | *stream = Fits<unsigned, size>::convert(value); |
5527 | } |
5528 | |
5529 | template<typename Functor> |
5530 | void setArgv(unsigned value, Functor func) |
5531 | { |
5532 | if (isWide()) |
5533 | setArgv<OpcodeSize::Wide>(value, func); |
5534 | else |
5535 | setArgv<OpcodeSize::Narrow>(value, func); |
5536 | } |
5537 | |
5538 | template <OpcodeSize size, typename Functor> |
5539 | void setArgv(unsigned value, Functor func) |
5540 | { |
5541 | if (!Fits<unsigned, size>::check(value)) |
5542 | value = func(); |
5543 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
5544 | *stream = Fits<unsigned, size>::convert(value); |
5545 | } |
5546 | |
5547 | struct Metadata { |
5548 | WTF_MAKE_NONCOPYABLE(Metadata); |
5549 | |
5550 | public: |
5551 | Metadata(const OpCallEval&) { } |
5552 | |
5553 | LLIntCallLinkInfo m_callLinkInfo; |
5554 | ArrayProfile m_arrayProfile; |
5555 | ValueProfile m_profile; |
5556 | }; |
5557 | |
5558 | Metadata& metadata(CodeBlock* codeBlock) const |
5559 | { |
5560 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
5561 | } |
5562 | |
5563 | Metadata& metadata(ExecState* exec) const |
5564 | { |
5565 | return metadata(exec->codeBlock()); |
5566 | } |
5567 | |
5568 | VirtualRegister m_dst; |
5569 | VirtualRegister m_callee; |
5570 | unsigned m_argc; |
5571 | unsigned m_argv; |
5572 | unsigned m_metadataID; |
5573 | }; |
5574 | |
5575 | struct OpCallVarargs : public Instruction { |
5576 | static constexpr OpcodeID opcodeID = op_call_varargs; |
5577 | |
5578 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg) |
5579 | { |
5580 | |
5581 | auto __metadataID = gen->addMetadataFor(opcodeID); |
5582 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID) |
5583 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID); |
5584 | } |
5585 | |
5586 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
5587 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg) |
5588 | { |
5589 | auto __metadataID = gen->addMetadataFor(opcodeID); |
5590 | return emit<size, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID); |
5591 | } |
5592 | |
5593 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
5594 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID) |
5595 | { |
5596 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID); |
5597 | if (shouldAssert == Assert) |
5598 | ASSERT(didEmit); |
5599 | return didEmit; |
5600 | } |
5601 | |
5602 | private: |
5603 | template<OpcodeSize size, bool recordOpcode> |
5604 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID) |
5605 | { |
5606 | if (size == OpcodeSize::Wide) |
5607 | gen->alignWideOpcode(); |
5608 | if (Fits<unsigned, size>::check(opcodeID) |
5609 | && Fits<VirtualRegister, size>::check(dst) |
5610 | && Fits<VirtualRegister, size>::check(callee) |
5611 | && Fits<VirtualRegister, size>::check(thisValue) |
5612 | && Fits<VirtualRegister, size>::check(arguments) |
5613 | && Fits<VirtualRegister, size>::check(firstFree) |
5614 | && Fits<int, size>::check(firstVarArg) |
5615 | && Fits<unsigned, size>::check(__metadataID) |
5616 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
5617 | if (recordOpcode) |
5618 | gen->recordOpcode(opcodeID); |
5619 | if (size == OpcodeSize::Wide) |
5620 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
5621 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
5622 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
5623 | gen->write(Fits<VirtualRegister, size>::convert(callee)); |
5624 | gen->write(Fits<VirtualRegister, size>::convert(thisValue)); |
5625 | gen->write(Fits<VirtualRegister, size>::convert(arguments)); |
5626 | gen->write(Fits<VirtualRegister, size>::convert(firstFree)); |
5627 | gen->write(Fits<int, size>::convert(firstVarArg)); |
5628 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
5629 | return true; |
5630 | } |
5631 | return false; |
5632 | } |
5633 | |
5634 | public: |
5635 | template<typename Block> |
5636 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
5637 | { |
5638 | dumper->printLocationAndOp(__location, &"*call_varargs" [!__isWide]); |
5639 | dumper->dumpOperand(m_dst, true); |
5640 | dumper->dumpOperand(m_callee, false); |
5641 | dumper->dumpOperand(m_thisValue, false); |
5642 | dumper->dumpOperand(m_arguments, false); |
5643 | dumper->dumpOperand(m_firstFree, false); |
5644 | dumper->dumpOperand(m_firstVarArg, false); |
5645 | } |
5646 | |
5647 | OpCallVarargs(const uint8_t* stream) |
5648 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
5649 | , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
5650 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
5651 | , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
5652 | , m_firstFree(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5])) |
5653 | , m_firstVarArg(Fits<int, OpcodeSize::Narrow>::convert(stream[6])) |
5654 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7])) |
5655 | { |
5656 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
5657 | } |
5658 | |
5659 | OpCallVarargs(const uint32_t* stream) |
5660 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
5661 | , m_callee(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
5662 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
5663 | , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
5664 | , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[5])) |
5665 | , m_firstVarArg(Fits<int, OpcodeSize::Wide>::convert(stream[6])) |
5666 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[7])) |
5667 | { |
5668 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
5669 | } |
5670 | |
5671 | static OpCallVarargs decode(const uint8_t* stream) |
5672 | { |
5673 | if (*stream != op_wide) |
5674 | return { stream }; |
5675 | |
5676 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
5677 | return { wideStream }; |
5678 | } |
5679 | |
5680 | template<typename Functor> |
5681 | void setDst(VirtualRegister value, Functor func) |
5682 | { |
5683 | if (isWide()) |
5684 | setDst<OpcodeSize::Wide>(value, func); |
5685 | else |
5686 | setDst<OpcodeSize::Narrow>(value, func); |
5687 | } |
5688 | |
5689 | template <OpcodeSize size, typename Functor> |
5690 | void setDst(VirtualRegister value, Functor func) |
5691 | { |
5692 | if (!Fits<VirtualRegister, size>::check(value)) |
5693 | value = func(); |
5694 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
5695 | *stream = Fits<VirtualRegister, size>::convert(value); |
5696 | } |
5697 | |
5698 | template<typename Functor> |
5699 | void setCallee(VirtualRegister value, Functor func) |
5700 | { |
5701 | if (isWide()) |
5702 | setCallee<OpcodeSize::Wide>(value, func); |
5703 | else |
5704 | setCallee<OpcodeSize::Narrow>(value, func); |
5705 | } |
5706 | |
5707 | template <OpcodeSize size, typename Functor> |
5708 | void setCallee(VirtualRegister value, Functor func) |
5709 | { |
5710 | if (!Fits<VirtualRegister, size>::check(value)) |
5711 | value = func(); |
5712 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
5713 | *stream = Fits<VirtualRegister, size>::convert(value); |
5714 | } |
5715 | |
5716 | template<typename Functor> |
5717 | void setThisValue(VirtualRegister value, Functor func) |
5718 | { |
5719 | if (isWide()) |
5720 | setThisValue<OpcodeSize::Wide>(value, func); |
5721 | else |
5722 | setThisValue<OpcodeSize::Narrow>(value, func); |
5723 | } |
5724 | |
5725 | template <OpcodeSize size, typename Functor> |
5726 | void setThisValue(VirtualRegister value, Functor func) |
5727 | { |
5728 | if (!Fits<VirtualRegister, size>::check(value)) |
5729 | value = func(); |
5730 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
5731 | *stream = Fits<VirtualRegister, size>::convert(value); |
5732 | } |
5733 | |
5734 | template<typename Functor> |
5735 | void setArguments(VirtualRegister value, Functor func) |
5736 | { |
5737 | if (isWide()) |
5738 | setArguments<OpcodeSize::Wide>(value, func); |
5739 | else |
5740 | setArguments<OpcodeSize::Narrow>(value, func); |
5741 | } |
5742 | |
5743 | template <OpcodeSize size, typename Functor> |
5744 | void setArguments(VirtualRegister value, Functor func) |
5745 | { |
5746 | if (!Fits<VirtualRegister, size>::check(value)) |
5747 | value = func(); |
5748 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
5749 | *stream = Fits<VirtualRegister, size>::convert(value); |
5750 | } |
5751 | |
5752 | template<typename Functor> |
5753 | void setFirstFree(VirtualRegister value, Functor func) |
5754 | { |
5755 | if (isWide()) |
5756 | setFirstFree<OpcodeSize::Wide>(value, func); |
5757 | else |
5758 | setFirstFree<OpcodeSize::Narrow>(value, func); |
5759 | } |
5760 | |
5761 | template <OpcodeSize size, typename Functor> |
5762 | void setFirstFree(VirtualRegister value, Functor func) |
5763 | { |
5764 | if (!Fits<VirtualRegister, size>::check(value)) |
5765 | value = func(); |
5766 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value); |
5767 | *stream = Fits<VirtualRegister, size>::convert(value); |
5768 | } |
5769 | |
5770 | template<typename Functor> |
5771 | void setFirstVarArg(int value, Functor func) |
5772 | { |
5773 | if (isWide()) |
5774 | setFirstVarArg<OpcodeSize::Wide>(value, func); |
5775 | else |
5776 | setFirstVarArg<OpcodeSize::Narrow>(value, func); |
5777 | } |
5778 | |
5779 | template <OpcodeSize size, typename Functor> |
5780 | void setFirstVarArg(int value, Functor func) |
5781 | { |
5782 | if (!Fits<int, size>::check(value)) |
5783 | value = func(); |
5784 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 6 * size + PaddingBySize<size>::value); |
5785 | *stream = Fits<int, size>::convert(value); |
5786 | } |
5787 | |
5788 | struct Metadata { |
5789 | WTF_MAKE_NONCOPYABLE(Metadata); |
5790 | |
5791 | public: |
5792 | Metadata(const OpCallVarargs&) { } |
5793 | |
5794 | ArrayProfile m_arrayProfile; |
5795 | ValueProfile m_profile; |
5796 | }; |
5797 | |
5798 | Metadata& metadata(CodeBlock* codeBlock) const |
5799 | { |
5800 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
5801 | } |
5802 | |
5803 | Metadata& metadata(ExecState* exec) const |
5804 | { |
5805 | return metadata(exec->codeBlock()); |
5806 | } |
5807 | |
5808 | VirtualRegister m_dst; |
5809 | VirtualRegister m_callee; |
5810 | VirtualRegister m_thisValue; |
5811 | VirtualRegister m_arguments; |
5812 | VirtualRegister m_firstFree; |
5813 | int m_firstVarArg; |
5814 | unsigned m_metadataID; |
5815 | }; |
5816 | |
5817 | struct OpTailCallVarargs : public Instruction { |
5818 | static constexpr OpcodeID opcodeID = op_tail_call_varargs; |
5819 | |
5820 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg) |
5821 | { |
5822 | |
5823 | auto __metadataID = gen->addMetadataFor(opcodeID); |
5824 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID) |
5825 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID); |
5826 | } |
5827 | |
5828 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
5829 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg) |
5830 | { |
5831 | auto __metadataID = gen->addMetadataFor(opcodeID); |
5832 | return emit<size, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID); |
5833 | } |
5834 | |
5835 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
5836 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID) |
5837 | { |
5838 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID); |
5839 | if (shouldAssert == Assert) |
5840 | ASSERT(didEmit); |
5841 | return didEmit; |
5842 | } |
5843 | |
5844 | private: |
5845 | template<OpcodeSize size, bool recordOpcode> |
5846 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID) |
5847 | { |
5848 | if (size == OpcodeSize::Wide) |
5849 | gen->alignWideOpcode(); |
5850 | if (Fits<unsigned, size>::check(opcodeID) |
5851 | && Fits<VirtualRegister, size>::check(dst) |
5852 | && Fits<VirtualRegister, size>::check(callee) |
5853 | && Fits<VirtualRegister, size>::check(thisValue) |
5854 | && Fits<VirtualRegister, size>::check(arguments) |
5855 | && Fits<VirtualRegister, size>::check(firstFree) |
5856 | && Fits<int, size>::check(firstVarArg) |
5857 | && Fits<unsigned, size>::check(__metadataID) |
5858 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
5859 | if (recordOpcode) |
5860 | gen->recordOpcode(opcodeID); |
5861 | if (size == OpcodeSize::Wide) |
5862 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
5863 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
5864 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
5865 | gen->write(Fits<VirtualRegister, size>::convert(callee)); |
5866 | gen->write(Fits<VirtualRegister, size>::convert(thisValue)); |
5867 | gen->write(Fits<VirtualRegister, size>::convert(arguments)); |
5868 | gen->write(Fits<VirtualRegister, size>::convert(firstFree)); |
5869 | gen->write(Fits<int, size>::convert(firstVarArg)); |
5870 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
5871 | return true; |
5872 | } |
5873 | return false; |
5874 | } |
5875 | |
5876 | public: |
5877 | template<typename Block> |
5878 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
5879 | { |
5880 | dumper->printLocationAndOp(__location, &"*tail_call_varargs" [!__isWide]); |
5881 | dumper->dumpOperand(m_dst, true); |
5882 | dumper->dumpOperand(m_callee, false); |
5883 | dumper->dumpOperand(m_thisValue, false); |
5884 | dumper->dumpOperand(m_arguments, false); |
5885 | dumper->dumpOperand(m_firstFree, false); |
5886 | dumper->dumpOperand(m_firstVarArg, false); |
5887 | } |
5888 | |
5889 | OpTailCallVarargs(const uint8_t* stream) |
5890 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
5891 | , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
5892 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
5893 | , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
5894 | , m_firstFree(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5])) |
5895 | , m_firstVarArg(Fits<int, OpcodeSize::Narrow>::convert(stream[6])) |
5896 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7])) |
5897 | { |
5898 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
5899 | } |
5900 | |
5901 | OpTailCallVarargs(const uint32_t* stream) |
5902 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
5903 | , m_callee(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
5904 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
5905 | , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
5906 | , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[5])) |
5907 | , m_firstVarArg(Fits<int, OpcodeSize::Wide>::convert(stream[6])) |
5908 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[7])) |
5909 | { |
5910 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
5911 | } |
5912 | |
5913 | static OpTailCallVarargs decode(const uint8_t* stream) |
5914 | { |
5915 | if (*stream != op_wide) |
5916 | return { stream }; |
5917 | |
5918 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
5919 | return { wideStream }; |
5920 | } |
5921 | |
5922 | template<typename Functor> |
5923 | void setDst(VirtualRegister value, Functor func) |
5924 | { |
5925 | if (isWide()) |
5926 | setDst<OpcodeSize::Wide>(value, func); |
5927 | else |
5928 | setDst<OpcodeSize::Narrow>(value, func); |
5929 | } |
5930 | |
5931 | template <OpcodeSize size, typename Functor> |
5932 | void setDst(VirtualRegister value, Functor func) |
5933 | { |
5934 | if (!Fits<VirtualRegister, size>::check(value)) |
5935 | value = func(); |
5936 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
5937 | *stream = Fits<VirtualRegister, size>::convert(value); |
5938 | } |
5939 | |
5940 | template<typename Functor> |
5941 | void setCallee(VirtualRegister value, Functor func) |
5942 | { |
5943 | if (isWide()) |
5944 | setCallee<OpcodeSize::Wide>(value, func); |
5945 | else |
5946 | setCallee<OpcodeSize::Narrow>(value, func); |
5947 | } |
5948 | |
5949 | template <OpcodeSize size, typename Functor> |
5950 | void setCallee(VirtualRegister value, Functor func) |
5951 | { |
5952 | if (!Fits<VirtualRegister, size>::check(value)) |
5953 | value = func(); |
5954 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
5955 | *stream = Fits<VirtualRegister, size>::convert(value); |
5956 | } |
5957 | |
5958 | template<typename Functor> |
5959 | void setThisValue(VirtualRegister value, Functor func) |
5960 | { |
5961 | if (isWide()) |
5962 | setThisValue<OpcodeSize::Wide>(value, func); |
5963 | else |
5964 | setThisValue<OpcodeSize::Narrow>(value, func); |
5965 | } |
5966 | |
5967 | template <OpcodeSize size, typename Functor> |
5968 | void setThisValue(VirtualRegister value, Functor func) |
5969 | { |
5970 | if (!Fits<VirtualRegister, size>::check(value)) |
5971 | value = func(); |
5972 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
5973 | *stream = Fits<VirtualRegister, size>::convert(value); |
5974 | } |
5975 | |
5976 | template<typename Functor> |
5977 | void setArguments(VirtualRegister value, Functor func) |
5978 | { |
5979 | if (isWide()) |
5980 | setArguments<OpcodeSize::Wide>(value, func); |
5981 | else |
5982 | setArguments<OpcodeSize::Narrow>(value, func); |
5983 | } |
5984 | |
5985 | template <OpcodeSize size, typename Functor> |
5986 | void setArguments(VirtualRegister value, Functor func) |
5987 | { |
5988 | if (!Fits<VirtualRegister, size>::check(value)) |
5989 | value = func(); |
5990 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
5991 | *stream = Fits<VirtualRegister, size>::convert(value); |
5992 | } |
5993 | |
5994 | template<typename Functor> |
5995 | void setFirstFree(VirtualRegister value, Functor func) |
5996 | { |
5997 | if (isWide()) |
5998 | setFirstFree<OpcodeSize::Wide>(value, func); |
5999 | else |
6000 | setFirstFree<OpcodeSize::Narrow>(value, func); |
6001 | } |
6002 | |
6003 | template <OpcodeSize size, typename Functor> |
6004 | void setFirstFree(VirtualRegister value, Functor func) |
6005 | { |
6006 | if (!Fits<VirtualRegister, size>::check(value)) |
6007 | value = func(); |
6008 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value); |
6009 | *stream = Fits<VirtualRegister, size>::convert(value); |
6010 | } |
6011 | |
6012 | template<typename Functor> |
6013 | void setFirstVarArg(int value, Functor func) |
6014 | { |
6015 | if (isWide()) |
6016 | setFirstVarArg<OpcodeSize::Wide>(value, func); |
6017 | else |
6018 | setFirstVarArg<OpcodeSize::Narrow>(value, func); |
6019 | } |
6020 | |
6021 | template <OpcodeSize size, typename Functor> |
6022 | void setFirstVarArg(int value, Functor func) |
6023 | { |
6024 | if (!Fits<int, size>::check(value)) |
6025 | value = func(); |
6026 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 6 * size + PaddingBySize<size>::value); |
6027 | *stream = Fits<int, size>::convert(value); |
6028 | } |
6029 | |
6030 | struct Metadata { |
6031 | WTF_MAKE_NONCOPYABLE(Metadata); |
6032 | |
6033 | public: |
6034 | Metadata(const OpTailCallVarargs&) { } |
6035 | |
6036 | ArrayProfile m_arrayProfile; |
6037 | ValueProfile m_profile; |
6038 | }; |
6039 | |
6040 | Metadata& metadata(CodeBlock* codeBlock) const |
6041 | { |
6042 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
6043 | } |
6044 | |
6045 | Metadata& metadata(ExecState* exec) const |
6046 | { |
6047 | return metadata(exec->codeBlock()); |
6048 | } |
6049 | |
6050 | VirtualRegister m_dst; |
6051 | VirtualRegister m_callee; |
6052 | VirtualRegister m_thisValue; |
6053 | VirtualRegister m_arguments; |
6054 | VirtualRegister m_firstFree; |
6055 | int m_firstVarArg; |
6056 | unsigned m_metadataID; |
6057 | }; |
6058 | |
6059 | struct OpTailCallForwardArguments : public Instruction { |
6060 | static constexpr OpcodeID opcodeID = op_tail_call_forward_arguments; |
6061 | |
6062 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg) |
6063 | { |
6064 | |
6065 | auto __metadataID = gen->addMetadataFor(opcodeID); |
6066 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID) |
6067 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID); |
6068 | } |
6069 | |
6070 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
6071 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg) |
6072 | { |
6073 | auto __metadataID = gen->addMetadataFor(opcodeID); |
6074 | return emit<size, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID); |
6075 | } |
6076 | |
6077 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
6078 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID) |
6079 | { |
6080 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID); |
6081 | if (shouldAssert == Assert) |
6082 | ASSERT(didEmit); |
6083 | return didEmit; |
6084 | } |
6085 | |
6086 | private: |
6087 | template<OpcodeSize size, bool recordOpcode> |
6088 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID) |
6089 | { |
6090 | if (size == OpcodeSize::Wide) |
6091 | gen->alignWideOpcode(); |
6092 | if (Fits<unsigned, size>::check(opcodeID) |
6093 | && Fits<VirtualRegister, size>::check(dst) |
6094 | && Fits<VirtualRegister, size>::check(callee) |
6095 | && Fits<VirtualRegister, size>::check(thisValue) |
6096 | && Fits<VirtualRegister, size>::check(arguments) |
6097 | && Fits<VirtualRegister, size>::check(firstFree) |
6098 | && Fits<int, size>::check(firstVarArg) |
6099 | && Fits<unsigned, size>::check(__metadataID) |
6100 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
6101 | if (recordOpcode) |
6102 | gen->recordOpcode(opcodeID); |
6103 | if (size == OpcodeSize::Wide) |
6104 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
6105 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
6106 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
6107 | gen->write(Fits<VirtualRegister, size>::convert(callee)); |
6108 | gen->write(Fits<VirtualRegister, size>::convert(thisValue)); |
6109 | gen->write(Fits<VirtualRegister, size>::convert(arguments)); |
6110 | gen->write(Fits<VirtualRegister, size>::convert(firstFree)); |
6111 | gen->write(Fits<int, size>::convert(firstVarArg)); |
6112 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
6113 | return true; |
6114 | } |
6115 | return false; |
6116 | } |
6117 | |
6118 | public: |
6119 | template<typename Block> |
6120 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
6121 | { |
6122 | dumper->printLocationAndOp(__location, &"*tail_call_forward_arguments" [!__isWide]); |
6123 | dumper->dumpOperand(m_dst, true); |
6124 | dumper->dumpOperand(m_callee, false); |
6125 | dumper->dumpOperand(m_thisValue, false); |
6126 | dumper->dumpOperand(m_arguments, false); |
6127 | dumper->dumpOperand(m_firstFree, false); |
6128 | dumper->dumpOperand(m_firstVarArg, false); |
6129 | } |
6130 | |
6131 | OpTailCallForwardArguments(const uint8_t* stream) |
6132 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
6133 | , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
6134 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
6135 | , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
6136 | , m_firstFree(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5])) |
6137 | , m_firstVarArg(Fits<int, OpcodeSize::Narrow>::convert(stream[6])) |
6138 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7])) |
6139 | { |
6140 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
6141 | } |
6142 | |
6143 | OpTailCallForwardArguments(const uint32_t* stream) |
6144 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
6145 | , m_callee(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
6146 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
6147 | , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
6148 | , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[5])) |
6149 | , m_firstVarArg(Fits<int, OpcodeSize::Wide>::convert(stream[6])) |
6150 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[7])) |
6151 | { |
6152 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
6153 | } |
6154 | |
6155 | static OpTailCallForwardArguments decode(const uint8_t* stream) |
6156 | { |
6157 | if (*stream != op_wide) |
6158 | return { stream }; |
6159 | |
6160 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
6161 | return { wideStream }; |
6162 | } |
6163 | |
6164 | template<typename Functor> |
6165 | void setDst(VirtualRegister value, Functor func) |
6166 | { |
6167 | if (isWide()) |
6168 | setDst<OpcodeSize::Wide>(value, func); |
6169 | else |
6170 | setDst<OpcodeSize::Narrow>(value, func); |
6171 | } |
6172 | |
6173 | template <OpcodeSize size, typename Functor> |
6174 | void setDst(VirtualRegister value, Functor func) |
6175 | { |
6176 | if (!Fits<VirtualRegister, size>::check(value)) |
6177 | value = func(); |
6178 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
6179 | *stream = Fits<VirtualRegister, size>::convert(value); |
6180 | } |
6181 | |
6182 | template<typename Functor> |
6183 | void setCallee(VirtualRegister value, Functor func) |
6184 | { |
6185 | if (isWide()) |
6186 | setCallee<OpcodeSize::Wide>(value, func); |
6187 | else |
6188 | setCallee<OpcodeSize::Narrow>(value, func); |
6189 | } |
6190 | |
6191 | template <OpcodeSize size, typename Functor> |
6192 | void setCallee(VirtualRegister value, Functor func) |
6193 | { |
6194 | if (!Fits<VirtualRegister, size>::check(value)) |
6195 | value = func(); |
6196 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
6197 | *stream = Fits<VirtualRegister, size>::convert(value); |
6198 | } |
6199 | |
6200 | template<typename Functor> |
6201 | void setThisValue(VirtualRegister value, Functor func) |
6202 | { |
6203 | if (isWide()) |
6204 | setThisValue<OpcodeSize::Wide>(value, func); |
6205 | else |
6206 | setThisValue<OpcodeSize::Narrow>(value, func); |
6207 | } |
6208 | |
6209 | template <OpcodeSize size, typename Functor> |
6210 | void setThisValue(VirtualRegister value, Functor func) |
6211 | { |
6212 | if (!Fits<VirtualRegister, size>::check(value)) |
6213 | value = func(); |
6214 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
6215 | *stream = Fits<VirtualRegister, size>::convert(value); |
6216 | } |
6217 | |
6218 | template<typename Functor> |
6219 | void setArguments(VirtualRegister value, Functor func) |
6220 | { |
6221 | if (isWide()) |
6222 | setArguments<OpcodeSize::Wide>(value, func); |
6223 | else |
6224 | setArguments<OpcodeSize::Narrow>(value, func); |
6225 | } |
6226 | |
6227 | template <OpcodeSize size, typename Functor> |
6228 | void setArguments(VirtualRegister value, Functor func) |
6229 | { |
6230 | if (!Fits<VirtualRegister, size>::check(value)) |
6231 | value = func(); |
6232 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
6233 | *stream = Fits<VirtualRegister, size>::convert(value); |
6234 | } |
6235 | |
6236 | template<typename Functor> |
6237 | void setFirstFree(VirtualRegister value, Functor func) |
6238 | { |
6239 | if (isWide()) |
6240 | setFirstFree<OpcodeSize::Wide>(value, func); |
6241 | else |
6242 | setFirstFree<OpcodeSize::Narrow>(value, func); |
6243 | } |
6244 | |
6245 | template <OpcodeSize size, typename Functor> |
6246 | void setFirstFree(VirtualRegister value, Functor func) |
6247 | { |
6248 | if (!Fits<VirtualRegister, size>::check(value)) |
6249 | value = func(); |
6250 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value); |
6251 | *stream = Fits<VirtualRegister, size>::convert(value); |
6252 | } |
6253 | |
6254 | template<typename Functor> |
6255 | void setFirstVarArg(int value, Functor func) |
6256 | { |
6257 | if (isWide()) |
6258 | setFirstVarArg<OpcodeSize::Wide>(value, func); |
6259 | else |
6260 | setFirstVarArg<OpcodeSize::Narrow>(value, func); |
6261 | } |
6262 | |
6263 | template <OpcodeSize size, typename Functor> |
6264 | void setFirstVarArg(int value, Functor func) |
6265 | { |
6266 | if (!Fits<int, size>::check(value)) |
6267 | value = func(); |
6268 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 6 * size + PaddingBySize<size>::value); |
6269 | *stream = Fits<int, size>::convert(value); |
6270 | } |
6271 | |
6272 | struct Metadata { |
6273 | WTF_MAKE_NONCOPYABLE(Metadata); |
6274 | |
6275 | public: |
6276 | Metadata(const OpTailCallForwardArguments&) { } |
6277 | |
6278 | ArrayProfile m_arrayProfile; |
6279 | ValueProfile m_profile; |
6280 | }; |
6281 | |
6282 | Metadata& metadata(CodeBlock* codeBlock) const |
6283 | { |
6284 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
6285 | } |
6286 | |
6287 | Metadata& metadata(ExecState* exec) const |
6288 | { |
6289 | return metadata(exec->codeBlock()); |
6290 | } |
6291 | |
6292 | VirtualRegister m_dst; |
6293 | VirtualRegister m_callee; |
6294 | VirtualRegister m_thisValue; |
6295 | VirtualRegister m_arguments; |
6296 | VirtualRegister m_firstFree; |
6297 | int m_firstVarArg; |
6298 | unsigned m_metadataID; |
6299 | }; |
6300 | |
6301 | struct OpConstruct : public Instruction { |
6302 | static constexpr OpcodeID opcodeID = op_construct; |
6303 | |
6304 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv) |
6305 | { |
6306 | |
6307 | auto __metadataID = gen->addMetadataFor(opcodeID); |
6308 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID) |
6309 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, callee, argc, argv, __metadataID); |
6310 | } |
6311 | |
6312 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
6313 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv) |
6314 | { |
6315 | auto __metadataID = gen->addMetadataFor(opcodeID); |
6316 | return emit<size, shouldAssert>(gen, dst, callee, argc, argv, __metadataID); |
6317 | } |
6318 | |
6319 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
6320 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID) |
6321 | { |
6322 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, argc, argv, __metadataID); |
6323 | if (shouldAssert == Assert) |
6324 | ASSERT(didEmit); |
6325 | return didEmit; |
6326 | } |
6327 | |
6328 | private: |
6329 | template<OpcodeSize size, bool recordOpcode> |
6330 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID) |
6331 | { |
6332 | if (size == OpcodeSize::Wide) |
6333 | gen->alignWideOpcode(); |
6334 | if (Fits<unsigned, size>::check(opcodeID) |
6335 | && Fits<VirtualRegister, size>::check(dst) |
6336 | && Fits<VirtualRegister, size>::check(callee) |
6337 | && Fits<unsigned, size>::check(argc) |
6338 | && Fits<unsigned, size>::check(argv) |
6339 | && Fits<unsigned, size>::check(__metadataID) |
6340 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
6341 | if (recordOpcode) |
6342 | gen->recordOpcode(opcodeID); |
6343 | if (size == OpcodeSize::Wide) |
6344 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
6345 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
6346 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
6347 | gen->write(Fits<VirtualRegister, size>::convert(callee)); |
6348 | gen->write(Fits<unsigned, size>::convert(argc)); |
6349 | gen->write(Fits<unsigned, size>::convert(argv)); |
6350 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
6351 | return true; |
6352 | } |
6353 | return false; |
6354 | } |
6355 | |
6356 | public: |
6357 | template<typename Block> |
6358 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
6359 | { |
6360 | dumper->printLocationAndOp(__location, &"*construct" [!__isWide]); |
6361 | dumper->dumpOperand(m_dst, true); |
6362 | dumper->dumpOperand(m_callee, false); |
6363 | dumper->dumpOperand(m_argc, false); |
6364 | dumper->dumpOperand(m_argv, false); |
6365 | } |
6366 | |
6367 | OpConstruct(const uint8_t* stream) |
6368 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
6369 | , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
6370 | , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
6371 | , m_argv(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
6372 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
6373 | { |
6374 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
6375 | } |
6376 | |
6377 | OpConstruct(const uint32_t* stream) |
6378 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
6379 | , m_callee(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
6380 | , m_argc(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
6381 | , m_argv(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
6382 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
6383 | { |
6384 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
6385 | } |
6386 | |
6387 | static OpConstruct decode(const uint8_t* stream) |
6388 | { |
6389 | if (*stream != op_wide) |
6390 | return { stream }; |
6391 | |
6392 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
6393 | return { wideStream }; |
6394 | } |
6395 | |
6396 | template<typename Functor> |
6397 | void setDst(VirtualRegister value, Functor func) |
6398 | { |
6399 | if (isWide()) |
6400 | setDst<OpcodeSize::Wide>(value, func); |
6401 | else |
6402 | setDst<OpcodeSize::Narrow>(value, func); |
6403 | } |
6404 | |
6405 | template <OpcodeSize size, typename Functor> |
6406 | void setDst(VirtualRegister value, Functor func) |
6407 | { |
6408 | if (!Fits<VirtualRegister, size>::check(value)) |
6409 | value = func(); |
6410 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
6411 | *stream = Fits<VirtualRegister, size>::convert(value); |
6412 | } |
6413 | |
6414 | template<typename Functor> |
6415 | void setCallee(VirtualRegister value, Functor func) |
6416 | { |
6417 | if (isWide()) |
6418 | setCallee<OpcodeSize::Wide>(value, func); |
6419 | else |
6420 | setCallee<OpcodeSize::Narrow>(value, func); |
6421 | } |
6422 | |
6423 | template <OpcodeSize size, typename Functor> |
6424 | void setCallee(VirtualRegister value, Functor func) |
6425 | { |
6426 | if (!Fits<VirtualRegister, size>::check(value)) |
6427 | value = func(); |
6428 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
6429 | *stream = Fits<VirtualRegister, size>::convert(value); |
6430 | } |
6431 | |
6432 | template<typename Functor> |
6433 | void setArgc(unsigned value, Functor func) |
6434 | { |
6435 | if (isWide()) |
6436 | setArgc<OpcodeSize::Wide>(value, func); |
6437 | else |
6438 | setArgc<OpcodeSize::Narrow>(value, func); |
6439 | } |
6440 | |
6441 | template <OpcodeSize size, typename Functor> |
6442 | void setArgc(unsigned value, Functor func) |
6443 | { |
6444 | if (!Fits<unsigned, size>::check(value)) |
6445 | value = func(); |
6446 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
6447 | *stream = Fits<unsigned, size>::convert(value); |
6448 | } |
6449 | |
6450 | template<typename Functor> |
6451 | void setArgv(unsigned value, Functor func) |
6452 | { |
6453 | if (isWide()) |
6454 | setArgv<OpcodeSize::Wide>(value, func); |
6455 | else |
6456 | setArgv<OpcodeSize::Narrow>(value, func); |
6457 | } |
6458 | |
6459 | template <OpcodeSize size, typename Functor> |
6460 | void setArgv(unsigned value, Functor func) |
6461 | { |
6462 | if (!Fits<unsigned, size>::check(value)) |
6463 | value = func(); |
6464 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
6465 | *stream = Fits<unsigned, size>::convert(value); |
6466 | } |
6467 | |
6468 | struct Metadata { |
6469 | WTF_MAKE_NONCOPYABLE(Metadata); |
6470 | |
6471 | public: |
6472 | Metadata(const OpConstruct&) { } |
6473 | |
6474 | LLIntCallLinkInfo m_callLinkInfo; |
6475 | ArrayProfile m_arrayProfile; |
6476 | ValueProfile m_profile; |
6477 | }; |
6478 | |
6479 | Metadata& metadata(CodeBlock* codeBlock) const |
6480 | { |
6481 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
6482 | } |
6483 | |
6484 | Metadata& metadata(ExecState* exec) const |
6485 | { |
6486 | return metadata(exec->codeBlock()); |
6487 | } |
6488 | |
6489 | VirtualRegister m_dst; |
6490 | VirtualRegister m_callee; |
6491 | unsigned m_argc; |
6492 | unsigned m_argv; |
6493 | unsigned m_metadataID; |
6494 | }; |
6495 | |
6496 | struct OpConstructVarargs : public Instruction { |
6497 | static constexpr OpcodeID opcodeID = op_construct_varargs; |
6498 | |
6499 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg) |
6500 | { |
6501 | |
6502 | auto __metadataID = gen->addMetadataFor(opcodeID); |
6503 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID) |
6504 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID); |
6505 | } |
6506 | |
6507 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
6508 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg) |
6509 | { |
6510 | auto __metadataID = gen->addMetadataFor(opcodeID); |
6511 | return emit<size, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID); |
6512 | } |
6513 | |
6514 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
6515 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID) |
6516 | { |
6517 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID); |
6518 | if (shouldAssert == Assert) |
6519 | ASSERT(didEmit); |
6520 | return didEmit; |
6521 | } |
6522 | |
6523 | private: |
6524 | template<OpcodeSize size, bool recordOpcode> |
6525 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID) |
6526 | { |
6527 | if (size == OpcodeSize::Wide) |
6528 | gen->alignWideOpcode(); |
6529 | if (Fits<unsigned, size>::check(opcodeID) |
6530 | && Fits<VirtualRegister, size>::check(dst) |
6531 | && Fits<VirtualRegister, size>::check(callee) |
6532 | && Fits<VirtualRegister, size>::check(thisValue) |
6533 | && Fits<VirtualRegister, size>::check(arguments) |
6534 | && Fits<VirtualRegister, size>::check(firstFree) |
6535 | && Fits<int, size>::check(firstVarArg) |
6536 | && Fits<unsigned, size>::check(__metadataID) |
6537 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
6538 | if (recordOpcode) |
6539 | gen->recordOpcode(opcodeID); |
6540 | if (size == OpcodeSize::Wide) |
6541 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
6542 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
6543 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
6544 | gen->write(Fits<VirtualRegister, size>::convert(callee)); |
6545 | gen->write(Fits<VirtualRegister, size>::convert(thisValue)); |
6546 | gen->write(Fits<VirtualRegister, size>::convert(arguments)); |
6547 | gen->write(Fits<VirtualRegister, size>::convert(firstFree)); |
6548 | gen->write(Fits<int, size>::convert(firstVarArg)); |
6549 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
6550 | return true; |
6551 | } |
6552 | return false; |
6553 | } |
6554 | |
6555 | public: |
6556 | template<typename Block> |
6557 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
6558 | { |
6559 | dumper->printLocationAndOp(__location, &"*construct_varargs" [!__isWide]); |
6560 | dumper->dumpOperand(m_dst, true); |
6561 | dumper->dumpOperand(m_callee, false); |
6562 | dumper->dumpOperand(m_thisValue, false); |
6563 | dumper->dumpOperand(m_arguments, false); |
6564 | dumper->dumpOperand(m_firstFree, false); |
6565 | dumper->dumpOperand(m_firstVarArg, false); |
6566 | } |
6567 | |
6568 | OpConstructVarargs(const uint8_t* stream) |
6569 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
6570 | , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
6571 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
6572 | , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
6573 | , m_firstFree(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5])) |
6574 | , m_firstVarArg(Fits<int, OpcodeSize::Narrow>::convert(stream[6])) |
6575 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7])) |
6576 | { |
6577 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
6578 | } |
6579 | |
6580 | OpConstructVarargs(const uint32_t* stream) |
6581 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
6582 | , m_callee(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
6583 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
6584 | , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
6585 | , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[5])) |
6586 | , m_firstVarArg(Fits<int, OpcodeSize::Wide>::convert(stream[6])) |
6587 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[7])) |
6588 | { |
6589 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
6590 | } |
6591 | |
6592 | static OpConstructVarargs decode(const uint8_t* stream) |
6593 | { |
6594 | if (*stream != op_wide) |
6595 | return { stream }; |
6596 | |
6597 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
6598 | return { wideStream }; |
6599 | } |
6600 | |
6601 | template<typename Functor> |
6602 | void setDst(VirtualRegister value, Functor func) |
6603 | { |
6604 | if (isWide()) |
6605 | setDst<OpcodeSize::Wide>(value, func); |
6606 | else |
6607 | setDst<OpcodeSize::Narrow>(value, func); |
6608 | } |
6609 | |
6610 | template <OpcodeSize size, typename Functor> |
6611 | void setDst(VirtualRegister value, Functor func) |
6612 | { |
6613 | if (!Fits<VirtualRegister, size>::check(value)) |
6614 | value = func(); |
6615 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
6616 | *stream = Fits<VirtualRegister, size>::convert(value); |
6617 | } |
6618 | |
6619 | template<typename Functor> |
6620 | void setCallee(VirtualRegister value, Functor func) |
6621 | { |
6622 | if (isWide()) |
6623 | setCallee<OpcodeSize::Wide>(value, func); |
6624 | else |
6625 | setCallee<OpcodeSize::Narrow>(value, func); |
6626 | } |
6627 | |
6628 | template <OpcodeSize size, typename Functor> |
6629 | void setCallee(VirtualRegister value, Functor func) |
6630 | { |
6631 | if (!Fits<VirtualRegister, size>::check(value)) |
6632 | value = func(); |
6633 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
6634 | *stream = Fits<VirtualRegister, size>::convert(value); |
6635 | } |
6636 | |
6637 | template<typename Functor> |
6638 | void setThisValue(VirtualRegister value, Functor func) |
6639 | { |
6640 | if (isWide()) |
6641 | setThisValue<OpcodeSize::Wide>(value, func); |
6642 | else |
6643 | setThisValue<OpcodeSize::Narrow>(value, func); |
6644 | } |
6645 | |
6646 | template <OpcodeSize size, typename Functor> |
6647 | void setThisValue(VirtualRegister value, Functor func) |
6648 | { |
6649 | if (!Fits<VirtualRegister, size>::check(value)) |
6650 | value = func(); |
6651 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
6652 | *stream = Fits<VirtualRegister, size>::convert(value); |
6653 | } |
6654 | |
6655 | template<typename Functor> |
6656 | void setArguments(VirtualRegister value, Functor func) |
6657 | { |
6658 | if (isWide()) |
6659 | setArguments<OpcodeSize::Wide>(value, func); |
6660 | else |
6661 | setArguments<OpcodeSize::Narrow>(value, func); |
6662 | } |
6663 | |
6664 | template <OpcodeSize size, typename Functor> |
6665 | void setArguments(VirtualRegister value, Functor func) |
6666 | { |
6667 | if (!Fits<VirtualRegister, size>::check(value)) |
6668 | value = func(); |
6669 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
6670 | *stream = Fits<VirtualRegister, size>::convert(value); |
6671 | } |
6672 | |
6673 | template<typename Functor> |
6674 | void setFirstFree(VirtualRegister value, Functor func) |
6675 | { |
6676 | if (isWide()) |
6677 | setFirstFree<OpcodeSize::Wide>(value, func); |
6678 | else |
6679 | setFirstFree<OpcodeSize::Narrow>(value, func); |
6680 | } |
6681 | |
6682 | template <OpcodeSize size, typename Functor> |
6683 | void setFirstFree(VirtualRegister value, Functor func) |
6684 | { |
6685 | if (!Fits<VirtualRegister, size>::check(value)) |
6686 | value = func(); |
6687 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value); |
6688 | *stream = Fits<VirtualRegister, size>::convert(value); |
6689 | } |
6690 | |
6691 | template<typename Functor> |
6692 | void setFirstVarArg(int value, Functor func) |
6693 | { |
6694 | if (isWide()) |
6695 | setFirstVarArg<OpcodeSize::Wide>(value, func); |
6696 | else |
6697 | setFirstVarArg<OpcodeSize::Narrow>(value, func); |
6698 | } |
6699 | |
6700 | template <OpcodeSize size, typename Functor> |
6701 | void setFirstVarArg(int value, Functor func) |
6702 | { |
6703 | if (!Fits<int, size>::check(value)) |
6704 | value = func(); |
6705 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 6 * size + PaddingBySize<size>::value); |
6706 | *stream = Fits<int, size>::convert(value); |
6707 | } |
6708 | |
6709 | struct Metadata { |
6710 | WTF_MAKE_NONCOPYABLE(Metadata); |
6711 | |
6712 | public: |
6713 | Metadata(const OpConstructVarargs&) { } |
6714 | |
6715 | ArrayProfile m_arrayProfile; |
6716 | ValueProfile m_profile; |
6717 | }; |
6718 | |
6719 | Metadata& metadata(CodeBlock* codeBlock) const |
6720 | { |
6721 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
6722 | } |
6723 | |
6724 | Metadata& metadata(ExecState* exec) const |
6725 | { |
6726 | return metadata(exec->codeBlock()); |
6727 | } |
6728 | |
6729 | VirtualRegister m_dst; |
6730 | VirtualRegister m_callee; |
6731 | VirtualRegister m_thisValue; |
6732 | VirtualRegister m_arguments; |
6733 | VirtualRegister m_firstFree; |
6734 | int m_firstVarArg; |
6735 | unsigned m_metadataID; |
6736 | }; |
6737 | |
6738 | struct OpResolveScope : public Instruction { |
6739 | static constexpr OpcodeID opcodeID = op_resolve_scope; |
6740 | |
6741 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth) |
6742 | { |
6743 | |
6744 | auto __metadataID = gen->addMetadataFor(opcodeID); |
6745 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID) |
6746 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID); |
6747 | } |
6748 | |
6749 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
6750 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth) |
6751 | { |
6752 | auto __metadataID = gen->addMetadataFor(opcodeID); |
6753 | return emit<size, shouldAssert>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID); |
6754 | } |
6755 | |
6756 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
6757 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth, unsigned __metadataID) |
6758 | { |
6759 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID); |
6760 | if (shouldAssert == Assert) |
6761 | ASSERT(didEmit); |
6762 | return didEmit; |
6763 | } |
6764 | |
6765 | private: |
6766 | template<OpcodeSize size, bool recordOpcode> |
6767 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth, unsigned __metadataID) |
6768 | { |
6769 | if (size == OpcodeSize::Wide) |
6770 | gen->alignWideOpcode(); |
6771 | if (Fits<unsigned, size>::check(opcodeID) |
6772 | && Fits<VirtualRegister, size>::check(dst) |
6773 | && Fits<VirtualRegister, size>::check(scope) |
6774 | && Fits<unsigned, size>::check(var) |
6775 | && Fits<ResolveType, size>::check(resolveType) |
6776 | && Fits<unsigned, size>::check(localScopeDepth) |
6777 | && Fits<unsigned, size>::check(__metadataID) |
6778 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
6779 | if (recordOpcode) |
6780 | gen->recordOpcode(opcodeID); |
6781 | if (size == OpcodeSize::Wide) |
6782 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
6783 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
6784 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
6785 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
6786 | gen->write(Fits<unsigned, size>::convert(var)); |
6787 | gen->write(Fits<ResolveType, size>::convert(resolveType)); |
6788 | gen->write(Fits<unsigned, size>::convert(localScopeDepth)); |
6789 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
6790 | return true; |
6791 | } |
6792 | return false; |
6793 | } |
6794 | |
6795 | public: |
6796 | template<typename Block> |
6797 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
6798 | { |
6799 | dumper->printLocationAndOp(__location, &"*resolve_scope" [!__isWide]); |
6800 | dumper->dumpOperand(m_dst, true); |
6801 | dumper->dumpOperand(m_scope, false); |
6802 | dumper->dumpOperand(m_var, false); |
6803 | dumper->dumpOperand(m_resolveType, false); |
6804 | dumper->dumpOperand(m_localScopeDepth, false); |
6805 | } |
6806 | |
6807 | OpResolveScope(const uint8_t* stream) |
6808 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
6809 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
6810 | , m_var(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
6811 | , m_resolveType(Fits<ResolveType, OpcodeSize::Narrow>::convert(stream[4])) |
6812 | , m_localScopeDepth(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
6813 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6])) |
6814 | { |
6815 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
6816 | } |
6817 | |
6818 | OpResolveScope(const uint32_t* stream) |
6819 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
6820 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
6821 | , m_var(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
6822 | , m_resolveType(Fits<ResolveType, OpcodeSize::Wide>::convert(stream[4])) |
6823 | , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
6824 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[6])) |
6825 | { |
6826 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
6827 | } |
6828 | |
6829 | static OpResolveScope decode(const uint8_t* stream) |
6830 | { |
6831 | if (*stream != op_wide) |
6832 | return { stream }; |
6833 | |
6834 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
6835 | return { wideStream }; |
6836 | } |
6837 | |
6838 | template<typename Functor> |
6839 | void setDst(VirtualRegister value, Functor func) |
6840 | { |
6841 | if (isWide()) |
6842 | setDst<OpcodeSize::Wide>(value, func); |
6843 | else |
6844 | setDst<OpcodeSize::Narrow>(value, func); |
6845 | } |
6846 | |
6847 | template <OpcodeSize size, typename Functor> |
6848 | void setDst(VirtualRegister value, Functor func) |
6849 | { |
6850 | if (!Fits<VirtualRegister, size>::check(value)) |
6851 | value = func(); |
6852 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
6853 | *stream = Fits<VirtualRegister, size>::convert(value); |
6854 | } |
6855 | |
6856 | template<typename Functor> |
6857 | void setScope(VirtualRegister value, Functor func) |
6858 | { |
6859 | if (isWide()) |
6860 | setScope<OpcodeSize::Wide>(value, func); |
6861 | else |
6862 | setScope<OpcodeSize::Narrow>(value, func); |
6863 | } |
6864 | |
6865 | template <OpcodeSize size, typename Functor> |
6866 | void setScope(VirtualRegister value, Functor func) |
6867 | { |
6868 | if (!Fits<VirtualRegister, size>::check(value)) |
6869 | value = func(); |
6870 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
6871 | *stream = Fits<VirtualRegister, size>::convert(value); |
6872 | } |
6873 | |
6874 | template<typename Functor> |
6875 | void setVar(unsigned value, Functor func) |
6876 | { |
6877 | if (isWide()) |
6878 | setVar<OpcodeSize::Wide>(value, func); |
6879 | else |
6880 | setVar<OpcodeSize::Narrow>(value, func); |
6881 | } |
6882 | |
6883 | template <OpcodeSize size, typename Functor> |
6884 | void setVar(unsigned value, Functor func) |
6885 | { |
6886 | if (!Fits<unsigned, size>::check(value)) |
6887 | value = func(); |
6888 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
6889 | *stream = Fits<unsigned, size>::convert(value); |
6890 | } |
6891 | |
6892 | template<typename Functor> |
6893 | void setResolveType(ResolveType value, Functor func) |
6894 | { |
6895 | if (isWide()) |
6896 | setResolveType<OpcodeSize::Wide>(value, func); |
6897 | else |
6898 | setResolveType<OpcodeSize::Narrow>(value, func); |
6899 | } |
6900 | |
6901 | template <OpcodeSize size, typename Functor> |
6902 | void setResolveType(ResolveType value, Functor func) |
6903 | { |
6904 | if (!Fits<ResolveType, size>::check(value)) |
6905 | value = func(); |
6906 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
6907 | *stream = Fits<ResolveType, size>::convert(value); |
6908 | } |
6909 | |
6910 | template<typename Functor> |
6911 | void setLocalScopeDepth(unsigned value, Functor func) |
6912 | { |
6913 | if (isWide()) |
6914 | setLocalScopeDepth<OpcodeSize::Wide>(value, func); |
6915 | else |
6916 | setLocalScopeDepth<OpcodeSize::Narrow>(value, func); |
6917 | } |
6918 | |
6919 | template <OpcodeSize size, typename Functor> |
6920 | void setLocalScopeDepth(unsigned value, Functor func) |
6921 | { |
6922 | if (!Fits<unsigned, size>::check(value)) |
6923 | value = func(); |
6924 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value); |
6925 | *stream = Fits<unsigned, size>::convert(value); |
6926 | } |
6927 | |
6928 | struct Metadata { |
6929 | WTF_MAKE_NONCOPYABLE(Metadata); |
6930 | |
6931 | public: |
6932 | Metadata(const OpResolveScope&) { } |
6933 | |
6934 | ResolveType m_resolveType; |
6935 | union { |
6936 | unsigned m_localScopeDepth; |
6937 | unsigned m_globalLexicalBindingEpoch; |
6938 | }; |
6939 | union { |
6940 | WriteBarrierBase<JSCell> m_lexicalEnvironment; |
6941 | WriteBarrierBase<SymbolTable> m_symbolTable; |
6942 | WriteBarrierBase<JSScope> m_constantScope; |
6943 | JSGlobalLexicalEnvironment* m_globalLexicalEnvironment; |
6944 | JSGlobalObject* m_globalObject; |
6945 | }; |
6946 | }; |
6947 | |
6948 | Metadata& metadata(CodeBlock* codeBlock) const |
6949 | { |
6950 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
6951 | } |
6952 | |
6953 | Metadata& metadata(ExecState* exec) const |
6954 | { |
6955 | return metadata(exec->codeBlock()); |
6956 | } |
6957 | |
6958 | VirtualRegister m_dst; |
6959 | VirtualRegister m_scope; |
6960 | unsigned m_var; |
6961 | ResolveType m_resolveType; |
6962 | unsigned m_localScopeDepth; |
6963 | unsigned m_metadataID; |
6964 | }; |
6965 | |
6966 | struct OpGetFromScope : public Instruction { |
6967 | static constexpr OpcodeID opcodeID = op_get_from_scope; |
6968 | |
6969 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset) |
6970 | { |
6971 | |
6972 | auto __metadataID = gen->addMetadataFor(opcodeID); |
6973 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID) |
6974 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID); |
6975 | } |
6976 | |
6977 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
6978 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset) |
6979 | { |
6980 | auto __metadataID = gen->addMetadataFor(opcodeID); |
6981 | return emit<size, shouldAssert>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID); |
6982 | } |
6983 | |
6984 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
6985 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset, unsigned __metadataID) |
6986 | { |
6987 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID); |
6988 | if (shouldAssert == Assert) |
6989 | ASSERT(didEmit); |
6990 | return didEmit; |
6991 | } |
6992 | |
6993 | private: |
6994 | template<OpcodeSize size, bool recordOpcode> |
6995 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset, unsigned __metadataID) |
6996 | { |
6997 | if (size == OpcodeSize::Wide) |
6998 | gen->alignWideOpcode(); |
6999 | if (Fits<unsigned, size>::check(opcodeID) |
7000 | && Fits<VirtualRegister, size>::check(dst) |
7001 | && Fits<VirtualRegister, size>::check(scope) |
7002 | && Fits<unsigned, size>::check(var) |
7003 | && Fits<GetPutInfo, size>::check(getPutInfo) |
7004 | && Fits<unsigned, size>::check(localScopeDepth) |
7005 | && Fits<unsigned, size>::check(offset) |
7006 | && Fits<unsigned, size>::check(__metadataID) |
7007 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
7008 | if (recordOpcode) |
7009 | gen->recordOpcode(opcodeID); |
7010 | if (size == OpcodeSize::Wide) |
7011 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
7012 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
7013 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
7014 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
7015 | gen->write(Fits<unsigned, size>::convert(var)); |
7016 | gen->write(Fits<GetPutInfo, size>::convert(getPutInfo)); |
7017 | gen->write(Fits<unsigned, size>::convert(localScopeDepth)); |
7018 | gen->write(Fits<unsigned, size>::convert(offset)); |
7019 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
7020 | return true; |
7021 | } |
7022 | return false; |
7023 | } |
7024 | |
7025 | public: |
7026 | template<typename Block> |
7027 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
7028 | { |
7029 | dumper->printLocationAndOp(__location, &"*get_from_scope" [!__isWide]); |
7030 | dumper->dumpOperand(m_dst, true); |
7031 | dumper->dumpOperand(m_scope, false); |
7032 | dumper->dumpOperand(m_var, false); |
7033 | dumper->dumpOperand(m_getPutInfo, false); |
7034 | dumper->dumpOperand(m_localScopeDepth, false); |
7035 | dumper->dumpOperand(m_offset, false); |
7036 | } |
7037 | |
7038 | OpGetFromScope(const uint8_t* stream) |
7039 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
7040 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
7041 | , m_var(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
7042 | , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Narrow>::convert(stream[4])) |
7043 | , m_localScopeDepth(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5])) |
7044 | , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6])) |
7045 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7])) |
7046 | { |
7047 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
7048 | } |
7049 | |
7050 | OpGetFromScope(const uint32_t* stream) |
7051 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
7052 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
7053 | , m_var(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
7054 | , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide>::convert(stream[4])) |
7055 | , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide>::convert(stream[5])) |
7056 | , m_offset(Fits<unsigned, OpcodeSize::Wide>::convert(stream[6])) |
7057 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[7])) |
7058 | { |
7059 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
7060 | } |
7061 | |
7062 | static OpGetFromScope decode(const uint8_t* stream) |
7063 | { |
7064 | if (*stream != op_wide) |
7065 | return { stream }; |
7066 | |
7067 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
7068 | return { wideStream }; |
7069 | } |
7070 | |
7071 | template<typename Functor> |
7072 | void setDst(VirtualRegister value, Functor func) |
7073 | { |
7074 | if (isWide()) |
7075 | setDst<OpcodeSize::Wide>(value, func); |
7076 | else |
7077 | setDst<OpcodeSize::Narrow>(value, func); |
7078 | } |
7079 | |
7080 | template <OpcodeSize size, typename Functor> |
7081 | void setDst(VirtualRegister value, Functor func) |
7082 | { |
7083 | if (!Fits<VirtualRegister, size>::check(value)) |
7084 | value = func(); |
7085 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
7086 | *stream = Fits<VirtualRegister, size>::convert(value); |
7087 | } |
7088 | |
7089 | template<typename Functor> |
7090 | void setScope(VirtualRegister value, Functor func) |
7091 | { |
7092 | if (isWide()) |
7093 | setScope<OpcodeSize::Wide>(value, func); |
7094 | else |
7095 | setScope<OpcodeSize::Narrow>(value, func); |
7096 | } |
7097 | |
7098 | template <OpcodeSize size, typename Functor> |
7099 | void setScope(VirtualRegister value, Functor func) |
7100 | { |
7101 | if (!Fits<VirtualRegister, size>::check(value)) |
7102 | value = func(); |
7103 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
7104 | *stream = Fits<VirtualRegister, size>::convert(value); |
7105 | } |
7106 | |
7107 | template<typename Functor> |
7108 | void setVar(unsigned value, Functor func) |
7109 | { |
7110 | if (isWide()) |
7111 | setVar<OpcodeSize::Wide>(value, func); |
7112 | else |
7113 | setVar<OpcodeSize::Narrow>(value, func); |
7114 | } |
7115 | |
7116 | template <OpcodeSize size, typename Functor> |
7117 | void setVar(unsigned value, Functor func) |
7118 | { |
7119 | if (!Fits<unsigned, size>::check(value)) |
7120 | value = func(); |
7121 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
7122 | *stream = Fits<unsigned, size>::convert(value); |
7123 | } |
7124 | |
7125 | template<typename Functor> |
7126 | void setGetPutInfo(GetPutInfo value, Functor func) |
7127 | { |
7128 | if (isWide()) |
7129 | setGetPutInfo<OpcodeSize::Wide>(value, func); |
7130 | else |
7131 | setGetPutInfo<OpcodeSize::Narrow>(value, func); |
7132 | } |
7133 | |
7134 | template <OpcodeSize size, typename Functor> |
7135 | void setGetPutInfo(GetPutInfo value, Functor func) |
7136 | { |
7137 | if (!Fits<GetPutInfo, size>::check(value)) |
7138 | value = func(); |
7139 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
7140 | *stream = Fits<GetPutInfo, size>::convert(value); |
7141 | } |
7142 | |
7143 | template<typename Functor> |
7144 | void setLocalScopeDepth(unsigned value, Functor func) |
7145 | { |
7146 | if (isWide()) |
7147 | setLocalScopeDepth<OpcodeSize::Wide>(value, func); |
7148 | else |
7149 | setLocalScopeDepth<OpcodeSize::Narrow>(value, func); |
7150 | } |
7151 | |
7152 | template <OpcodeSize size, typename Functor> |
7153 | void setLocalScopeDepth(unsigned value, Functor func) |
7154 | { |
7155 | if (!Fits<unsigned, size>::check(value)) |
7156 | value = func(); |
7157 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value); |
7158 | *stream = Fits<unsigned, size>::convert(value); |
7159 | } |
7160 | |
7161 | template<typename Functor> |
7162 | void setOffset(unsigned value, Functor func) |
7163 | { |
7164 | if (isWide()) |
7165 | setOffset<OpcodeSize::Wide>(value, func); |
7166 | else |
7167 | setOffset<OpcodeSize::Narrow>(value, func); |
7168 | } |
7169 | |
7170 | template <OpcodeSize size, typename Functor> |
7171 | void setOffset(unsigned value, Functor func) |
7172 | { |
7173 | if (!Fits<unsigned, size>::check(value)) |
7174 | value = func(); |
7175 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 6 * size + PaddingBySize<size>::value); |
7176 | *stream = Fits<unsigned, size>::convert(value); |
7177 | } |
7178 | |
7179 | struct Metadata { |
7180 | WTF_MAKE_NONCOPYABLE(Metadata); |
7181 | |
7182 | public: |
7183 | Metadata(const OpGetFromScope& __op) |
7184 | : m_getPutInfo(__op.m_getPutInfo) |
7185 | , m_operand(__op.m_offset) |
7186 | { } |
7187 | |
7188 | GetPutInfo m_getPutInfo; |
7189 | union { |
7190 | WatchpointSet* m_watchpointSet; |
7191 | WriteBarrierBase<Structure> m_structure; |
7192 | }; |
7193 | uintptr_t m_operand; |
7194 | ValueProfile m_profile; |
7195 | }; |
7196 | |
7197 | Metadata& metadata(CodeBlock* codeBlock) const |
7198 | { |
7199 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
7200 | } |
7201 | |
7202 | Metadata& metadata(ExecState* exec) const |
7203 | { |
7204 | return metadata(exec->codeBlock()); |
7205 | } |
7206 | |
7207 | VirtualRegister m_dst; |
7208 | VirtualRegister m_scope; |
7209 | unsigned m_var; |
7210 | GetPutInfo m_getPutInfo; |
7211 | unsigned m_localScopeDepth; |
7212 | unsigned m_offset; |
7213 | unsigned m_metadataID; |
7214 | }; |
7215 | |
7216 | struct OpPutToScope : public Instruction { |
7217 | static constexpr OpcodeID opcodeID = op_put_to_scope; |
7218 | |
7219 | static void emit(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset) |
7220 | { |
7221 | |
7222 | auto __metadataID = gen->addMetadataFor(opcodeID); |
7223 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID) |
7224 | || emit<OpcodeSize::Wide, Assert, true>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID); |
7225 | } |
7226 | |
7227 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
7228 | static bool emit(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset) |
7229 | { |
7230 | auto __metadataID = gen->addMetadataFor(opcodeID); |
7231 | return emit<size, shouldAssert>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID); |
7232 | } |
7233 | |
7234 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
7235 | static bool emit(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset, unsigned __metadataID) |
7236 | { |
7237 | bool didEmit = emitImpl<size, recordOpcode>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID); |
7238 | if (shouldAssert == Assert) |
7239 | ASSERT(didEmit); |
7240 | return didEmit; |
7241 | } |
7242 | |
7243 | private: |
7244 | template<OpcodeSize size, bool recordOpcode> |
7245 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset, unsigned __metadataID) |
7246 | { |
7247 | if (size == OpcodeSize::Wide) |
7248 | gen->alignWideOpcode(); |
7249 | if (Fits<unsigned, size>::check(opcodeID) |
7250 | && Fits<VirtualRegister, size>::check(scope) |
7251 | && Fits<unsigned, size>::check(var) |
7252 | && Fits<VirtualRegister, size>::check(value) |
7253 | && Fits<GetPutInfo, size>::check(getPutInfo) |
7254 | && Fits<SymbolTableOrScopeDepth, size>::check(symbolTableOrScopeDepth) |
7255 | && Fits<unsigned, size>::check(offset) |
7256 | && Fits<unsigned, size>::check(__metadataID) |
7257 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
7258 | if (recordOpcode) |
7259 | gen->recordOpcode(opcodeID); |
7260 | if (size == OpcodeSize::Wide) |
7261 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
7262 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
7263 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
7264 | gen->write(Fits<unsigned, size>::convert(var)); |
7265 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
7266 | gen->write(Fits<GetPutInfo, size>::convert(getPutInfo)); |
7267 | gen->write(Fits<SymbolTableOrScopeDepth, size>::convert(symbolTableOrScopeDepth)); |
7268 | gen->write(Fits<unsigned, size>::convert(offset)); |
7269 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
7270 | return true; |
7271 | } |
7272 | return false; |
7273 | } |
7274 | |
7275 | public: |
7276 | template<typename Block> |
7277 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
7278 | { |
7279 | dumper->printLocationAndOp(__location, &"*put_to_scope" [!__isWide]); |
7280 | dumper->dumpOperand(m_scope, true); |
7281 | dumper->dumpOperand(m_var, false); |
7282 | dumper->dumpOperand(m_value, false); |
7283 | dumper->dumpOperand(m_getPutInfo, false); |
7284 | dumper->dumpOperand(m_symbolTableOrScopeDepth, false); |
7285 | dumper->dumpOperand(m_offset, false); |
7286 | } |
7287 | |
7288 | OpPutToScope(const uint8_t* stream) |
7289 | : m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
7290 | , m_var(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2])) |
7291 | , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
7292 | , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Narrow>::convert(stream[4])) |
7293 | , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Narrow>::convert(stream[5])) |
7294 | , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6])) |
7295 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7])) |
7296 | { |
7297 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
7298 | } |
7299 | |
7300 | OpPutToScope(const uint32_t* stream) |
7301 | : m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
7302 | , m_var(Fits<unsigned, OpcodeSize::Wide>::convert(stream[2])) |
7303 | , m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
7304 | , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide>::convert(stream[4])) |
7305 | , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Wide>::convert(stream[5])) |
7306 | , m_offset(Fits<unsigned, OpcodeSize::Wide>::convert(stream[6])) |
7307 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[7])) |
7308 | { |
7309 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
7310 | } |
7311 | |
7312 | static OpPutToScope decode(const uint8_t* stream) |
7313 | { |
7314 | if (*stream != op_wide) |
7315 | return { stream }; |
7316 | |
7317 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
7318 | return { wideStream }; |
7319 | } |
7320 | |
7321 | template<typename Functor> |
7322 | void setScope(VirtualRegister value, Functor func) |
7323 | { |
7324 | if (isWide()) |
7325 | setScope<OpcodeSize::Wide>(value, func); |
7326 | else |
7327 | setScope<OpcodeSize::Narrow>(value, func); |
7328 | } |
7329 | |
7330 | template <OpcodeSize size, typename Functor> |
7331 | void setScope(VirtualRegister value, Functor func) |
7332 | { |
7333 | if (!Fits<VirtualRegister, size>::check(value)) |
7334 | value = func(); |
7335 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
7336 | *stream = Fits<VirtualRegister, size>::convert(value); |
7337 | } |
7338 | |
7339 | template<typename Functor> |
7340 | void setVar(unsigned value, Functor func) |
7341 | { |
7342 | if (isWide()) |
7343 | setVar<OpcodeSize::Wide>(value, func); |
7344 | else |
7345 | setVar<OpcodeSize::Narrow>(value, func); |
7346 | } |
7347 | |
7348 | template <OpcodeSize size, typename Functor> |
7349 | void setVar(unsigned value, Functor func) |
7350 | { |
7351 | if (!Fits<unsigned, size>::check(value)) |
7352 | value = func(); |
7353 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
7354 | *stream = Fits<unsigned, size>::convert(value); |
7355 | } |
7356 | |
7357 | template<typename Functor> |
7358 | void setValue(VirtualRegister value, Functor func) |
7359 | { |
7360 | if (isWide()) |
7361 | setValue<OpcodeSize::Wide>(value, func); |
7362 | else |
7363 | setValue<OpcodeSize::Narrow>(value, func); |
7364 | } |
7365 | |
7366 | template <OpcodeSize size, typename Functor> |
7367 | void setValue(VirtualRegister value, Functor func) |
7368 | { |
7369 | if (!Fits<VirtualRegister, size>::check(value)) |
7370 | value = func(); |
7371 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
7372 | *stream = Fits<VirtualRegister, size>::convert(value); |
7373 | } |
7374 | |
7375 | template<typename Functor> |
7376 | void setGetPutInfo(GetPutInfo value, Functor func) |
7377 | { |
7378 | if (isWide()) |
7379 | setGetPutInfo<OpcodeSize::Wide>(value, func); |
7380 | else |
7381 | setGetPutInfo<OpcodeSize::Narrow>(value, func); |
7382 | } |
7383 | |
7384 | template <OpcodeSize size, typename Functor> |
7385 | void setGetPutInfo(GetPutInfo value, Functor func) |
7386 | { |
7387 | if (!Fits<GetPutInfo, size>::check(value)) |
7388 | value = func(); |
7389 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
7390 | *stream = Fits<GetPutInfo, size>::convert(value); |
7391 | } |
7392 | |
7393 | template<typename Functor> |
7394 | void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func) |
7395 | { |
7396 | if (isWide()) |
7397 | setSymbolTableOrScopeDepth<OpcodeSize::Wide>(value, func); |
7398 | else |
7399 | setSymbolTableOrScopeDepth<OpcodeSize::Narrow>(value, func); |
7400 | } |
7401 | |
7402 | template <OpcodeSize size, typename Functor> |
7403 | void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func) |
7404 | { |
7405 | if (!Fits<SymbolTableOrScopeDepth, size>::check(value)) |
7406 | value = func(); |
7407 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value); |
7408 | *stream = Fits<SymbolTableOrScopeDepth, size>::convert(value); |
7409 | } |
7410 | |
7411 | template<typename Functor> |
7412 | void setOffset(unsigned value, Functor func) |
7413 | { |
7414 | if (isWide()) |
7415 | setOffset<OpcodeSize::Wide>(value, func); |
7416 | else |
7417 | setOffset<OpcodeSize::Narrow>(value, func); |
7418 | } |
7419 | |
7420 | template <OpcodeSize size, typename Functor> |
7421 | void setOffset(unsigned value, Functor func) |
7422 | { |
7423 | if (!Fits<unsigned, size>::check(value)) |
7424 | value = func(); |
7425 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 6 * size + PaddingBySize<size>::value); |
7426 | *stream = Fits<unsigned, size>::convert(value); |
7427 | } |
7428 | |
7429 | struct Metadata { |
7430 | WTF_MAKE_NONCOPYABLE(Metadata); |
7431 | |
7432 | public: |
7433 | Metadata(const OpPutToScope& __op) |
7434 | : m_getPutInfo(__op.m_getPutInfo) |
7435 | , m_operand(__op.m_offset) |
7436 | { } |
7437 | |
7438 | GetPutInfo m_getPutInfo; |
7439 | union { |
7440 | WriteBarrierBase<Structure> m_structure; |
7441 | WatchpointSet* m_watchpointSet; |
7442 | }; |
7443 | uintptr_t m_operand; |
7444 | }; |
7445 | |
7446 | Metadata& metadata(CodeBlock* codeBlock) const |
7447 | { |
7448 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
7449 | } |
7450 | |
7451 | Metadata& metadata(ExecState* exec) const |
7452 | { |
7453 | return metadata(exec->codeBlock()); |
7454 | } |
7455 | |
7456 | VirtualRegister m_scope; |
7457 | unsigned m_var; |
7458 | VirtualRegister m_value; |
7459 | GetPutInfo m_getPutInfo; |
7460 | SymbolTableOrScopeDepth m_symbolTableOrScopeDepth; |
7461 | unsigned m_offset; |
7462 | unsigned m_metadataID; |
7463 | }; |
7464 | |
7465 | struct OpGetFromArguments : public Instruction { |
7466 | static constexpr OpcodeID opcodeID = op_get_from_arguments; |
7467 | |
7468 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index) |
7469 | { |
7470 | |
7471 | auto __metadataID = gen->addMetadataFor(opcodeID); |
7472 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, arguments, index, __metadataID) |
7473 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, arguments, index, __metadataID); |
7474 | } |
7475 | |
7476 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
7477 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index) |
7478 | { |
7479 | auto __metadataID = gen->addMetadataFor(opcodeID); |
7480 | return emit<size, shouldAssert>(gen, dst, arguments, index, __metadataID); |
7481 | } |
7482 | |
7483 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
7484 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index, unsigned __metadataID) |
7485 | { |
7486 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, arguments, index, __metadataID); |
7487 | if (shouldAssert == Assert) |
7488 | ASSERT(didEmit); |
7489 | return didEmit; |
7490 | } |
7491 | |
7492 | private: |
7493 | template<OpcodeSize size, bool recordOpcode> |
7494 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index, unsigned __metadataID) |
7495 | { |
7496 | if (size == OpcodeSize::Wide) |
7497 | gen->alignWideOpcode(); |
7498 | if (Fits<unsigned, size>::check(opcodeID) |
7499 | && Fits<VirtualRegister, size>::check(dst) |
7500 | && Fits<VirtualRegister, size>::check(arguments) |
7501 | && Fits<unsigned, size>::check(index) |
7502 | && Fits<unsigned, size>::check(__metadataID) |
7503 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
7504 | if (recordOpcode) |
7505 | gen->recordOpcode(opcodeID); |
7506 | if (size == OpcodeSize::Wide) |
7507 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
7508 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
7509 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
7510 | gen->write(Fits<VirtualRegister, size>::convert(arguments)); |
7511 | gen->write(Fits<unsigned, size>::convert(index)); |
7512 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
7513 | return true; |
7514 | } |
7515 | return false; |
7516 | } |
7517 | |
7518 | public: |
7519 | template<typename Block> |
7520 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
7521 | { |
7522 | dumper->printLocationAndOp(__location, &"*get_from_arguments" [!__isWide]); |
7523 | dumper->dumpOperand(m_dst, true); |
7524 | dumper->dumpOperand(m_arguments, false); |
7525 | dumper->dumpOperand(m_index, false); |
7526 | } |
7527 | |
7528 | OpGetFromArguments(const uint8_t* stream) |
7529 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
7530 | , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
7531 | , m_index(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
7532 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
7533 | { |
7534 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
7535 | } |
7536 | |
7537 | OpGetFromArguments(const uint32_t* stream) |
7538 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
7539 | , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
7540 | , m_index(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
7541 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
7542 | { |
7543 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
7544 | } |
7545 | |
7546 | static OpGetFromArguments decode(const uint8_t* stream) |
7547 | { |
7548 | if (*stream != op_wide) |
7549 | return { stream }; |
7550 | |
7551 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
7552 | return { wideStream }; |
7553 | } |
7554 | |
7555 | template<typename Functor> |
7556 | void setDst(VirtualRegister value, Functor func) |
7557 | { |
7558 | if (isWide()) |
7559 | setDst<OpcodeSize::Wide>(value, func); |
7560 | else |
7561 | setDst<OpcodeSize::Narrow>(value, func); |
7562 | } |
7563 | |
7564 | template <OpcodeSize size, typename Functor> |
7565 | void setDst(VirtualRegister value, Functor func) |
7566 | { |
7567 | if (!Fits<VirtualRegister, size>::check(value)) |
7568 | value = func(); |
7569 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
7570 | *stream = Fits<VirtualRegister, size>::convert(value); |
7571 | } |
7572 | |
7573 | template<typename Functor> |
7574 | void setArguments(VirtualRegister value, Functor func) |
7575 | { |
7576 | if (isWide()) |
7577 | setArguments<OpcodeSize::Wide>(value, func); |
7578 | else |
7579 | setArguments<OpcodeSize::Narrow>(value, func); |
7580 | } |
7581 | |
7582 | template <OpcodeSize size, typename Functor> |
7583 | void setArguments(VirtualRegister value, Functor func) |
7584 | { |
7585 | if (!Fits<VirtualRegister, size>::check(value)) |
7586 | value = func(); |
7587 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
7588 | *stream = Fits<VirtualRegister, size>::convert(value); |
7589 | } |
7590 | |
7591 | template<typename Functor> |
7592 | void setIndex(unsigned value, Functor func) |
7593 | { |
7594 | if (isWide()) |
7595 | setIndex<OpcodeSize::Wide>(value, func); |
7596 | else |
7597 | setIndex<OpcodeSize::Narrow>(value, func); |
7598 | } |
7599 | |
7600 | template <OpcodeSize size, typename Functor> |
7601 | void setIndex(unsigned value, Functor func) |
7602 | { |
7603 | if (!Fits<unsigned, size>::check(value)) |
7604 | value = func(); |
7605 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
7606 | *stream = Fits<unsigned, size>::convert(value); |
7607 | } |
7608 | |
7609 | struct Metadata { |
7610 | WTF_MAKE_NONCOPYABLE(Metadata); |
7611 | |
7612 | public: |
7613 | Metadata(const OpGetFromArguments&) { } |
7614 | |
7615 | ValueProfile m_profile; |
7616 | }; |
7617 | |
7618 | Metadata& metadata(CodeBlock* codeBlock) const |
7619 | { |
7620 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
7621 | } |
7622 | |
7623 | Metadata& metadata(ExecState* exec) const |
7624 | { |
7625 | return metadata(exec->codeBlock()); |
7626 | } |
7627 | |
7628 | VirtualRegister m_dst; |
7629 | VirtualRegister m_arguments; |
7630 | unsigned m_index; |
7631 | unsigned m_metadataID; |
7632 | }; |
7633 | |
7634 | struct OpCatch : public Instruction { |
7635 | static constexpr OpcodeID opcodeID = op_catch; |
7636 | |
7637 | static void emit(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue) |
7638 | { |
7639 | |
7640 | auto __metadataID = gen->addMetadataFor(opcodeID); |
7641 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, exception, thrownValue, __metadataID) |
7642 | || emit<OpcodeSize::Wide, Assert, true>(gen, exception, thrownValue, __metadataID); |
7643 | } |
7644 | |
7645 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
7646 | static bool emit(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue) |
7647 | { |
7648 | auto __metadataID = gen->addMetadataFor(opcodeID); |
7649 | return emit<size, shouldAssert>(gen, exception, thrownValue, __metadataID); |
7650 | } |
7651 | |
7652 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
7653 | static bool emit(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue, unsigned __metadataID) |
7654 | { |
7655 | bool didEmit = emitImpl<size, recordOpcode>(gen, exception, thrownValue, __metadataID); |
7656 | if (shouldAssert == Assert) |
7657 | ASSERT(didEmit); |
7658 | return didEmit; |
7659 | } |
7660 | |
7661 | private: |
7662 | template<OpcodeSize size, bool recordOpcode> |
7663 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue, unsigned __metadataID) |
7664 | { |
7665 | if (size == OpcodeSize::Wide) |
7666 | gen->alignWideOpcode(); |
7667 | if (Fits<unsigned, size>::check(opcodeID) |
7668 | && Fits<VirtualRegister, size>::check(exception) |
7669 | && Fits<VirtualRegister, size>::check(thrownValue) |
7670 | && Fits<unsigned, size>::check(__metadataID) |
7671 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
7672 | if (recordOpcode) |
7673 | gen->recordOpcode(opcodeID); |
7674 | if (size == OpcodeSize::Wide) |
7675 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
7676 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
7677 | gen->write(Fits<VirtualRegister, size>::convert(exception)); |
7678 | gen->write(Fits<VirtualRegister, size>::convert(thrownValue)); |
7679 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
7680 | return true; |
7681 | } |
7682 | return false; |
7683 | } |
7684 | |
7685 | public: |
7686 | template<typename Block> |
7687 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
7688 | { |
7689 | dumper->printLocationAndOp(__location, &"*catch" [!__isWide]); |
7690 | dumper->dumpOperand(m_exception, true); |
7691 | dumper->dumpOperand(m_thrownValue, false); |
7692 | } |
7693 | |
7694 | OpCatch(const uint8_t* stream) |
7695 | : m_exception(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
7696 | , m_thrownValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
7697 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
7698 | { |
7699 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
7700 | } |
7701 | |
7702 | OpCatch(const uint32_t* stream) |
7703 | : m_exception(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
7704 | , m_thrownValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
7705 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
7706 | { |
7707 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
7708 | } |
7709 | |
7710 | static OpCatch decode(const uint8_t* stream) |
7711 | { |
7712 | if (*stream != op_wide) |
7713 | return { stream }; |
7714 | |
7715 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
7716 | return { wideStream }; |
7717 | } |
7718 | |
7719 | template<typename Functor> |
7720 | void setException(VirtualRegister value, Functor func) |
7721 | { |
7722 | if (isWide()) |
7723 | setException<OpcodeSize::Wide>(value, func); |
7724 | else |
7725 | setException<OpcodeSize::Narrow>(value, func); |
7726 | } |
7727 | |
7728 | template <OpcodeSize size, typename Functor> |
7729 | void setException(VirtualRegister value, Functor func) |
7730 | { |
7731 | if (!Fits<VirtualRegister, size>::check(value)) |
7732 | value = func(); |
7733 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
7734 | *stream = Fits<VirtualRegister, size>::convert(value); |
7735 | } |
7736 | |
7737 | template<typename Functor> |
7738 | void setThrownValue(VirtualRegister value, Functor func) |
7739 | { |
7740 | if (isWide()) |
7741 | setThrownValue<OpcodeSize::Wide>(value, func); |
7742 | else |
7743 | setThrownValue<OpcodeSize::Narrow>(value, func); |
7744 | } |
7745 | |
7746 | template <OpcodeSize size, typename Functor> |
7747 | void setThrownValue(VirtualRegister value, Functor func) |
7748 | { |
7749 | if (!Fits<VirtualRegister, size>::check(value)) |
7750 | value = func(); |
7751 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
7752 | *stream = Fits<VirtualRegister, size>::convert(value); |
7753 | } |
7754 | |
7755 | struct Metadata { |
7756 | WTF_MAKE_NONCOPYABLE(Metadata); |
7757 | |
7758 | public: |
7759 | Metadata(const OpCatch&) { } |
7760 | |
7761 | ValueProfileAndOperandBuffer* m_buffer; |
7762 | }; |
7763 | |
7764 | Metadata& metadata(CodeBlock* codeBlock) const |
7765 | { |
7766 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
7767 | } |
7768 | |
7769 | Metadata& metadata(ExecState* exec) const |
7770 | { |
7771 | return metadata(exec->codeBlock()); |
7772 | } |
7773 | |
7774 | VirtualRegister m_exception; |
7775 | VirtualRegister m_thrownValue; |
7776 | unsigned m_metadataID; |
7777 | }; |
7778 | |
7779 | struct OpProfileType : public Instruction { |
7780 | static constexpr OpcodeID opcodeID = op_profile_type; |
7781 | |
7782 | static void emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType) |
7783 | { |
7784 | |
7785 | auto __metadataID = gen->addMetadataFor(opcodeID); |
7786 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID) |
7787 | || emit<OpcodeSize::Wide, Assert, true>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID); |
7788 | } |
7789 | |
7790 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
7791 | static bool emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType) |
7792 | { |
7793 | auto __metadataID = gen->addMetadataFor(opcodeID); |
7794 | return emit<size, shouldAssert>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID); |
7795 | } |
7796 | |
7797 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
7798 | static bool emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType, unsigned __metadataID) |
7799 | { |
7800 | bool didEmit = emitImpl<size, recordOpcode>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID); |
7801 | if (shouldAssert == Assert) |
7802 | ASSERT(didEmit); |
7803 | return didEmit; |
7804 | } |
7805 | |
7806 | private: |
7807 | template<OpcodeSize size, bool recordOpcode> |
7808 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType, unsigned __metadataID) |
7809 | { |
7810 | if (size == OpcodeSize::Wide) |
7811 | gen->alignWideOpcode(); |
7812 | if (Fits<unsigned, size>::check(opcodeID) |
7813 | && Fits<VirtualRegister, size>::check(targetVirtualRegister) |
7814 | && Fits<SymbolTableOrScopeDepth, size>::check(symbolTableOrScopeDepth) |
7815 | && Fits<ProfileTypeBytecodeFlag, size>::check(flag) |
7816 | && Fits<unsigned, size>::check(identifier) |
7817 | && Fits<ResolveType, size>::check(resolveType) |
7818 | && Fits<unsigned, size>::check(__metadataID) |
7819 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
7820 | if (recordOpcode) |
7821 | gen->recordOpcode(opcodeID); |
7822 | if (size == OpcodeSize::Wide) |
7823 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
7824 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
7825 | gen->write(Fits<VirtualRegister, size>::convert(targetVirtualRegister)); |
7826 | gen->write(Fits<SymbolTableOrScopeDepth, size>::convert(symbolTableOrScopeDepth)); |
7827 | gen->write(Fits<ProfileTypeBytecodeFlag, size>::convert(flag)); |
7828 | gen->write(Fits<unsigned, size>::convert(identifier)); |
7829 | gen->write(Fits<ResolveType, size>::convert(resolveType)); |
7830 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
7831 | return true; |
7832 | } |
7833 | return false; |
7834 | } |
7835 | |
7836 | public: |
7837 | template<typename Block> |
7838 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
7839 | { |
7840 | dumper->printLocationAndOp(__location, &"*profile_type" [!__isWide]); |
7841 | dumper->dumpOperand(m_targetVirtualRegister, true); |
7842 | dumper->dumpOperand(m_symbolTableOrScopeDepth, false); |
7843 | dumper->dumpOperand(m_flag, false); |
7844 | dumper->dumpOperand(m_identifier, false); |
7845 | dumper->dumpOperand(m_resolveType, false); |
7846 | } |
7847 | |
7848 | OpProfileType(const uint8_t* stream) |
7849 | : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
7850 | , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Narrow>::convert(stream[2])) |
7851 | , m_flag(Fits<ProfileTypeBytecodeFlag, OpcodeSize::Narrow>::convert(stream[3])) |
7852 | , m_identifier(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
7853 | , m_resolveType(Fits<ResolveType, OpcodeSize::Narrow>::convert(stream[5])) |
7854 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6])) |
7855 | { |
7856 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
7857 | } |
7858 | |
7859 | OpProfileType(const uint32_t* stream) |
7860 | : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
7861 | , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Wide>::convert(stream[2])) |
7862 | , m_flag(Fits<ProfileTypeBytecodeFlag, OpcodeSize::Wide>::convert(stream[3])) |
7863 | , m_identifier(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
7864 | , m_resolveType(Fits<ResolveType, OpcodeSize::Wide>::convert(stream[5])) |
7865 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[6])) |
7866 | { |
7867 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
7868 | } |
7869 | |
7870 | static OpProfileType decode(const uint8_t* stream) |
7871 | { |
7872 | if (*stream != op_wide) |
7873 | return { stream }; |
7874 | |
7875 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
7876 | return { wideStream }; |
7877 | } |
7878 | |
7879 | template<typename Functor> |
7880 | void setTargetVirtualRegister(VirtualRegister value, Functor func) |
7881 | { |
7882 | if (isWide()) |
7883 | setTargetVirtualRegister<OpcodeSize::Wide>(value, func); |
7884 | else |
7885 | setTargetVirtualRegister<OpcodeSize::Narrow>(value, func); |
7886 | } |
7887 | |
7888 | template <OpcodeSize size, typename Functor> |
7889 | void setTargetVirtualRegister(VirtualRegister value, Functor func) |
7890 | { |
7891 | if (!Fits<VirtualRegister, size>::check(value)) |
7892 | value = func(); |
7893 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
7894 | *stream = Fits<VirtualRegister, size>::convert(value); |
7895 | } |
7896 | |
7897 | template<typename Functor> |
7898 | void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func) |
7899 | { |
7900 | if (isWide()) |
7901 | setSymbolTableOrScopeDepth<OpcodeSize::Wide>(value, func); |
7902 | else |
7903 | setSymbolTableOrScopeDepth<OpcodeSize::Narrow>(value, func); |
7904 | } |
7905 | |
7906 | template <OpcodeSize size, typename Functor> |
7907 | void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func) |
7908 | { |
7909 | if (!Fits<SymbolTableOrScopeDepth, size>::check(value)) |
7910 | value = func(); |
7911 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
7912 | *stream = Fits<SymbolTableOrScopeDepth, size>::convert(value); |
7913 | } |
7914 | |
7915 | template<typename Functor> |
7916 | void setFlag(ProfileTypeBytecodeFlag value, Functor func) |
7917 | { |
7918 | if (isWide()) |
7919 | setFlag<OpcodeSize::Wide>(value, func); |
7920 | else |
7921 | setFlag<OpcodeSize::Narrow>(value, func); |
7922 | } |
7923 | |
7924 | template <OpcodeSize size, typename Functor> |
7925 | void setFlag(ProfileTypeBytecodeFlag value, Functor func) |
7926 | { |
7927 | if (!Fits<ProfileTypeBytecodeFlag, size>::check(value)) |
7928 | value = func(); |
7929 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
7930 | *stream = Fits<ProfileTypeBytecodeFlag, size>::convert(value); |
7931 | } |
7932 | |
7933 | template<typename Functor> |
7934 | void setIdentifier(unsigned value, Functor func) |
7935 | { |
7936 | if (isWide()) |
7937 | setIdentifier<OpcodeSize::Wide>(value, func); |
7938 | else |
7939 | setIdentifier<OpcodeSize::Narrow>(value, func); |
7940 | } |
7941 | |
7942 | template <OpcodeSize size, typename Functor> |
7943 | void setIdentifier(unsigned value, Functor func) |
7944 | { |
7945 | if (!Fits<unsigned, size>::check(value)) |
7946 | value = func(); |
7947 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
7948 | *stream = Fits<unsigned, size>::convert(value); |
7949 | } |
7950 | |
7951 | template<typename Functor> |
7952 | void setResolveType(ResolveType value, Functor func) |
7953 | { |
7954 | if (isWide()) |
7955 | setResolveType<OpcodeSize::Wide>(value, func); |
7956 | else |
7957 | setResolveType<OpcodeSize::Narrow>(value, func); |
7958 | } |
7959 | |
7960 | template <OpcodeSize size, typename Functor> |
7961 | void setResolveType(ResolveType value, Functor func) |
7962 | { |
7963 | if (!Fits<ResolveType, size>::check(value)) |
7964 | value = func(); |
7965 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value); |
7966 | *stream = Fits<ResolveType, size>::convert(value); |
7967 | } |
7968 | |
7969 | struct Metadata { |
7970 | WTF_MAKE_NONCOPYABLE(Metadata); |
7971 | |
7972 | public: |
7973 | Metadata(const OpProfileType&) { } |
7974 | |
7975 | TypeLocation* m_typeLocation; |
7976 | }; |
7977 | |
7978 | Metadata& metadata(CodeBlock* codeBlock) const |
7979 | { |
7980 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
7981 | } |
7982 | |
7983 | Metadata& metadata(ExecState* exec) const |
7984 | { |
7985 | return metadata(exec->codeBlock()); |
7986 | } |
7987 | |
7988 | VirtualRegister m_targetVirtualRegister; |
7989 | SymbolTableOrScopeDepth m_symbolTableOrScopeDepth; |
7990 | ProfileTypeBytecodeFlag m_flag; |
7991 | unsigned m_identifier; |
7992 | ResolveType m_resolveType; |
7993 | unsigned m_metadataID; |
7994 | }; |
7995 | |
7996 | struct OpProfileControlFlow : public Instruction { |
7997 | static constexpr OpcodeID opcodeID = op_profile_control_flow; |
7998 | |
7999 | static void emit(BytecodeGenerator* gen, int textOffset) |
8000 | { |
8001 | |
8002 | auto __metadataID = gen->addMetadataFor(opcodeID); |
8003 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, textOffset, __metadataID) |
8004 | || emit<OpcodeSize::Wide, Assert, true>(gen, textOffset, __metadataID); |
8005 | } |
8006 | |
8007 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
8008 | static bool emit(BytecodeGenerator* gen, int textOffset) |
8009 | { |
8010 | auto __metadataID = gen->addMetadataFor(opcodeID); |
8011 | return emit<size, shouldAssert>(gen, textOffset, __metadataID); |
8012 | } |
8013 | |
8014 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
8015 | static bool emit(BytecodeGenerator* gen, int textOffset, unsigned __metadataID) |
8016 | { |
8017 | bool didEmit = emitImpl<size, recordOpcode>(gen, textOffset, __metadataID); |
8018 | if (shouldAssert == Assert) |
8019 | ASSERT(didEmit); |
8020 | return didEmit; |
8021 | } |
8022 | |
8023 | private: |
8024 | template<OpcodeSize size, bool recordOpcode> |
8025 | static bool emitImpl(BytecodeGenerator* gen, int textOffset, unsigned __metadataID) |
8026 | { |
8027 | if (size == OpcodeSize::Wide) |
8028 | gen->alignWideOpcode(); |
8029 | if (Fits<unsigned, size>::check(opcodeID) |
8030 | && Fits<int, size>::check(textOffset) |
8031 | && Fits<unsigned, size>::check(__metadataID) |
8032 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
8033 | if (recordOpcode) |
8034 | gen->recordOpcode(opcodeID); |
8035 | if (size == OpcodeSize::Wide) |
8036 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
8037 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
8038 | gen->write(Fits<int, size>::convert(textOffset)); |
8039 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
8040 | return true; |
8041 | } |
8042 | return false; |
8043 | } |
8044 | |
8045 | public: |
8046 | template<typename Block> |
8047 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
8048 | { |
8049 | dumper->printLocationAndOp(__location, &"*profile_control_flow" [!__isWide]); |
8050 | dumper->dumpOperand(m_textOffset, true); |
8051 | } |
8052 | |
8053 | OpProfileControlFlow(const uint8_t* stream) |
8054 | : m_textOffset(Fits<int, OpcodeSize::Narrow>::convert(stream[1])) |
8055 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2])) |
8056 | { |
8057 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8058 | } |
8059 | |
8060 | OpProfileControlFlow(const uint32_t* stream) |
8061 | : m_textOffset(Fits<int, OpcodeSize::Wide>::convert(stream[1])) |
8062 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[2])) |
8063 | { |
8064 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8065 | } |
8066 | |
8067 | static OpProfileControlFlow decode(const uint8_t* stream) |
8068 | { |
8069 | if (*stream != op_wide) |
8070 | return { stream }; |
8071 | |
8072 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
8073 | return { wideStream }; |
8074 | } |
8075 | |
8076 | template<typename Functor> |
8077 | void setTextOffset(int value, Functor func) |
8078 | { |
8079 | if (isWide()) |
8080 | setTextOffset<OpcodeSize::Wide>(value, func); |
8081 | else |
8082 | setTextOffset<OpcodeSize::Narrow>(value, func); |
8083 | } |
8084 | |
8085 | template <OpcodeSize size, typename Functor> |
8086 | void setTextOffset(int value, Functor func) |
8087 | { |
8088 | if (!Fits<int, size>::check(value)) |
8089 | value = func(); |
8090 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
8091 | *stream = Fits<int, size>::convert(value); |
8092 | } |
8093 | |
8094 | struct Metadata { |
8095 | WTF_MAKE_NONCOPYABLE(Metadata); |
8096 | |
8097 | public: |
8098 | Metadata(const OpProfileControlFlow&) { } |
8099 | |
8100 | BasicBlockLocation* m_basicBlockLocation; |
8101 | }; |
8102 | |
8103 | Metadata& metadata(CodeBlock* codeBlock) const |
8104 | { |
8105 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
8106 | } |
8107 | |
8108 | Metadata& metadata(ExecState* exec) const |
8109 | { |
8110 | return metadata(exec->codeBlock()); |
8111 | } |
8112 | |
8113 | int m_textOffset; |
8114 | unsigned m_metadataID; |
8115 | }; |
8116 | |
8117 | struct OpHasIndexedProperty : public Instruction { |
8118 | static constexpr OpcodeID opcodeID = op_has_indexed_property; |
8119 | |
8120 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property) |
8121 | { |
8122 | |
8123 | auto __metadataID = gen->addMetadataFor(opcodeID); |
8124 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, __metadataID) |
8125 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, property, __metadataID); |
8126 | } |
8127 | |
8128 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
8129 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property) |
8130 | { |
8131 | auto __metadataID = gen->addMetadataFor(opcodeID); |
8132 | return emit<size, shouldAssert>(gen, dst, base, property, __metadataID); |
8133 | } |
8134 | |
8135 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
8136 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID) |
8137 | { |
8138 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, __metadataID); |
8139 | if (shouldAssert == Assert) |
8140 | ASSERT(didEmit); |
8141 | return didEmit; |
8142 | } |
8143 | |
8144 | private: |
8145 | template<OpcodeSize size, bool recordOpcode> |
8146 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID) |
8147 | { |
8148 | if (size == OpcodeSize::Wide) |
8149 | gen->alignWideOpcode(); |
8150 | if (Fits<unsigned, size>::check(opcodeID) |
8151 | && Fits<VirtualRegister, size>::check(dst) |
8152 | && Fits<VirtualRegister, size>::check(base) |
8153 | && Fits<VirtualRegister, size>::check(property) |
8154 | && Fits<unsigned, size>::check(__metadataID) |
8155 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
8156 | if (recordOpcode) |
8157 | gen->recordOpcode(opcodeID); |
8158 | if (size == OpcodeSize::Wide) |
8159 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
8160 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
8161 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
8162 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
8163 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
8164 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
8165 | return true; |
8166 | } |
8167 | return false; |
8168 | } |
8169 | |
8170 | public: |
8171 | template<typename Block> |
8172 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
8173 | { |
8174 | dumper->printLocationAndOp(__location, &"*has_indexed_property" [!__isWide]); |
8175 | dumper->dumpOperand(m_dst, true); |
8176 | dumper->dumpOperand(m_base, false); |
8177 | dumper->dumpOperand(m_property, false); |
8178 | } |
8179 | |
8180 | OpHasIndexedProperty(const uint8_t* stream) |
8181 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
8182 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
8183 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
8184 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
8185 | { |
8186 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8187 | } |
8188 | |
8189 | OpHasIndexedProperty(const uint32_t* stream) |
8190 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
8191 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
8192 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
8193 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
8194 | { |
8195 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8196 | } |
8197 | |
8198 | static OpHasIndexedProperty decode(const uint8_t* stream) |
8199 | { |
8200 | if (*stream != op_wide) |
8201 | return { stream }; |
8202 | |
8203 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
8204 | return { wideStream }; |
8205 | } |
8206 | |
8207 | template<typename Functor> |
8208 | void setDst(VirtualRegister value, Functor func) |
8209 | { |
8210 | if (isWide()) |
8211 | setDst<OpcodeSize::Wide>(value, func); |
8212 | else |
8213 | setDst<OpcodeSize::Narrow>(value, func); |
8214 | } |
8215 | |
8216 | template <OpcodeSize size, typename Functor> |
8217 | void setDst(VirtualRegister value, Functor func) |
8218 | { |
8219 | if (!Fits<VirtualRegister, size>::check(value)) |
8220 | value = func(); |
8221 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
8222 | *stream = Fits<VirtualRegister, size>::convert(value); |
8223 | } |
8224 | |
8225 | template<typename Functor> |
8226 | void setBase(VirtualRegister value, Functor func) |
8227 | { |
8228 | if (isWide()) |
8229 | setBase<OpcodeSize::Wide>(value, func); |
8230 | else |
8231 | setBase<OpcodeSize::Narrow>(value, func); |
8232 | } |
8233 | |
8234 | template <OpcodeSize size, typename Functor> |
8235 | void setBase(VirtualRegister value, Functor func) |
8236 | { |
8237 | if (!Fits<VirtualRegister, size>::check(value)) |
8238 | value = func(); |
8239 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
8240 | *stream = Fits<VirtualRegister, size>::convert(value); |
8241 | } |
8242 | |
8243 | template<typename Functor> |
8244 | void setProperty(VirtualRegister value, Functor func) |
8245 | { |
8246 | if (isWide()) |
8247 | setProperty<OpcodeSize::Wide>(value, func); |
8248 | else |
8249 | setProperty<OpcodeSize::Narrow>(value, func); |
8250 | } |
8251 | |
8252 | template <OpcodeSize size, typename Functor> |
8253 | void setProperty(VirtualRegister value, Functor func) |
8254 | { |
8255 | if (!Fits<VirtualRegister, size>::check(value)) |
8256 | value = func(); |
8257 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
8258 | *stream = Fits<VirtualRegister, size>::convert(value); |
8259 | } |
8260 | |
8261 | struct Metadata { |
8262 | WTF_MAKE_NONCOPYABLE(Metadata); |
8263 | |
8264 | public: |
8265 | Metadata(const OpHasIndexedProperty&) { } |
8266 | |
8267 | ArrayProfile m_arrayProfile; |
8268 | }; |
8269 | |
8270 | Metadata& metadata(CodeBlock* codeBlock) const |
8271 | { |
8272 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
8273 | } |
8274 | |
8275 | Metadata& metadata(ExecState* exec) const |
8276 | { |
8277 | return metadata(exec->codeBlock()); |
8278 | } |
8279 | |
8280 | VirtualRegister m_dst; |
8281 | VirtualRegister m_base; |
8282 | VirtualRegister m_property; |
8283 | unsigned m_metadataID; |
8284 | }; |
8285 | |
8286 | struct OpGetDirectPname : public Instruction { |
8287 | static constexpr OpcodeID opcodeID = op_get_direct_pname; |
8288 | |
8289 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator) |
8290 | { |
8291 | |
8292 | auto __metadataID = gen->addMetadataFor(opcodeID); |
8293 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, index, enumerator, __metadataID) |
8294 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, property, index, enumerator, __metadataID); |
8295 | } |
8296 | |
8297 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert> |
8298 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator) |
8299 | { |
8300 | auto __metadataID = gen->addMetadataFor(opcodeID); |
8301 | return emit<size, shouldAssert>(gen, dst, base, property, index, enumerator, __metadataID); |
8302 | } |
8303 | |
8304 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
8305 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator, unsigned __metadataID) |
8306 | { |
8307 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, index, enumerator, __metadataID); |
8308 | if (shouldAssert == Assert) |
8309 | ASSERT(didEmit); |
8310 | return didEmit; |
8311 | } |
8312 | |
8313 | private: |
8314 | template<OpcodeSize size, bool recordOpcode> |
8315 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator, unsigned __metadataID) |
8316 | { |
8317 | if (size == OpcodeSize::Wide) |
8318 | gen->alignWideOpcode(); |
8319 | if (Fits<unsigned, size>::check(opcodeID) |
8320 | && Fits<VirtualRegister, size>::check(dst) |
8321 | && Fits<VirtualRegister, size>::check(base) |
8322 | && Fits<VirtualRegister, size>::check(property) |
8323 | && Fits<VirtualRegister, size>::check(index) |
8324 | && Fits<VirtualRegister, size>::check(enumerator) |
8325 | && Fits<unsigned, size>::check(__metadataID) |
8326 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
8327 | if (recordOpcode) |
8328 | gen->recordOpcode(opcodeID); |
8329 | if (size == OpcodeSize::Wide) |
8330 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
8331 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
8332 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
8333 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
8334 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
8335 | gen->write(Fits<VirtualRegister, size>::convert(index)); |
8336 | gen->write(Fits<VirtualRegister, size>::convert(enumerator)); |
8337 | gen->write(Fits<unsigned, size>::convert(__metadataID)); |
8338 | return true; |
8339 | } |
8340 | return false; |
8341 | } |
8342 | |
8343 | public: |
8344 | template<typename Block> |
8345 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
8346 | { |
8347 | dumper->printLocationAndOp(__location, &"*get_direct_pname" [!__isWide]); |
8348 | dumper->dumpOperand(m_dst, true); |
8349 | dumper->dumpOperand(m_base, false); |
8350 | dumper->dumpOperand(m_property, false); |
8351 | dumper->dumpOperand(m_index, false); |
8352 | dumper->dumpOperand(m_enumerator, false); |
8353 | } |
8354 | |
8355 | OpGetDirectPname(const uint8_t* stream) |
8356 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
8357 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
8358 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
8359 | , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
8360 | , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5])) |
8361 | , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6])) |
8362 | { |
8363 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8364 | } |
8365 | |
8366 | OpGetDirectPname(const uint32_t* stream) |
8367 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
8368 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
8369 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
8370 | , m_index(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
8371 | , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[5])) |
8372 | , m_metadataID(Fits<unsigned, OpcodeSize::Wide>::convert(stream[6])) |
8373 | { |
8374 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8375 | } |
8376 | |
8377 | static OpGetDirectPname decode(const uint8_t* stream) |
8378 | { |
8379 | if (*stream != op_wide) |
8380 | return { stream }; |
8381 | |
8382 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
8383 | return { wideStream }; |
8384 | } |
8385 | |
8386 | template<typename Functor> |
8387 | void setDst(VirtualRegister value, Functor func) |
8388 | { |
8389 | if (isWide()) |
8390 | setDst<OpcodeSize::Wide>(value, func); |
8391 | else |
8392 | setDst<OpcodeSize::Narrow>(value, func); |
8393 | } |
8394 | |
8395 | template <OpcodeSize size, typename Functor> |
8396 | void setDst(VirtualRegister value, Functor func) |
8397 | { |
8398 | if (!Fits<VirtualRegister, size>::check(value)) |
8399 | value = func(); |
8400 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
8401 | *stream = Fits<VirtualRegister, size>::convert(value); |
8402 | } |
8403 | |
8404 | template<typename Functor> |
8405 | void setBase(VirtualRegister value, Functor func) |
8406 | { |
8407 | if (isWide()) |
8408 | setBase<OpcodeSize::Wide>(value, func); |
8409 | else |
8410 | setBase<OpcodeSize::Narrow>(value, func); |
8411 | } |
8412 | |
8413 | template <OpcodeSize size, typename Functor> |
8414 | void setBase(VirtualRegister value, Functor func) |
8415 | { |
8416 | if (!Fits<VirtualRegister, size>::check(value)) |
8417 | value = func(); |
8418 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
8419 | *stream = Fits<VirtualRegister, size>::convert(value); |
8420 | } |
8421 | |
8422 | template<typename Functor> |
8423 | void setProperty(VirtualRegister value, Functor func) |
8424 | { |
8425 | if (isWide()) |
8426 | setProperty<OpcodeSize::Wide>(value, func); |
8427 | else |
8428 | setProperty<OpcodeSize::Narrow>(value, func); |
8429 | } |
8430 | |
8431 | template <OpcodeSize size, typename Functor> |
8432 | void setProperty(VirtualRegister value, Functor func) |
8433 | { |
8434 | if (!Fits<VirtualRegister, size>::check(value)) |
8435 | value = func(); |
8436 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
8437 | *stream = Fits<VirtualRegister, size>::convert(value); |
8438 | } |
8439 | |
8440 | template<typename Functor> |
8441 | void setIndex(VirtualRegister value, Functor func) |
8442 | { |
8443 | if (isWide()) |
8444 | setIndex<OpcodeSize::Wide>(value, func); |
8445 | else |
8446 | setIndex<OpcodeSize::Narrow>(value, func); |
8447 | } |
8448 | |
8449 | template <OpcodeSize size, typename Functor> |
8450 | void setIndex(VirtualRegister value, Functor func) |
8451 | { |
8452 | if (!Fits<VirtualRegister, size>::check(value)) |
8453 | value = func(); |
8454 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
8455 | *stream = Fits<VirtualRegister, size>::convert(value); |
8456 | } |
8457 | |
8458 | template<typename Functor> |
8459 | void setEnumerator(VirtualRegister value, Functor func) |
8460 | { |
8461 | if (isWide()) |
8462 | setEnumerator<OpcodeSize::Wide>(value, func); |
8463 | else |
8464 | setEnumerator<OpcodeSize::Narrow>(value, func); |
8465 | } |
8466 | |
8467 | template <OpcodeSize size, typename Functor> |
8468 | void setEnumerator(VirtualRegister value, Functor func) |
8469 | { |
8470 | if (!Fits<VirtualRegister, size>::check(value)) |
8471 | value = func(); |
8472 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value); |
8473 | *stream = Fits<VirtualRegister, size>::convert(value); |
8474 | } |
8475 | |
8476 | struct Metadata { |
8477 | WTF_MAKE_NONCOPYABLE(Metadata); |
8478 | |
8479 | public: |
8480 | Metadata(const OpGetDirectPname&) { } |
8481 | |
8482 | ValueProfile m_profile; |
8483 | }; |
8484 | |
8485 | Metadata& metadata(CodeBlock* codeBlock) const |
8486 | { |
8487 | return codeBlock->metadata<Metadata>(opcodeID, m_metadataID); |
8488 | } |
8489 | |
8490 | Metadata& metadata(ExecState* exec) const |
8491 | { |
8492 | return metadata(exec->codeBlock()); |
8493 | } |
8494 | |
8495 | VirtualRegister m_dst; |
8496 | VirtualRegister m_base; |
8497 | VirtualRegister m_property; |
8498 | VirtualRegister m_index; |
8499 | VirtualRegister m_enumerator; |
8500 | unsigned m_metadataID; |
8501 | }; |
8502 | |
8503 | struct OpWide : public Instruction { |
8504 | static constexpr OpcodeID opcodeID = op_wide; |
8505 | |
8506 | static void emit(BytecodeGenerator* gen) |
8507 | { |
8508 | |
8509 | emit<OpcodeSize::Narrow, NoAssert, true>(gen) |
8510 | || emit<OpcodeSize::Wide, Assert, true>(gen); |
8511 | } |
8512 | |
8513 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
8514 | static bool emit(BytecodeGenerator* gen) |
8515 | { |
8516 | bool didEmit = emitImpl<size, recordOpcode>(gen); |
8517 | if (shouldAssert == Assert) |
8518 | ASSERT(didEmit); |
8519 | return didEmit; |
8520 | } |
8521 | |
8522 | private: |
8523 | template<OpcodeSize size, bool recordOpcode> |
8524 | static bool emitImpl(BytecodeGenerator* gen) |
8525 | { |
8526 | if (size == OpcodeSize::Wide) |
8527 | gen->alignWideOpcode(); |
8528 | if (Fits<unsigned, size>::check(opcodeID) |
8529 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
8530 | if (recordOpcode) |
8531 | gen->recordOpcode(opcodeID); |
8532 | if (size == OpcodeSize::Wide) |
8533 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
8534 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
8535 | return true; |
8536 | } |
8537 | return false; |
8538 | } |
8539 | |
8540 | public: |
8541 | template<typename Block> |
8542 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
8543 | { |
8544 | dumper->printLocationAndOp(__location, &"*wide" [!__isWide]); |
8545 | |
8546 | } |
8547 | |
8548 | OpWide(const uint8_t* stream) |
8549 | |
8550 | { |
8551 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8552 | } |
8553 | |
8554 | OpWide(const uint32_t* stream) |
8555 | |
8556 | { |
8557 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8558 | } |
8559 | |
8560 | static OpWide decode(const uint8_t* stream) |
8561 | { |
8562 | if (*stream != op_wide) |
8563 | return { stream }; |
8564 | |
8565 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
8566 | return { wideStream }; |
8567 | } |
8568 | |
8569 | |
8570 | |
8571 | }; |
8572 | |
8573 | struct OpEnter : public Instruction { |
8574 | static constexpr OpcodeID opcodeID = op_enter; |
8575 | |
8576 | static void emit(BytecodeGenerator* gen) |
8577 | { |
8578 | |
8579 | emit<OpcodeSize::Narrow, NoAssert, true>(gen) |
8580 | || emit<OpcodeSize::Wide, Assert, true>(gen); |
8581 | } |
8582 | |
8583 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
8584 | static bool emit(BytecodeGenerator* gen) |
8585 | { |
8586 | bool didEmit = emitImpl<size, recordOpcode>(gen); |
8587 | if (shouldAssert == Assert) |
8588 | ASSERT(didEmit); |
8589 | return didEmit; |
8590 | } |
8591 | |
8592 | private: |
8593 | template<OpcodeSize size, bool recordOpcode> |
8594 | static bool emitImpl(BytecodeGenerator* gen) |
8595 | { |
8596 | if (size == OpcodeSize::Wide) |
8597 | gen->alignWideOpcode(); |
8598 | if (Fits<unsigned, size>::check(opcodeID) |
8599 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
8600 | if (recordOpcode) |
8601 | gen->recordOpcode(opcodeID); |
8602 | if (size == OpcodeSize::Wide) |
8603 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
8604 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
8605 | return true; |
8606 | } |
8607 | return false; |
8608 | } |
8609 | |
8610 | public: |
8611 | template<typename Block> |
8612 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
8613 | { |
8614 | dumper->printLocationAndOp(__location, &"*enter" [!__isWide]); |
8615 | |
8616 | } |
8617 | |
8618 | OpEnter(const uint8_t* stream) |
8619 | |
8620 | { |
8621 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8622 | } |
8623 | |
8624 | OpEnter(const uint32_t* stream) |
8625 | |
8626 | { |
8627 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8628 | } |
8629 | |
8630 | static OpEnter decode(const uint8_t* stream) |
8631 | { |
8632 | if (*stream != op_wide) |
8633 | return { stream }; |
8634 | |
8635 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
8636 | return { wideStream }; |
8637 | } |
8638 | |
8639 | |
8640 | |
8641 | }; |
8642 | |
8643 | struct OpGetScope : public Instruction { |
8644 | static constexpr OpcodeID opcodeID = op_get_scope; |
8645 | |
8646 | static void emit(BytecodeGenerator* gen, VirtualRegister dst) |
8647 | { |
8648 | |
8649 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst) |
8650 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst); |
8651 | } |
8652 | |
8653 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
8654 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst) |
8655 | { |
8656 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst); |
8657 | if (shouldAssert == Assert) |
8658 | ASSERT(didEmit); |
8659 | return didEmit; |
8660 | } |
8661 | |
8662 | private: |
8663 | template<OpcodeSize size, bool recordOpcode> |
8664 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst) |
8665 | { |
8666 | if (size == OpcodeSize::Wide) |
8667 | gen->alignWideOpcode(); |
8668 | if (Fits<unsigned, size>::check(opcodeID) |
8669 | && Fits<VirtualRegister, size>::check(dst) |
8670 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
8671 | if (recordOpcode) |
8672 | gen->recordOpcode(opcodeID); |
8673 | if (size == OpcodeSize::Wide) |
8674 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
8675 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
8676 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
8677 | return true; |
8678 | } |
8679 | return false; |
8680 | } |
8681 | |
8682 | public: |
8683 | template<typename Block> |
8684 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
8685 | { |
8686 | dumper->printLocationAndOp(__location, &"*get_scope" [!__isWide]); |
8687 | dumper->dumpOperand(m_dst, true); |
8688 | } |
8689 | |
8690 | OpGetScope(const uint8_t* stream) |
8691 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
8692 | { |
8693 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8694 | } |
8695 | |
8696 | OpGetScope(const uint32_t* stream) |
8697 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
8698 | { |
8699 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8700 | } |
8701 | |
8702 | static OpGetScope decode(const uint8_t* stream) |
8703 | { |
8704 | if (*stream != op_wide) |
8705 | return { stream }; |
8706 | |
8707 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
8708 | return { wideStream }; |
8709 | } |
8710 | |
8711 | template<typename Functor> |
8712 | void setDst(VirtualRegister value, Functor func) |
8713 | { |
8714 | if (isWide()) |
8715 | setDst<OpcodeSize::Wide>(value, func); |
8716 | else |
8717 | setDst<OpcodeSize::Narrow>(value, func); |
8718 | } |
8719 | |
8720 | template <OpcodeSize size, typename Functor> |
8721 | void setDst(VirtualRegister value, Functor func) |
8722 | { |
8723 | if (!Fits<VirtualRegister, size>::check(value)) |
8724 | value = func(); |
8725 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
8726 | *stream = Fits<VirtualRegister, size>::convert(value); |
8727 | } |
8728 | |
8729 | VirtualRegister m_dst; |
8730 | }; |
8731 | |
8732 | struct OpCreateDirectArguments : public Instruction { |
8733 | static constexpr OpcodeID opcodeID = op_create_direct_arguments; |
8734 | |
8735 | static void emit(BytecodeGenerator* gen, VirtualRegister dst) |
8736 | { |
8737 | |
8738 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst) |
8739 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst); |
8740 | } |
8741 | |
8742 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
8743 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst) |
8744 | { |
8745 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst); |
8746 | if (shouldAssert == Assert) |
8747 | ASSERT(didEmit); |
8748 | return didEmit; |
8749 | } |
8750 | |
8751 | private: |
8752 | template<OpcodeSize size, bool recordOpcode> |
8753 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst) |
8754 | { |
8755 | if (size == OpcodeSize::Wide) |
8756 | gen->alignWideOpcode(); |
8757 | if (Fits<unsigned, size>::check(opcodeID) |
8758 | && Fits<VirtualRegister, size>::check(dst) |
8759 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
8760 | if (recordOpcode) |
8761 | gen->recordOpcode(opcodeID); |
8762 | if (size == OpcodeSize::Wide) |
8763 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
8764 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
8765 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
8766 | return true; |
8767 | } |
8768 | return false; |
8769 | } |
8770 | |
8771 | public: |
8772 | template<typename Block> |
8773 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
8774 | { |
8775 | dumper->printLocationAndOp(__location, &"*create_direct_arguments" [!__isWide]); |
8776 | dumper->dumpOperand(m_dst, true); |
8777 | } |
8778 | |
8779 | OpCreateDirectArguments(const uint8_t* stream) |
8780 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
8781 | { |
8782 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8783 | } |
8784 | |
8785 | OpCreateDirectArguments(const uint32_t* stream) |
8786 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
8787 | { |
8788 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8789 | } |
8790 | |
8791 | static OpCreateDirectArguments decode(const uint8_t* stream) |
8792 | { |
8793 | if (*stream != op_wide) |
8794 | return { stream }; |
8795 | |
8796 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
8797 | return { wideStream }; |
8798 | } |
8799 | |
8800 | template<typename Functor> |
8801 | void setDst(VirtualRegister value, Functor func) |
8802 | { |
8803 | if (isWide()) |
8804 | setDst<OpcodeSize::Wide>(value, func); |
8805 | else |
8806 | setDst<OpcodeSize::Narrow>(value, func); |
8807 | } |
8808 | |
8809 | template <OpcodeSize size, typename Functor> |
8810 | void setDst(VirtualRegister value, Functor func) |
8811 | { |
8812 | if (!Fits<VirtualRegister, size>::check(value)) |
8813 | value = func(); |
8814 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
8815 | *stream = Fits<VirtualRegister, size>::convert(value); |
8816 | } |
8817 | |
8818 | VirtualRegister m_dst; |
8819 | }; |
8820 | |
8821 | struct OpCreateScopedArguments : public Instruction { |
8822 | static constexpr OpcodeID opcodeID = op_create_scoped_arguments; |
8823 | |
8824 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope) |
8825 | { |
8826 | |
8827 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope) |
8828 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope); |
8829 | } |
8830 | |
8831 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
8832 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope) |
8833 | { |
8834 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope); |
8835 | if (shouldAssert == Assert) |
8836 | ASSERT(didEmit); |
8837 | return didEmit; |
8838 | } |
8839 | |
8840 | private: |
8841 | template<OpcodeSize size, bool recordOpcode> |
8842 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope) |
8843 | { |
8844 | if (size == OpcodeSize::Wide) |
8845 | gen->alignWideOpcode(); |
8846 | if (Fits<unsigned, size>::check(opcodeID) |
8847 | && Fits<VirtualRegister, size>::check(dst) |
8848 | && Fits<VirtualRegister, size>::check(scope) |
8849 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
8850 | if (recordOpcode) |
8851 | gen->recordOpcode(opcodeID); |
8852 | if (size == OpcodeSize::Wide) |
8853 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
8854 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
8855 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
8856 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
8857 | return true; |
8858 | } |
8859 | return false; |
8860 | } |
8861 | |
8862 | public: |
8863 | template<typename Block> |
8864 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
8865 | { |
8866 | dumper->printLocationAndOp(__location, &"*create_scoped_arguments" [!__isWide]); |
8867 | dumper->dumpOperand(m_dst, true); |
8868 | dumper->dumpOperand(m_scope, false); |
8869 | } |
8870 | |
8871 | OpCreateScopedArguments(const uint8_t* stream) |
8872 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
8873 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
8874 | { |
8875 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8876 | } |
8877 | |
8878 | OpCreateScopedArguments(const uint32_t* stream) |
8879 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
8880 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
8881 | { |
8882 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8883 | } |
8884 | |
8885 | static OpCreateScopedArguments decode(const uint8_t* stream) |
8886 | { |
8887 | if (*stream != op_wide) |
8888 | return { stream }; |
8889 | |
8890 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
8891 | return { wideStream }; |
8892 | } |
8893 | |
8894 | template<typename Functor> |
8895 | void setDst(VirtualRegister value, Functor func) |
8896 | { |
8897 | if (isWide()) |
8898 | setDst<OpcodeSize::Wide>(value, func); |
8899 | else |
8900 | setDst<OpcodeSize::Narrow>(value, func); |
8901 | } |
8902 | |
8903 | template <OpcodeSize size, typename Functor> |
8904 | void setDst(VirtualRegister value, Functor func) |
8905 | { |
8906 | if (!Fits<VirtualRegister, size>::check(value)) |
8907 | value = func(); |
8908 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
8909 | *stream = Fits<VirtualRegister, size>::convert(value); |
8910 | } |
8911 | |
8912 | template<typename Functor> |
8913 | void setScope(VirtualRegister value, Functor func) |
8914 | { |
8915 | if (isWide()) |
8916 | setScope<OpcodeSize::Wide>(value, func); |
8917 | else |
8918 | setScope<OpcodeSize::Narrow>(value, func); |
8919 | } |
8920 | |
8921 | template <OpcodeSize size, typename Functor> |
8922 | void setScope(VirtualRegister value, Functor func) |
8923 | { |
8924 | if (!Fits<VirtualRegister, size>::check(value)) |
8925 | value = func(); |
8926 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
8927 | *stream = Fits<VirtualRegister, size>::convert(value); |
8928 | } |
8929 | |
8930 | VirtualRegister m_dst; |
8931 | VirtualRegister m_scope; |
8932 | }; |
8933 | |
8934 | struct OpCreateClonedArguments : public Instruction { |
8935 | static constexpr OpcodeID opcodeID = op_create_cloned_arguments; |
8936 | |
8937 | static void emit(BytecodeGenerator* gen, VirtualRegister dst) |
8938 | { |
8939 | |
8940 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst) |
8941 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst); |
8942 | } |
8943 | |
8944 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
8945 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst) |
8946 | { |
8947 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst); |
8948 | if (shouldAssert == Assert) |
8949 | ASSERT(didEmit); |
8950 | return didEmit; |
8951 | } |
8952 | |
8953 | private: |
8954 | template<OpcodeSize size, bool recordOpcode> |
8955 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst) |
8956 | { |
8957 | if (size == OpcodeSize::Wide) |
8958 | gen->alignWideOpcode(); |
8959 | if (Fits<unsigned, size>::check(opcodeID) |
8960 | && Fits<VirtualRegister, size>::check(dst) |
8961 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
8962 | if (recordOpcode) |
8963 | gen->recordOpcode(opcodeID); |
8964 | if (size == OpcodeSize::Wide) |
8965 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
8966 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
8967 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
8968 | return true; |
8969 | } |
8970 | return false; |
8971 | } |
8972 | |
8973 | public: |
8974 | template<typename Block> |
8975 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
8976 | { |
8977 | dumper->printLocationAndOp(__location, &"*create_cloned_arguments" [!__isWide]); |
8978 | dumper->dumpOperand(m_dst, true); |
8979 | } |
8980 | |
8981 | OpCreateClonedArguments(const uint8_t* stream) |
8982 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
8983 | { |
8984 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8985 | } |
8986 | |
8987 | OpCreateClonedArguments(const uint32_t* stream) |
8988 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
8989 | { |
8990 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
8991 | } |
8992 | |
8993 | static OpCreateClonedArguments decode(const uint8_t* stream) |
8994 | { |
8995 | if (*stream != op_wide) |
8996 | return { stream }; |
8997 | |
8998 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
8999 | return { wideStream }; |
9000 | } |
9001 | |
9002 | template<typename Functor> |
9003 | void setDst(VirtualRegister value, Functor func) |
9004 | { |
9005 | if (isWide()) |
9006 | setDst<OpcodeSize::Wide>(value, func); |
9007 | else |
9008 | setDst<OpcodeSize::Narrow>(value, func); |
9009 | } |
9010 | |
9011 | template <OpcodeSize size, typename Functor> |
9012 | void setDst(VirtualRegister value, Functor func) |
9013 | { |
9014 | if (!Fits<VirtualRegister, size>::check(value)) |
9015 | value = func(); |
9016 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
9017 | *stream = Fits<VirtualRegister, size>::convert(value); |
9018 | } |
9019 | |
9020 | VirtualRegister m_dst; |
9021 | }; |
9022 | |
9023 | struct OpArgumentCount : public Instruction { |
9024 | static constexpr OpcodeID opcodeID = op_argument_count; |
9025 | |
9026 | static void emit(BytecodeGenerator* gen, VirtualRegister dst) |
9027 | { |
9028 | |
9029 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst) |
9030 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst); |
9031 | } |
9032 | |
9033 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
9034 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst) |
9035 | { |
9036 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst); |
9037 | if (shouldAssert == Assert) |
9038 | ASSERT(didEmit); |
9039 | return didEmit; |
9040 | } |
9041 | |
9042 | private: |
9043 | template<OpcodeSize size, bool recordOpcode> |
9044 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst) |
9045 | { |
9046 | if (size == OpcodeSize::Wide) |
9047 | gen->alignWideOpcode(); |
9048 | if (Fits<unsigned, size>::check(opcodeID) |
9049 | && Fits<VirtualRegister, size>::check(dst) |
9050 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
9051 | if (recordOpcode) |
9052 | gen->recordOpcode(opcodeID); |
9053 | if (size == OpcodeSize::Wide) |
9054 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
9055 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
9056 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
9057 | return true; |
9058 | } |
9059 | return false; |
9060 | } |
9061 | |
9062 | public: |
9063 | template<typename Block> |
9064 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
9065 | { |
9066 | dumper->printLocationAndOp(__location, &"*argument_count" [!__isWide]); |
9067 | dumper->dumpOperand(m_dst, true); |
9068 | } |
9069 | |
9070 | OpArgumentCount(const uint8_t* stream) |
9071 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
9072 | { |
9073 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9074 | } |
9075 | |
9076 | OpArgumentCount(const uint32_t* stream) |
9077 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
9078 | { |
9079 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9080 | } |
9081 | |
9082 | static OpArgumentCount decode(const uint8_t* stream) |
9083 | { |
9084 | if (*stream != op_wide) |
9085 | return { stream }; |
9086 | |
9087 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
9088 | return { wideStream }; |
9089 | } |
9090 | |
9091 | template<typename Functor> |
9092 | void setDst(VirtualRegister value, Functor func) |
9093 | { |
9094 | if (isWide()) |
9095 | setDst<OpcodeSize::Wide>(value, func); |
9096 | else |
9097 | setDst<OpcodeSize::Narrow>(value, func); |
9098 | } |
9099 | |
9100 | template <OpcodeSize size, typename Functor> |
9101 | void setDst(VirtualRegister value, Functor func) |
9102 | { |
9103 | if (!Fits<VirtualRegister, size>::check(value)) |
9104 | value = func(); |
9105 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
9106 | *stream = Fits<VirtualRegister, size>::convert(value); |
9107 | } |
9108 | |
9109 | VirtualRegister m_dst; |
9110 | }; |
9111 | |
9112 | struct OpCheckTdz : public Instruction { |
9113 | static constexpr OpcodeID opcodeID = op_check_tdz; |
9114 | |
9115 | static void emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister) |
9116 | { |
9117 | |
9118 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, targetVirtualRegister) |
9119 | || emit<OpcodeSize::Wide, Assert, true>(gen, targetVirtualRegister); |
9120 | } |
9121 | |
9122 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
9123 | static bool emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister) |
9124 | { |
9125 | bool didEmit = emitImpl<size, recordOpcode>(gen, targetVirtualRegister); |
9126 | if (shouldAssert == Assert) |
9127 | ASSERT(didEmit); |
9128 | return didEmit; |
9129 | } |
9130 | |
9131 | private: |
9132 | template<OpcodeSize size, bool recordOpcode> |
9133 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister) |
9134 | { |
9135 | if (size == OpcodeSize::Wide) |
9136 | gen->alignWideOpcode(); |
9137 | if (Fits<unsigned, size>::check(opcodeID) |
9138 | && Fits<VirtualRegister, size>::check(targetVirtualRegister) |
9139 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
9140 | if (recordOpcode) |
9141 | gen->recordOpcode(opcodeID); |
9142 | if (size == OpcodeSize::Wide) |
9143 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
9144 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
9145 | gen->write(Fits<VirtualRegister, size>::convert(targetVirtualRegister)); |
9146 | return true; |
9147 | } |
9148 | return false; |
9149 | } |
9150 | |
9151 | public: |
9152 | template<typename Block> |
9153 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
9154 | { |
9155 | dumper->printLocationAndOp(__location, &"*check_tdz" [!__isWide]); |
9156 | dumper->dumpOperand(m_targetVirtualRegister, true); |
9157 | } |
9158 | |
9159 | OpCheckTdz(const uint8_t* stream) |
9160 | : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
9161 | { |
9162 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9163 | } |
9164 | |
9165 | OpCheckTdz(const uint32_t* stream) |
9166 | : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
9167 | { |
9168 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9169 | } |
9170 | |
9171 | static OpCheckTdz decode(const uint8_t* stream) |
9172 | { |
9173 | if (*stream != op_wide) |
9174 | return { stream }; |
9175 | |
9176 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
9177 | return { wideStream }; |
9178 | } |
9179 | |
9180 | template<typename Functor> |
9181 | void setTargetVirtualRegister(VirtualRegister value, Functor func) |
9182 | { |
9183 | if (isWide()) |
9184 | setTargetVirtualRegister<OpcodeSize::Wide>(value, func); |
9185 | else |
9186 | setTargetVirtualRegister<OpcodeSize::Narrow>(value, func); |
9187 | } |
9188 | |
9189 | template <OpcodeSize size, typename Functor> |
9190 | void setTargetVirtualRegister(VirtualRegister value, Functor func) |
9191 | { |
9192 | if (!Fits<VirtualRegister, size>::check(value)) |
9193 | value = func(); |
9194 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
9195 | *stream = Fits<VirtualRegister, size>::convert(value); |
9196 | } |
9197 | |
9198 | VirtualRegister m_targetVirtualRegister; |
9199 | }; |
9200 | |
9201 | struct OpNewArrayWithSpread : public Instruction { |
9202 | static constexpr OpcodeID opcodeID = op_new_array_with_spread; |
9203 | |
9204 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, unsigned bitVector) |
9205 | { |
9206 | |
9207 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, argv, argc, bitVector) |
9208 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, argv, argc, bitVector); |
9209 | } |
9210 | |
9211 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
9212 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, unsigned bitVector) |
9213 | { |
9214 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, argv, argc, bitVector); |
9215 | if (shouldAssert == Assert) |
9216 | ASSERT(didEmit); |
9217 | return didEmit; |
9218 | } |
9219 | |
9220 | private: |
9221 | template<OpcodeSize size, bool recordOpcode> |
9222 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, unsigned bitVector) |
9223 | { |
9224 | if (size == OpcodeSize::Wide) |
9225 | gen->alignWideOpcode(); |
9226 | if (Fits<unsigned, size>::check(opcodeID) |
9227 | && Fits<VirtualRegister, size>::check(dst) |
9228 | && Fits<VirtualRegister, size>::check(argv) |
9229 | && Fits<unsigned, size>::check(argc) |
9230 | && Fits<unsigned, size>::check(bitVector) |
9231 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
9232 | if (recordOpcode) |
9233 | gen->recordOpcode(opcodeID); |
9234 | if (size == OpcodeSize::Wide) |
9235 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
9236 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
9237 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
9238 | gen->write(Fits<VirtualRegister, size>::convert(argv)); |
9239 | gen->write(Fits<unsigned, size>::convert(argc)); |
9240 | gen->write(Fits<unsigned, size>::convert(bitVector)); |
9241 | return true; |
9242 | } |
9243 | return false; |
9244 | } |
9245 | |
9246 | public: |
9247 | template<typename Block> |
9248 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
9249 | { |
9250 | dumper->printLocationAndOp(__location, &"*new_array_with_spread" [!__isWide]); |
9251 | dumper->dumpOperand(m_dst, true); |
9252 | dumper->dumpOperand(m_argv, false); |
9253 | dumper->dumpOperand(m_argc, false); |
9254 | dumper->dumpOperand(m_bitVector, false); |
9255 | } |
9256 | |
9257 | OpNewArrayWithSpread(const uint8_t* stream) |
9258 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
9259 | , m_argv(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
9260 | , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
9261 | , m_bitVector(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4])) |
9262 | { |
9263 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9264 | } |
9265 | |
9266 | OpNewArrayWithSpread(const uint32_t* stream) |
9267 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
9268 | , m_argv(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
9269 | , m_argc(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
9270 | , m_bitVector(Fits<unsigned, OpcodeSize::Wide>::convert(stream[4])) |
9271 | { |
9272 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9273 | } |
9274 | |
9275 | static OpNewArrayWithSpread decode(const uint8_t* stream) |
9276 | { |
9277 | if (*stream != op_wide) |
9278 | return { stream }; |
9279 | |
9280 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
9281 | return { wideStream }; |
9282 | } |
9283 | |
9284 | template<typename Functor> |
9285 | void setDst(VirtualRegister value, Functor func) |
9286 | { |
9287 | if (isWide()) |
9288 | setDst<OpcodeSize::Wide>(value, func); |
9289 | else |
9290 | setDst<OpcodeSize::Narrow>(value, func); |
9291 | } |
9292 | |
9293 | template <OpcodeSize size, typename Functor> |
9294 | void setDst(VirtualRegister value, Functor func) |
9295 | { |
9296 | if (!Fits<VirtualRegister, size>::check(value)) |
9297 | value = func(); |
9298 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
9299 | *stream = Fits<VirtualRegister, size>::convert(value); |
9300 | } |
9301 | |
9302 | template<typename Functor> |
9303 | void setArgv(VirtualRegister value, Functor func) |
9304 | { |
9305 | if (isWide()) |
9306 | setArgv<OpcodeSize::Wide>(value, func); |
9307 | else |
9308 | setArgv<OpcodeSize::Narrow>(value, func); |
9309 | } |
9310 | |
9311 | template <OpcodeSize size, typename Functor> |
9312 | void setArgv(VirtualRegister value, Functor func) |
9313 | { |
9314 | if (!Fits<VirtualRegister, size>::check(value)) |
9315 | value = func(); |
9316 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
9317 | *stream = Fits<VirtualRegister, size>::convert(value); |
9318 | } |
9319 | |
9320 | template<typename Functor> |
9321 | void setArgc(unsigned value, Functor func) |
9322 | { |
9323 | if (isWide()) |
9324 | setArgc<OpcodeSize::Wide>(value, func); |
9325 | else |
9326 | setArgc<OpcodeSize::Narrow>(value, func); |
9327 | } |
9328 | |
9329 | template <OpcodeSize size, typename Functor> |
9330 | void setArgc(unsigned value, Functor func) |
9331 | { |
9332 | if (!Fits<unsigned, size>::check(value)) |
9333 | value = func(); |
9334 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
9335 | *stream = Fits<unsigned, size>::convert(value); |
9336 | } |
9337 | |
9338 | template<typename Functor> |
9339 | void setBitVector(unsigned value, Functor func) |
9340 | { |
9341 | if (isWide()) |
9342 | setBitVector<OpcodeSize::Wide>(value, func); |
9343 | else |
9344 | setBitVector<OpcodeSize::Narrow>(value, func); |
9345 | } |
9346 | |
9347 | template <OpcodeSize size, typename Functor> |
9348 | void setBitVector(unsigned value, Functor func) |
9349 | { |
9350 | if (!Fits<unsigned, size>::check(value)) |
9351 | value = func(); |
9352 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
9353 | *stream = Fits<unsigned, size>::convert(value); |
9354 | } |
9355 | |
9356 | VirtualRegister m_dst; |
9357 | VirtualRegister m_argv; |
9358 | unsigned m_argc; |
9359 | unsigned m_bitVector; |
9360 | }; |
9361 | |
9362 | struct OpSpread : public Instruction { |
9363 | static constexpr OpcodeID opcodeID = op_spread; |
9364 | |
9365 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argument) |
9366 | { |
9367 | |
9368 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, argument) |
9369 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, argument); |
9370 | } |
9371 | |
9372 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
9373 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argument) |
9374 | { |
9375 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, argument); |
9376 | if (shouldAssert == Assert) |
9377 | ASSERT(didEmit); |
9378 | return didEmit; |
9379 | } |
9380 | |
9381 | private: |
9382 | template<OpcodeSize size, bool recordOpcode> |
9383 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argument) |
9384 | { |
9385 | if (size == OpcodeSize::Wide) |
9386 | gen->alignWideOpcode(); |
9387 | if (Fits<unsigned, size>::check(opcodeID) |
9388 | && Fits<VirtualRegister, size>::check(dst) |
9389 | && Fits<VirtualRegister, size>::check(argument) |
9390 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
9391 | if (recordOpcode) |
9392 | gen->recordOpcode(opcodeID); |
9393 | if (size == OpcodeSize::Wide) |
9394 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
9395 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
9396 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
9397 | gen->write(Fits<VirtualRegister, size>::convert(argument)); |
9398 | return true; |
9399 | } |
9400 | return false; |
9401 | } |
9402 | |
9403 | public: |
9404 | template<typename Block> |
9405 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
9406 | { |
9407 | dumper->printLocationAndOp(__location, &"*spread" [!__isWide]); |
9408 | dumper->dumpOperand(m_dst, true); |
9409 | dumper->dumpOperand(m_argument, false); |
9410 | } |
9411 | |
9412 | OpSpread(const uint8_t* stream) |
9413 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
9414 | , m_argument(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
9415 | { |
9416 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9417 | } |
9418 | |
9419 | OpSpread(const uint32_t* stream) |
9420 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
9421 | , m_argument(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
9422 | { |
9423 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9424 | } |
9425 | |
9426 | static OpSpread decode(const uint8_t* stream) |
9427 | { |
9428 | if (*stream != op_wide) |
9429 | return { stream }; |
9430 | |
9431 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
9432 | return { wideStream }; |
9433 | } |
9434 | |
9435 | template<typename Functor> |
9436 | void setDst(VirtualRegister value, Functor func) |
9437 | { |
9438 | if (isWide()) |
9439 | setDst<OpcodeSize::Wide>(value, func); |
9440 | else |
9441 | setDst<OpcodeSize::Narrow>(value, func); |
9442 | } |
9443 | |
9444 | template <OpcodeSize size, typename Functor> |
9445 | void setDst(VirtualRegister value, Functor func) |
9446 | { |
9447 | if (!Fits<VirtualRegister, size>::check(value)) |
9448 | value = func(); |
9449 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
9450 | *stream = Fits<VirtualRegister, size>::convert(value); |
9451 | } |
9452 | |
9453 | template<typename Functor> |
9454 | void setArgument(VirtualRegister value, Functor func) |
9455 | { |
9456 | if (isWide()) |
9457 | setArgument<OpcodeSize::Wide>(value, func); |
9458 | else |
9459 | setArgument<OpcodeSize::Narrow>(value, func); |
9460 | } |
9461 | |
9462 | template <OpcodeSize size, typename Functor> |
9463 | void setArgument(VirtualRegister value, Functor func) |
9464 | { |
9465 | if (!Fits<VirtualRegister, size>::check(value)) |
9466 | value = func(); |
9467 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
9468 | *stream = Fits<VirtualRegister, size>::convert(value); |
9469 | } |
9470 | |
9471 | VirtualRegister m_dst; |
9472 | VirtualRegister m_argument; |
9473 | }; |
9474 | |
9475 | struct OpNewRegexp : public Instruction { |
9476 | static constexpr OpcodeID opcodeID = op_new_regexp; |
9477 | |
9478 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister regexp) |
9479 | { |
9480 | |
9481 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, regexp) |
9482 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, regexp); |
9483 | } |
9484 | |
9485 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
9486 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister regexp) |
9487 | { |
9488 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, regexp); |
9489 | if (shouldAssert == Assert) |
9490 | ASSERT(didEmit); |
9491 | return didEmit; |
9492 | } |
9493 | |
9494 | private: |
9495 | template<OpcodeSize size, bool recordOpcode> |
9496 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister regexp) |
9497 | { |
9498 | if (size == OpcodeSize::Wide) |
9499 | gen->alignWideOpcode(); |
9500 | if (Fits<unsigned, size>::check(opcodeID) |
9501 | && Fits<VirtualRegister, size>::check(dst) |
9502 | && Fits<VirtualRegister, size>::check(regexp) |
9503 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
9504 | if (recordOpcode) |
9505 | gen->recordOpcode(opcodeID); |
9506 | if (size == OpcodeSize::Wide) |
9507 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
9508 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
9509 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
9510 | gen->write(Fits<VirtualRegister, size>::convert(regexp)); |
9511 | return true; |
9512 | } |
9513 | return false; |
9514 | } |
9515 | |
9516 | public: |
9517 | template<typename Block> |
9518 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
9519 | { |
9520 | dumper->printLocationAndOp(__location, &"*new_regexp" [!__isWide]); |
9521 | dumper->dumpOperand(m_dst, true); |
9522 | dumper->dumpOperand(m_regexp, false); |
9523 | } |
9524 | |
9525 | OpNewRegexp(const uint8_t* stream) |
9526 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
9527 | , m_regexp(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
9528 | { |
9529 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9530 | } |
9531 | |
9532 | OpNewRegexp(const uint32_t* stream) |
9533 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
9534 | , m_regexp(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
9535 | { |
9536 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9537 | } |
9538 | |
9539 | static OpNewRegexp decode(const uint8_t* stream) |
9540 | { |
9541 | if (*stream != op_wide) |
9542 | return { stream }; |
9543 | |
9544 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
9545 | return { wideStream }; |
9546 | } |
9547 | |
9548 | template<typename Functor> |
9549 | void setDst(VirtualRegister value, Functor func) |
9550 | { |
9551 | if (isWide()) |
9552 | setDst<OpcodeSize::Wide>(value, func); |
9553 | else |
9554 | setDst<OpcodeSize::Narrow>(value, func); |
9555 | } |
9556 | |
9557 | template <OpcodeSize size, typename Functor> |
9558 | void setDst(VirtualRegister value, Functor func) |
9559 | { |
9560 | if (!Fits<VirtualRegister, size>::check(value)) |
9561 | value = func(); |
9562 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
9563 | *stream = Fits<VirtualRegister, size>::convert(value); |
9564 | } |
9565 | |
9566 | template<typename Functor> |
9567 | void setRegexp(VirtualRegister value, Functor func) |
9568 | { |
9569 | if (isWide()) |
9570 | setRegexp<OpcodeSize::Wide>(value, func); |
9571 | else |
9572 | setRegexp<OpcodeSize::Narrow>(value, func); |
9573 | } |
9574 | |
9575 | template <OpcodeSize size, typename Functor> |
9576 | void setRegexp(VirtualRegister value, Functor func) |
9577 | { |
9578 | if (!Fits<VirtualRegister, size>::check(value)) |
9579 | value = func(); |
9580 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
9581 | *stream = Fits<VirtualRegister, size>::convert(value); |
9582 | } |
9583 | |
9584 | VirtualRegister m_dst; |
9585 | VirtualRegister m_regexp; |
9586 | }; |
9587 | |
9588 | struct OpMov : public Instruction { |
9589 | static constexpr OpcodeID opcodeID = op_mov; |
9590 | |
9591 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src) |
9592 | { |
9593 | |
9594 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, src) |
9595 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, src); |
9596 | } |
9597 | |
9598 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
9599 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src) |
9600 | { |
9601 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, src); |
9602 | if (shouldAssert == Assert) |
9603 | ASSERT(didEmit); |
9604 | return didEmit; |
9605 | } |
9606 | |
9607 | private: |
9608 | template<OpcodeSize size, bool recordOpcode> |
9609 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src) |
9610 | { |
9611 | if (size == OpcodeSize::Wide) |
9612 | gen->alignWideOpcode(); |
9613 | if (Fits<unsigned, size>::check(opcodeID) |
9614 | && Fits<VirtualRegister, size>::check(dst) |
9615 | && Fits<VirtualRegister, size>::check(src) |
9616 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
9617 | if (recordOpcode) |
9618 | gen->recordOpcode(opcodeID); |
9619 | if (size == OpcodeSize::Wide) |
9620 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
9621 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
9622 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
9623 | gen->write(Fits<VirtualRegister, size>::convert(src)); |
9624 | return true; |
9625 | } |
9626 | return false; |
9627 | } |
9628 | |
9629 | public: |
9630 | template<typename Block> |
9631 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
9632 | { |
9633 | dumper->printLocationAndOp(__location, &"*mov" [!__isWide]); |
9634 | dumper->dumpOperand(m_dst, true); |
9635 | dumper->dumpOperand(m_src, false); |
9636 | } |
9637 | |
9638 | OpMov(const uint8_t* stream) |
9639 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
9640 | , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
9641 | { |
9642 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9643 | } |
9644 | |
9645 | OpMov(const uint32_t* stream) |
9646 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
9647 | , m_src(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
9648 | { |
9649 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9650 | } |
9651 | |
9652 | static OpMov decode(const uint8_t* stream) |
9653 | { |
9654 | if (*stream != op_wide) |
9655 | return { stream }; |
9656 | |
9657 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
9658 | return { wideStream }; |
9659 | } |
9660 | |
9661 | template<typename Functor> |
9662 | void setDst(VirtualRegister value, Functor func) |
9663 | { |
9664 | if (isWide()) |
9665 | setDst<OpcodeSize::Wide>(value, func); |
9666 | else |
9667 | setDst<OpcodeSize::Narrow>(value, func); |
9668 | } |
9669 | |
9670 | template <OpcodeSize size, typename Functor> |
9671 | void setDst(VirtualRegister value, Functor func) |
9672 | { |
9673 | if (!Fits<VirtualRegister, size>::check(value)) |
9674 | value = func(); |
9675 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
9676 | *stream = Fits<VirtualRegister, size>::convert(value); |
9677 | } |
9678 | |
9679 | template<typename Functor> |
9680 | void setSrc(VirtualRegister value, Functor func) |
9681 | { |
9682 | if (isWide()) |
9683 | setSrc<OpcodeSize::Wide>(value, func); |
9684 | else |
9685 | setSrc<OpcodeSize::Narrow>(value, func); |
9686 | } |
9687 | |
9688 | template <OpcodeSize size, typename Functor> |
9689 | void setSrc(VirtualRegister value, Functor func) |
9690 | { |
9691 | if (!Fits<VirtualRegister, size>::check(value)) |
9692 | value = func(); |
9693 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
9694 | *stream = Fits<VirtualRegister, size>::convert(value); |
9695 | } |
9696 | |
9697 | VirtualRegister m_dst; |
9698 | VirtualRegister m_src; |
9699 | }; |
9700 | |
9701 | struct OpEq : public Instruction { |
9702 | static constexpr OpcodeID opcodeID = op_eq; |
9703 | |
9704 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
9705 | { |
9706 | |
9707 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
9708 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
9709 | } |
9710 | |
9711 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
9712 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
9713 | { |
9714 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
9715 | if (shouldAssert == Assert) |
9716 | ASSERT(didEmit); |
9717 | return didEmit; |
9718 | } |
9719 | |
9720 | private: |
9721 | template<OpcodeSize size, bool recordOpcode> |
9722 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
9723 | { |
9724 | if (size == OpcodeSize::Wide) |
9725 | gen->alignWideOpcode(); |
9726 | if (Fits<unsigned, size>::check(opcodeID) |
9727 | && Fits<VirtualRegister, size>::check(dst) |
9728 | && Fits<VirtualRegister, size>::check(lhs) |
9729 | && Fits<VirtualRegister, size>::check(rhs) |
9730 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
9731 | if (recordOpcode) |
9732 | gen->recordOpcode(opcodeID); |
9733 | if (size == OpcodeSize::Wide) |
9734 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
9735 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
9736 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
9737 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
9738 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
9739 | return true; |
9740 | } |
9741 | return false; |
9742 | } |
9743 | |
9744 | public: |
9745 | template<typename Block> |
9746 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
9747 | { |
9748 | dumper->printLocationAndOp(__location, &"*eq" [!__isWide]); |
9749 | dumper->dumpOperand(m_dst, true); |
9750 | dumper->dumpOperand(m_lhs, false); |
9751 | dumper->dumpOperand(m_rhs, false); |
9752 | } |
9753 | |
9754 | OpEq(const uint8_t* stream) |
9755 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
9756 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
9757 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
9758 | { |
9759 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9760 | } |
9761 | |
9762 | OpEq(const uint32_t* stream) |
9763 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
9764 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
9765 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
9766 | { |
9767 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9768 | } |
9769 | |
9770 | static OpEq decode(const uint8_t* stream) |
9771 | { |
9772 | if (*stream != op_wide) |
9773 | return { stream }; |
9774 | |
9775 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
9776 | return { wideStream }; |
9777 | } |
9778 | |
9779 | template<typename Functor> |
9780 | void setDst(VirtualRegister value, Functor func) |
9781 | { |
9782 | if (isWide()) |
9783 | setDst<OpcodeSize::Wide>(value, func); |
9784 | else |
9785 | setDst<OpcodeSize::Narrow>(value, func); |
9786 | } |
9787 | |
9788 | template <OpcodeSize size, typename Functor> |
9789 | void setDst(VirtualRegister value, Functor func) |
9790 | { |
9791 | if (!Fits<VirtualRegister, size>::check(value)) |
9792 | value = func(); |
9793 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
9794 | *stream = Fits<VirtualRegister, size>::convert(value); |
9795 | } |
9796 | |
9797 | template<typename Functor> |
9798 | void setLhs(VirtualRegister value, Functor func) |
9799 | { |
9800 | if (isWide()) |
9801 | setLhs<OpcodeSize::Wide>(value, func); |
9802 | else |
9803 | setLhs<OpcodeSize::Narrow>(value, func); |
9804 | } |
9805 | |
9806 | template <OpcodeSize size, typename Functor> |
9807 | void setLhs(VirtualRegister value, Functor func) |
9808 | { |
9809 | if (!Fits<VirtualRegister, size>::check(value)) |
9810 | value = func(); |
9811 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
9812 | *stream = Fits<VirtualRegister, size>::convert(value); |
9813 | } |
9814 | |
9815 | template<typename Functor> |
9816 | void setRhs(VirtualRegister value, Functor func) |
9817 | { |
9818 | if (isWide()) |
9819 | setRhs<OpcodeSize::Wide>(value, func); |
9820 | else |
9821 | setRhs<OpcodeSize::Narrow>(value, func); |
9822 | } |
9823 | |
9824 | template <OpcodeSize size, typename Functor> |
9825 | void setRhs(VirtualRegister value, Functor func) |
9826 | { |
9827 | if (!Fits<VirtualRegister, size>::check(value)) |
9828 | value = func(); |
9829 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
9830 | *stream = Fits<VirtualRegister, size>::convert(value); |
9831 | } |
9832 | |
9833 | VirtualRegister m_dst; |
9834 | VirtualRegister m_lhs; |
9835 | VirtualRegister m_rhs; |
9836 | }; |
9837 | |
9838 | struct OpNeq : public Instruction { |
9839 | static constexpr OpcodeID opcodeID = op_neq; |
9840 | |
9841 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
9842 | { |
9843 | |
9844 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
9845 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
9846 | } |
9847 | |
9848 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
9849 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
9850 | { |
9851 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
9852 | if (shouldAssert == Assert) |
9853 | ASSERT(didEmit); |
9854 | return didEmit; |
9855 | } |
9856 | |
9857 | private: |
9858 | template<OpcodeSize size, bool recordOpcode> |
9859 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
9860 | { |
9861 | if (size == OpcodeSize::Wide) |
9862 | gen->alignWideOpcode(); |
9863 | if (Fits<unsigned, size>::check(opcodeID) |
9864 | && Fits<VirtualRegister, size>::check(dst) |
9865 | && Fits<VirtualRegister, size>::check(lhs) |
9866 | && Fits<VirtualRegister, size>::check(rhs) |
9867 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
9868 | if (recordOpcode) |
9869 | gen->recordOpcode(opcodeID); |
9870 | if (size == OpcodeSize::Wide) |
9871 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
9872 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
9873 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
9874 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
9875 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
9876 | return true; |
9877 | } |
9878 | return false; |
9879 | } |
9880 | |
9881 | public: |
9882 | template<typename Block> |
9883 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
9884 | { |
9885 | dumper->printLocationAndOp(__location, &"*neq" [!__isWide]); |
9886 | dumper->dumpOperand(m_dst, true); |
9887 | dumper->dumpOperand(m_lhs, false); |
9888 | dumper->dumpOperand(m_rhs, false); |
9889 | } |
9890 | |
9891 | OpNeq(const uint8_t* stream) |
9892 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
9893 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
9894 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
9895 | { |
9896 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9897 | } |
9898 | |
9899 | OpNeq(const uint32_t* stream) |
9900 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
9901 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
9902 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
9903 | { |
9904 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
9905 | } |
9906 | |
9907 | static OpNeq decode(const uint8_t* stream) |
9908 | { |
9909 | if (*stream != op_wide) |
9910 | return { stream }; |
9911 | |
9912 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
9913 | return { wideStream }; |
9914 | } |
9915 | |
9916 | template<typename Functor> |
9917 | void setDst(VirtualRegister value, Functor func) |
9918 | { |
9919 | if (isWide()) |
9920 | setDst<OpcodeSize::Wide>(value, func); |
9921 | else |
9922 | setDst<OpcodeSize::Narrow>(value, func); |
9923 | } |
9924 | |
9925 | template <OpcodeSize size, typename Functor> |
9926 | void setDst(VirtualRegister value, Functor func) |
9927 | { |
9928 | if (!Fits<VirtualRegister, size>::check(value)) |
9929 | value = func(); |
9930 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
9931 | *stream = Fits<VirtualRegister, size>::convert(value); |
9932 | } |
9933 | |
9934 | template<typename Functor> |
9935 | void setLhs(VirtualRegister value, Functor func) |
9936 | { |
9937 | if (isWide()) |
9938 | setLhs<OpcodeSize::Wide>(value, func); |
9939 | else |
9940 | setLhs<OpcodeSize::Narrow>(value, func); |
9941 | } |
9942 | |
9943 | template <OpcodeSize size, typename Functor> |
9944 | void setLhs(VirtualRegister value, Functor func) |
9945 | { |
9946 | if (!Fits<VirtualRegister, size>::check(value)) |
9947 | value = func(); |
9948 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
9949 | *stream = Fits<VirtualRegister, size>::convert(value); |
9950 | } |
9951 | |
9952 | template<typename Functor> |
9953 | void setRhs(VirtualRegister value, Functor func) |
9954 | { |
9955 | if (isWide()) |
9956 | setRhs<OpcodeSize::Wide>(value, func); |
9957 | else |
9958 | setRhs<OpcodeSize::Narrow>(value, func); |
9959 | } |
9960 | |
9961 | template <OpcodeSize size, typename Functor> |
9962 | void setRhs(VirtualRegister value, Functor func) |
9963 | { |
9964 | if (!Fits<VirtualRegister, size>::check(value)) |
9965 | value = func(); |
9966 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
9967 | *stream = Fits<VirtualRegister, size>::convert(value); |
9968 | } |
9969 | |
9970 | VirtualRegister m_dst; |
9971 | VirtualRegister m_lhs; |
9972 | VirtualRegister m_rhs; |
9973 | }; |
9974 | |
9975 | struct OpStricteq : public Instruction { |
9976 | static constexpr OpcodeID opcodeID = op_stricteq; |
9977 | |
9978 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
9979 | { |
9980 | |
9981 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
9982 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
9983 | } |
9984 | |
9985 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
9986 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
9987 | { |
9988 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
9989 | if (shouldAssert == Assert) |
9990 | ASSERT(didEmit); |
9991 | return didEmit; |
9992 | } |
9993 | |
9994 | private: |
9995 | template<OpcodeSize size, bool recordOpcode> |
9996 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
9997 | { |
9998 | if (size == OpcodeSize::Wide) |
9999 | gen->alignWideOpcode(); |
10000 | if (Fits<unsigned, size>::check(opcodeID) |
10001 | && Fits<VirtualRegister, size>::check(dst) |
10002 | && Fits<VirtualRegister, size>::check(lhs) |
10003 | && Fits<VirtualRegister, size>::check(rhs) |
10004 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
10005 | if (recordOpcode) |
10006 | gen->recordOpcode(opcodeID); |
10007 | if (size == OpcodeSize::Wide) |
10008 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
10009 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
10010 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
10011 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
10012 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
10013 | return true; |
10014 | } |
10015 | return false; |
10016 | } |
10017 | |
10018 | public: |
10019 | template<typename Block> |
10020 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
10021 | { |
10022 | dumper->printLocationAndOp(__location, &"*stricteq" [!__isWide]); |
10023 | dumper->dumpOperand(m_dst, true); |
10024 | dumper->dumpOperand(m_lhs, false); |
10025 | dumper->dumpOperand(m_rhs, false); |
10026 | } |
10027 | |
10028 | OpStricteq(const uint8_t* stream) |
10029 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
10030 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
10031 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
10032 | { |
10033 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10034 | } |
10035 | |
10036 | OpStricteq(const uint32_t* stream) |
10037 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
10038 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
10039 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
10040 | { |
10041 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10042 | } |
10043 | |
10044 | static OpStricteq decode(const uint8_t* stream) |
10045 | { |
10046 | if (*stream != op_wide) |
10047 | return { stream }; |
10048 | |
10049 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
10050 | return { wideStream }; |
10051 | } |
10052 | |
10053 | template<typename Functor> |
10054 | void setDst(VirtualRegister value, Functor func) |
10055 | { |
10056 | if (isWide()) |
10057 | setDst<OpcodeSize::Wide>(value, func); |
10058 | else |
10059 | setDst<OpcodeSize::Narrow>(value, func); |
10060 | } |
10061 | |
10062 | template <OpcodeSize size, typename Functor> |
10063 | void setDst(VirtualRegister value, Functor func) |
10064 | { |
10065 | if (!Fits<VirtualRegister, size>::check(value)) |
10066 | value = func(); |
10067 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
10068 | *stream = Fits<VirtualRegister, size>::convert(value); |
10069 | } |
10070 | |
10071 | template<typename Functor> |
10072 | void setLhs(VirtualRegister value, Functor func) |
10073 | { |
10074 | if (isWide()) |
10075 | setLhs<OpcodeSize::Wide>(value, func); |
10076 | else |
10077 | setLhs<OpcodeSize::Narrow>(value, func); |
10078 | } |
10079 | |
10080 | template <OpcodeSize size, typename Functor> |
10081 | void setLhs(VirtualRegister value, Functor func) |
10082 | { |
10083 | if (!Fits<VirtualRegister, size>::check(value)) |
10084 | value = func(); |
10085 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
10086 | *stream = Fits<VirtualRegister, size>::convert(value); |
10087 | } |
10088 | |
10089 | template<typename Functor> |
10090 | void setRhs(VirtualRegister value, Functor func) |
10091 | { |
10092 | if (isWide()) |
10093 | setRhs<OpcodeSize::Wide>(value, func); |
10094 | else |
10095 | setRhs<OpcodeSize::Narrow>(value, func); |
10096 | } |
10097 | |
10098 | template <OpcodeSize size, typename Functor> |
10099 | void setRhs(VirtualRegister value, Functor func) |
10100 | { |
10101 | if (!Fits<VirtualRegister, size>::check(value)) |
10102 | value = func(); |
10103 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
10104 | *stream = Fits<VirtualRegister, size>::convert(value); |
10105 | } |
10106 | |
10107 | VirtualRegister m_dst; |
10108 | VirtualRegister m_lhs; |
10109 | VirtualRegister m_rhs; |
10110 | }; |
10111 | |
10112 | struct OpNstricteq : public Instruction { |
10113 | static constexpr OpcodeID opcodeID = op_nstricteq; |
10114 | |
10115 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10116 | { |
10117 | |
10118 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
10119 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
10120 | } |
10121 | |
10122 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
10123 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10124 | { |
10125 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
10126 | if (shouldAssert == Assert) |
10127 | ASSERT(didEmit); |
10128 | return didEmit; |
10129 | } |
10130 | |
10131 | private: |
10132 | template<OpcodeSize size, bool recordOpcode> |
10133 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10134 | { |
10135 | if (size == OpcodeSize::Wide) |
10136 | gen->alignWideOpcode(); |
10137 | if (Fits<unsigned, size>::check(opcodeID) |
10138 | && Fits<VirtualRegister, size>::check(dst) |
10139 | && Fits<VirtualRegister, size>::check(lhs) |
10140 | && Fits<VirtualRegister, size>::check(rhs) |
10141 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
10142 | if (recordOpcode) |
10143 | gen->recordOpcode(opcodeID); |
10144 | if (size == OpcodeSize::Wide) |
10145 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
10146 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
10147 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
10148 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
10149 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
10150 | return true; |
10151 | } |
10152 | return false; |
10153 | } |
10154 | |
10155 | public: |
10156 | template<typename Block> |
10157 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
10158 | { |
10159 | dumper->printLocationAndOp(__location, &"*nstricteq" [!__isWide]); |
10160 | dumper->dumpOperand(m_dst, true); |
10161 | dumper->dumpOperand(m_lhs, false); |
10162 | dumper->dumpOperand(m_rhs, false); |
10163 | } |
10164 | |
10165 | OpNstricteq(const uint8_t* stream) |
10166 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
10167 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
10168 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
10169 | { |
10170 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10171 | } |
10172 | |
10173 | OpNstricteq(const uint32_t* stream) |
10174 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
10175 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
10176 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
10177 | { |
10178 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10179 | } |
10180 | |
10181 | static OpNstricteq decode(const uint8_t* stream) |
10182 | { |
10183 | if (*stream != op_wide) |
10184 | return { stream }; |
10185 | |
10186 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
10187 | return { wideStream }; |
10188 | } |
10189 | |
10190 | template<typename Functor> |
10191 | void setDst(VirtualRegister value, Functor func) |
10192 | { |
10193 | if (isWide()) |
10194 | setDst<OpcodeSize::Wide>(value, func); |
10195 | else |
10196 | setDst<OpcodeSize::Narrow>(value, func); |
10197 | } |
10198 | |
10199 | template <OpcodeSize size, typename Functor> |
10200 | void setDst(VirtualRegister value, Functor func) |
10201 | { |
10202 | if (!Fits<VirtualRegister, size>::check(value)) |
10203 | value = func(); |
10204 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
10205 | *stream = Fits<VirtualRegister, size>::convert(value); |
10206 | } |
10207 | |
10208 | template<typename Functor> |
10209 | void setLhs(VirtualRegister value, Functor func) |
10210 | { |
10211 | if (isWide()) |
10212 | setLhs<OpcodeSize::Wide>(value, func); |
10213 | else |
10214 | setLhs<OpcodeSize::Narrow>(value, func); |
10215 | } |
10216 | |
10217 | template <OpcodeSize size, typename Functor> |
10218 | void setLhs(VirtualRegister value, Functor func) |
10219 | { |
10220 | if (!Fits<VirtualRegister, size>::check(value)) |
10221 | value = func(); |
10222 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
10223 | *stream = Fits<VirtualRegister, size>::convert(value); |
10224 | } |
10225 | |
10226 | template<typename Functor> |
10227 | void setRhs(VirtualRegister value, Functor func) |
10228 | { |
10229 | if (isWide()) |
10230 | setRhs<OpcodeSize::Wide>(value, func); |
10231 | else |
10232 | setRhs<OpcodeSize::Narrow>(value, func); |
10233 | } |
10234 | |
10235 | template <OpcodeSize size, typename Functor> |
10236 | void setRhs(VirtualRegister value, Functor func) |
10237 | { |
10238 | if (!Fits<VirtualRegister, size>::check(value)) |
10239 | value = func(); |
10240 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
10241 | *stream = Fits<VirtualRegister, size>::convert(value); |
10242 | } |
10243 | |
10244 | VirtualRegister m_dst; |
10245 | VirtualRegister m_lhs; |
10246 | VirtualRegister m_rhs; |
10247 | }; |
10248 | |
10249 | struct OpLess : public Instruction { |
10250 | static constexpr OpcodeID opcodeID = op_less; |
10251 | |
10252 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10253 | { |
10254 | |
10255 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
10256 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
10257 | } |
10258 | |
10259 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
10260 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10261 | { |
10262 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
10263 | if (shouldAssert == Assert) |
10264 | ASSERT(didEmit); |
10265 | return didEmit; |
10266 | } |
10267 | |
10268 | private: |
10269 | template<OpcodeSize size, bool recordOpcode> |
10270 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10271 | { |
10272 | if (size == OpcodeSize::Wide) |
10273 | gen->alignWideOpcode(); |
10274 | if (Fits<unsigned, size>::check(opcodeID) |
10275 | && Fits<VirtualRegister, size>::check(dst) |
10276 | && Fits<VirtualRegister, size>::check(lhs) |
10277 | && Fits<VirtualRegister, size>::check(rhs) |
10278 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
10279 | if (recordOpcode) |
10280 | gen->recordOpcode(opcodeID); |
10281 | if (size == OpcodeSize::Wide) |
10282 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
10283 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
10284 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
10285 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
10286 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
10287 | return true; |
10288 | } |
10289 | return false; |
10290 | } |
10291 | |
10292 | public: |
10293 | template<typename Block> |
10294 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
10295 | { |
10296 | dumper->printLocationAndOp(__location, &"*less" [!__isWide]); |
10297 | dumper->dumpOperand(m_dst, true); |
10298 | dumper->dumpOperand(m_lhs, false); |
10299 | dumper->dumpOperand(m_rhs, false); |
10300 | } |
10301 | |
10302 | OpLess(const uint8_t* stream) |
10303 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
10304 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
10305 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
10306 | { |
10307 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10308 | } |
10309 | |
10310 | OpLess(const uint32_t* stream) |
10311 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
10312 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
10313 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
10314 | { |
10315 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10316 | } |
10317 | |
10318 | static OpLess decode(const uint8_t* stream) |
10319 | { |
10320 | if (*stream != op_wide) |
10321 | return { stream }; |
10322 | |
10323 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
10324 | return { wideStream }; |
10325 | } |
10326 | |
10327 | template<typename Functor> |
10328 | void setDst(VirtualRegister value, Functor func) |
10329 | { |
10330 | if (isWide()) |
10331 | setDst<OpcodeSize::Wide>(value, func); |
10332 | else |
10333 | setDst<OpcodeSize::Narrow>(value, func); |
10334 | } |
10335 | |
10336 | template <OpcodeSize size, typename Functor> |
10337 | void setDst(VirtualRegister value, Functor func) |
10338 | { |
10339 | if (!Fits<VirtualRegister, size>::check(value)) |
10340 | value = func(); |
10341 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
10342 | *stream = Fits<VirtualRegister, size>::convert(value); |
10343 | } |
10344 | |
10345 | template<typename Functor> |
10346 | void setLhs(VirtualRegister value, Functor func) |
10347 | { |
10348 | if (isWide()) |
10349 | setLhs<OpcodeSize::Wide>(value, func); |
10350 | else |
10351 | setLhs<OpcodeSize::Narrow>(value, func); |
10352 | } |
10353 | |
10354 | template <OpcodeSize size, typename Functor> |
10355 | void setLhs(VirtualRegister value, Functor func) |
10356 | { |
10357 | if (!Fits<VirtualRegister, size>::check(value)) |
10358 | value = func(); |
10359 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
10360 | *stream = Fits<VirtualRegister, size>::convert(value); |
10361 | } |
10362 | |
10363 | template<typename Functor> |
10364 | void setRhs(VirtualRegister value, Functor func) |
10365 | { |
10366 | if (isWide()) |
10367 | setRhs<OpcodeSize::Wide>(value, func); |
10368 | else |
10369 | setRhs<OpcodeSize::Narrow>(value, func); |
10370 | } |
10371 | |
10372 | template <OpcodeSize size, typename Functor> |
10373 | void setRhs(VirtualRegister value, Functor func) |
10374 | { |
10375 | if (!Fits<VirtualRegister, size>::check(value)) |
10376 | value = func(); |
10377 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
10378 | *stream = Fits<VirtualRegister, size>::convert(value); |
10379 | } |
10380 | |
10381 | VirtualRegister m_dst; |
10382 | VirtualRegister m_lhs; |
10383 | VirtualRegister m_rhs; |
10384 | }; |
10385 | |
10386 | struct OpLesseq : public Instruction { |
10387 | static constexpr OpcodeID opcodeID = op_lesseq; |
10388 | |
10389 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10390 | { |
10391 | |
10392 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
10393 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
10394 | } |
10395 | |
10396 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
10397 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10398 | { |
10399 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
10400 | if (shouldAssert == Assert) |
10401 | ASSERT(didEmit); |
10402 | return didEmit; |
10403 | } |
10404 | |
10405 | private: |
10406 | template<OpcodeSize size, bool recordOpcode> |
10407 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10408 | { |
10409 | if (size == OpcodeSize::Wide) |
10410 | gen->alignWideOpcode(); |
10411 | if (Fits<unsigned, size>::check(opcodeID) |
10412 | && Fits<VirtualRegister, size>::check(dst) |
10413 | && Fits<VirtualRegister, size>::check(lhs) |
10414 | && Fits<VirtualRegister, size>::check(rhs) |
10415 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
10416 | if (recordOpcode) |
10417 | gen->recordOpcode(opcodeID); |
10418 | if (size == OpcodeSize::Wide) |
10419 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
10420 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
10421 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
10422 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
10423 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
10424 | return true; |
10425 | } |
10426 | return false; |
10427 | } |
10428 | |
10429 | public: |
10430 | template<typename Block> |
10431 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
10432 | { |
10433 | dumper->printLocationAndOp(__location, &"*lesseq" [!__isWide]); |
10434 | dumper->dumpOperand(m_dst, true); |
10435 | dumper->dumpOperand(m_lhs, false); |
10436 | dumper->dumpOperand(m_rhs, false); |
10437 | } |
10438 | |
10439 | OpLesseq(const uint8_t* stream) |
10440 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
10441 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
10442 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
10443 | { |
10444 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10445 | } |
10446 | |
10447 | OpLesseq(const uint32_t* stream) |
10448 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
10449 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
10450 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
10451 | { |
10452 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10453 | } |
10454 | |
10455 | static OpLesseq decode(const uint8_t* stream) |
10456 | { |
10457 | if (*stream != op_wide) |
10458 | return { stream }; |
10459 | |
10460 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
10461 | return { wideStream }; |
10462 | } |
10463 | |
10464 | template<typename Functor> |
10465 | void setDst(VirtualRegister value, Functor func) |
10466 | { |
10467 | if (isWide()) |
10468 | setDst<OpcodeSize::Wide>(value, func); |
10469 | else |
10470 | setDst<OpcodeSize::Narrow>(value, func); |
10471 | } |
10472 | |
10473 | template <OpcodeSize size, typename Functor> |
10474 | void setDst(VirtualRegister value, Functor func) |
10475 | { |
10476 | if (!Fits<VirtualRegister, size>::check(value)) |
10477 | value = func(); |
10478 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
10479 | *stream = Fits<VirtualRegister, size>::convert(value); |
10480 | } |
10481 | |
10482 | template<typename Functor> |
10483 | void setLhs(VirtualRegister value, Functor func) |
10484 | { |
10485 | if (isWide()) |
10486 | setLhs<OpcodeSize::Wide>(value, func); |
10487 | else |
10488 | setLhs<OpcodeSize::Narrow>(value, func); |
10489 | } |
10490 | |
10491 | template <OpcodeSize size, typename Functor> |
10492 | void setLhs(VirtualRegister value, Functor func) |
10493 | { |
10494 | if (!Fits<VirtualRegister, size>::check(value)) |
10495 | value = func(); |
10496 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
10497 | *stream = Fits<VirtualRegister, size>::convert(value); |
10498 | } |
10499 | |
10500 | template<typename Functor> |
10501 | void setRhs(VirtualRegister value, Functor func) |
10502 | { |
10503 | if (isWide()) |
10504 | setRhs<OpcodeSize::Wide>(value, func); |
10505 | else |
10506 | setRhs<OpcodeSize::Narrow>(value, func); |
10507 | } |
10508 | |
10509 | template <OpcodeSize size, typename Functor> |
10510 | void setRhs(VirtualRegister value, Functor func) |
10511 | { |
10512 | if (!Fits<VirtualRegister, size>::check(value)) |
10513 | value = func(); |
10514 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
10515 | *stream = Fits<VirtualRegister, size>::convert(value); |
10516 | } |
10517 | |
10518 | VirtualRegister m_dst; |
10519 | VirtualRegister m_lhs; |
10520 | VirtualRegister m_rhs; |
10521 | }; |
10522 | |
10523 | struct OpGreater : public Instruction { |
10524 | static constexpr OpcodeID opcodeID = op_greater; |
10525 | |
10526 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10527 | { |
10528 | |
10529 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
10530 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
10531 | } |
10532 | |
10533 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
10534 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10535 | { |
10536 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
10537 | if (shouldAssert == Assert) |
10538 | ASSERT(didEmit); |
10539 | return didEmit; |
10540 | } |
10541 | |
10542 | private: |
10543 | template<OpcodeSize size, bool recordOpcode> |
10544 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10545 | { |
10546 | if (size == OpcodeSize::Wide) |
10547 | gen->alignWideOpcode(); |
10548 | if (Fits<unsigned, size>::check(opcodeID) |
10549 | && Fits<VirtualRegister, size>::check(dst) |
10550 | && Fits<VirtualRegister, size>::check(lhs) |
10551 | && Fits<VirtualRegister, size>::check(rhs) |
10552 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
10553 | if (recordOpcode) |
10554 | gen->recordOpcode(opcodeID); |
10555 | if (size == OpcodeSize::Wide) |
10556 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
10557 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
10558 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
10559 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
10560 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
10561 | return true; |
10562 | } |
10563 | return false; |
10564 | } |
10565 | |
10566 | public: |
10567 | template<typename Block> |
10568 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
10569 | { |
10570 | dumper->printLocationAndOp(__location, &"*greater" [!__isWide]); |
10571 | dumper->dumpOperand(m_dst, true); |
10572 | dumper->dumpOperand(m_lhs, false); |
10573 | dumper->dumpOperand(m_rhs, false); |
10574 | } |
10575 | |
10576 | OpGreater(const uint8_t* stream) |
10577 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
10578 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
10579 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
10580 | { |
10581 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10582 | } |
10583 | |
10584 | OpGreater(const uint32_t* stream) |
10585 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
10586 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
10587 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
10588 | { |
10589 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10590 | } |
10591 | |
10592 | static OpGreater decode(const uint8_t* stream) |
10593 | { |
10594 | if (*stream != op_wide) |
10595 | return { stream }; |
10596 | |
10597 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
10598 | return { wideStream }; |
10599 | } |
10600 | |
10601 | template<typename Functor> |
10602 | void setDst(VirtualRegister value, Functor func) |
10603 | { |
10604 | if (isWide()) |
10605 | setDst<OpcodeSize::Wide>(value, func); |
10606 | else |
10607 | setDst<OpcodeSize::Narrow>(value, func); |
10608 | } |
10609 | |
10610 | template <OpcodeSize size, typename Functor> |
10611 | void setDst(VirtualRegister value, Functor func) |
10612 | { |
10613 | if (!Fits<VirtualRegister, size>::check(value)) |
10614 | value = func(); |
10615 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
10616 | *stream = Fits<VirtualRegister, size>::convert(value); |
10617 | } |
10618 | |
10619 | template<typename Functor> |
10620 | void setLhs(VirtualRegister value, Functor func) |
10621 | { |
10622 | if (isWide()) |
10623 | setLhs<OpcodeSize::Wide>(value, func); |
10624 | else |
10625 | setLhs<OpcodeSize::Narrow>(value, func); |
10626 | } |
10627 | |
10628 | template <OpcodeSize size, typename Functor> |
10629 | void setLhs(VirtualRegister value, Functor func) |
10630 | { |
10631 | if (!Fits<VirtualRegister, size>::check(value)) |
10632 | value = func(); |
10633 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
10634 | *stream = Fits<VirtualRegister, size>::convert(value); |
10635 | } |
10636 | |
10637 | template<typename Functor> |
10638 | void setRhs(VirtualRegister value, Functor func) |
10639 | { |
10640 | if (isWide()) |
10641 | setRhs<OpcodeSize::Wide>(value, func); |
10642 | else |
10643 | setRhs<OpcodeSize::Narrow>(value, func); |
10644 | } |
10645 | |
10646 | template <OpcodeSize size, typename Functor> |
10647 | void setRhs(VirtualRegister value, Functor func) |
10648 | { |
10649 | if (!Fits<VirtualRegister, size>::check(value)) |
10650 | value = func(); |
10651 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
10652 | *stream = Fits<VirtualRegister, size>::convert(value); |
10653 | } |
10654 | |
10655 | VirtualRegister m_dst; |
10656 | VirtualRegister m_lhs; |
10657 | VirtualRegister m_rhs; |
10658 | }; |
10659 | |
10660 | struct OpGreatereq : public Instruction { |
10661 | static constexpr OpcodeID opcodeID = op_greatereq; |
10662 | |
10663 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10664 | { |
10665 | |
10666 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
10667 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
10668 | } |
10669 | |
10670 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
10671 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10672 | { |
10673 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
10674 | if (shouldAssert == Assert) |
10675 | ASSERT(didEmit); |
10676 | return didEmit; |
10677 | } |
10678 | |
10679 | private: |
10680 | template<OpcodeSize size, bool recordOpcode> |
10681 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10682 | { |
10683 | if (size == OpcodeSize::Wide) |
10684 | gen->alignWideOpcode(); |
10685 | if (Fits<unsigned, size>::check(opcodeID) |
10686 | && Fits<VirtualRegister, size>::check(dst) |
10687 | && Fits<VirtualRegister, size>::check(lhs) |
10688 | && Fits<VirtualRegister, size>::check(rhs) |
10689 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
10690 | if (recordOpcode) |
10691 | gen->recordOpcode(opcodeID); |
10692 | if (size == OpcodeSize::Wide) |
10693 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
10694 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
10695 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
10696 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
10697 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
10698 | return true; |
10699 | } |
10700 | return false; |
10701 | } |
10702 | |
10703 | public: |
10704 | template<typename Block> |
10705 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
10706 | { |
10707 | dumper->printLocationAndOp(__location, &"*greatereq" [!__isWide]); |
10708 | dumper->dumpOperand(m_dst, true); |
10709 | dumper->dumpOperand(m_lhs, false); |
10710 | dumper->dumpOperand(m_rhs, false); |
10711 | } |
10712 | |
10713 | OpGreatereq(const uint8_t* stream) |
10714 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
10715 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
10716 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
10717 | { |
10718 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10719 | } |
10720 | |
10721 | OpGreatereq(const uint32_t* stream) |
10722 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
10723 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
10724 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
10725 | { |
10726 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10727 | } |
10728 | |
10729 | static OpGreatereq decode(const uint8_t* stream) |
10730 | { |
10731 | if (*stream != op_wide) |
10732 | return { stream }; |
10733 | |
10734 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
10735 | return { wideStream }; |
10736 | } |
10737 | |
10738 | template<typename Functor> |
10739 | void setDst(VirtualRegister value, Functor func) |
10740 | { |
10741 | if (isWide()) |
10742 | setDst<OpcodeSize::Wide>(value, func); |
10743 | else |
10744 | setDst<OpcodeSize::Narrow>(value, func); |
10745 | } |
10746 | |
10747 | template <OpcodeSize size, typename Functor> |
10748 | void setDst(VirtualRegister value, Functor func) |
10749 | { |
10750 | if (!Fits<VirtualRegister, size>::check(value)) |
10751 | value = func(); |
10752 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
10753 | *stream = Fits<VirtualRegister, size>::convert(value); |
10754 | } |
10755 | |
10756 | template<typename Functor> |
10757 | void setLhs(VirtualRegister value, Functor func) |
10758 | { |
10759 | if (isWide()) |
10760 | setLhs<OpcodeSize::Wide>(value, func); |
10761 | else |
10762 | setLhs<OpcodeSize::Narrow>(value, func); |
10763 | } |
10764 | |
10765 | template <OpcodeSize size, typename Functor> |
10766 | void setLhs(VirtualRegister value, Functor func) |
10767 | { |
10768 | if (!Fits<VirtualRegister, size>::check(value)) |
10769 | value = func(); |
10770 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
10771 | *stream = Fits<VirtualRegister, size>::convert(value); |
10772 | } |
10773 | |
10774 | template<typename Functor> |
10775 | void setRhs(VirtualRegister value, Functor func) |
10776 | { |
10777 | if (isWide()) |
10778 | setRhs<OpcodeSize::Wide>(value, func); |
10779 | else |
10780 | setRhs<OpcodeSize::Narrow>(value, func); |
10781 | } |
10782 | |
10783 | template <OpcodeSize size, typename Functor> |
10784 | void setRhs(VirtualRegister value, Functor func) |
10785 | { |
10786 | if (!Fits<VirtualRegister, size>::check(value)) |
10787 | value = func(); |
10788 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
10789 | *stream = Fits<VirtualRegister, size>::convert(value); |
10790 | } |
10791 | |
10792 | VirtualRegister m_dst; |
10793 | VirtualRegister m_lhs; |
10794 | VirtualRegister m_rhs; |
10795 | }; |
10796 | |
10797 | struct OpBelow : public Instruction { |
10798 | static constexpr OpcodeID opcodeID = op_below; |
10799 | |
10800 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10801 | { |
10802 | |
10803 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
10804 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
10805 | } |
10806 | |
10807 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
10808 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10809 | { |
10810 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
10811 | if (shouldAssert == Assert) |
10812 | ASSERT(didEmit); |
10813 | return didEmit; |
10814 | } |
10815 | |
10816 | private: |
10817 | template<OpcodeSize size, bool recordOpcode> |
10818 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10819 | { |
10820 | if (size == OpcodeSize::Wide) |
10821 | gen->alignWideOpcode(); |
10822 | if (Fits<unsigned, size>::check(opcodeID) |
10823 | && Fits<VirtualRegister, size>::check(dst) |
10824 | && Fits<VirtualRegister, size>::check(lhs) |
10825 | && Fits<VirtualRegister, size>::check(rhs) |
10826 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
10827 | if (recordOpcode) |
10828 | gen->recordOpcode(opcodeID); |
10829 | if (size == OpcodeSize::Wide) |
10830 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
10831 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
10832 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
10833 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
10834 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
10835 | return true; |
10836 | } |
10837 | return false; |
10838 | } |
10839 | |
10840 | public: |
10841 | template<typename Block> |
10842 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
10843 | { |
10844 | dumper->printLocationAndOp(__location, &"*below" [!__isWide]); |
10845 | dumper->dumpOperand(m_dst, true); |
10846 | dumper->dumpOperand(m_lhs, false); |
10847 | dumper->dumpOperand(m_rhs, false); |
10848 | } |
10849 | |
10850 | OpBelow(const uint8_t* stream) |
10851 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
10852 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
10853 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
10854 | { |
10855 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10856 | } |
10857 | |
10858 | OpBelow(const uint32_t* stream) |
10859 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
10860 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
10861 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
10862 | { |
10863 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10864 | } |
10865 | |
10866 | static OpBelow decode(const uint8_t* stream) |
10867 | { |
10868 | if (*stream != op_wide) |
10869 | return { stream }; |
10870 | |
10871 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
10872 | return { wideStream }; |
10873 | } |
10874 | |
10875 | template<typename Functor> |
10876 | void setDst(VirtualRegister value, Functor func) |
10877 | { |
10878 | if (isWide()) |
10879 | setDst<OpcodeSize::Wide>(value, func); |
10880 | else |
10881 | setDst<OpcodeSize::Narrow>(value, func); |
10882 | } |
10883 | |
10884 | template <OpcodeSize size, typename Functor> |
10885 | void setDst(VirtualRegister value, Functor func) |
10886 | { |
10887 | if (!Fits<VirtualRegister, size>::check(value)) |
10888 | value = func(); |
10889 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
10890 | *stream = Fits<VirtualRegister, size>::convert(value); |
10891 | } |
10892 | |
10893 | template<typename Functor> |
10894 | void setLhs(VirtualRegister value, Functor func) |
10895 | { |
10896 | if (isWide()) |
10897 | setLhs<OpcodeSize::Wide>(value, func); |
10898 | else |
10899 | setLhs<OpcodeSize::Narrow>(value, func); |
10900 | } |
10901 | |
10902 | template <OpcodeSize size, typename Functor> |
10903 | void setLhs(VirtualRegister value, Functor func) |
10904 | { |
10905 | if (!Fits<VirtualRegister, size>::check(value)) |
10906 | value = func(); |
10907 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
10908 | *stream = Fits<VirtualRegister, size>::convert(value); |
10909 | } |
10910 | |
10911 | template<typename Functor> |
10912 | void setRhs(VirtualRegister value, Functor func) |
10913 | { |
10914 | if (isWide()) |
10915 | setRhs<OpcodeSize::Wide>(value, func); |
10916 | else |
10917 | setRhs<OpcodeSize::Narrow>(value, func); |
10918 | } |
10919 | |
10920 | template <OpcodeSize size, typename Functor> |
10921 | void setRhs(VirtualRegister value, Functor func) |
10922 | { |
10923 | if (!Fits<VirtualRegister, size>::check(value)) |
10924 | value = func(); |
10925 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
10926 | *stream = Fits<VirtualRegister, size>::convert(value); |
10927 | } |
10928 | |
10929 | VirtualRegister m_dst; |
10930 | VirtualRegister m_lhs; |
10931 | VirtualRegister m_rhs; |
10932 | }; |
10933 | |
10934 | struct OpBeloweq : public Instruction { |
10935 | static constexpr OpcodeID opcodeID = op_beloweq; |
10936 | |
10937 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10938 | { |
10939 | |
10940 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
10941 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
10942 | } |
10943 | |
10944 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
10945 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10946 | { |
10947 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
10948 | if (shouldAssert == Assert) |
10949 | ASSERT(didEmit); |
10950 | return didEmit; |
10951 | } |
10952 | |
10953 | private: |
10954 | template<OpcodeSize size, bool recordOpcode> |
10955 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
10956 | { |
10957 | if (size == OpcodeSize::Wide) |
10958 | gen->alignWideOpcode(); |
10959 | if (Fits<unsigned, size>::check(opcodeID) |
10960 | && Fits<VirtualRegister, size>::check(dst) |
10961 | && Fits<VirtualRegister, size>::check(lhs) |
10962 | && Fits<VirtualRegister, size>::check(rhs) |
10963 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
10964 | if (recordOpcode) |
10965 | gen->recordOpcode(opcodeID); |
10966 | if (size == OpcodeSize::Wide) |
10967 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
10968 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
10969 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
10970 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
10971 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
10972 | return true; |
10973 | } |
10974 | return false; |
10975 | } |
10976 | |
10977 | public: |
10978 | template<typename Block> |
10979 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
10980 | { |
10981 | dumper->printLocationAndOp(__location, &"*beloweq" [!__isWide]); |
10982 | dumper->dumpOperand(m_dst, true); |
10983 | dumper->dumpOperand(m_lhs, false); |
10984 | dumper->dumpOperand(m_rhs, false); |
10985 | } |
10986 | |
10987 | OpBeloweq(const uint8_t* stream) |
10988 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
10989 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
10990 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
10991 | { |
10992 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
10993 | } |
10994 | |
10995 | OpBeloweq(const uint32_t* stream) |
10996 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
10997 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
10998 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
10999 | { |
11000 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11001 | } |
11002 | |
11003 | static OpBeloweq decode(const uint8_t* stream) |
11004 | { |
11005 | if (*stream != op_wide) |
11006 | return { stream }; |
11007 | |
11008 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
11009 | return { wideStream }; |
11010 | } |
11011 | |
11012 | template<typename Functor> |
11013 | void setDst(VirtualRegister value, Functor func) |
11014 | { |
11015 | if (isWide()) |
11016 | setDst<OpcodeSize::Wide>(value, func); |
11017 | else |
11018 | setDst<OpcodeSize::Narrow>(value, func); |
11019 | } |
11020 | |
11021 | template <OpcodeSize size, typename Functor> |
11022 | void setDst(VirtualRegister value, Functor func) |
11023 | { |
11024 | if (!Fits<VirtualRegister, size>::check(value)) |
11025 | value = func(); |
11026 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
11027 | *stream = Fits<VirtualRegister, size>::convert(value); |
11028 | } |
11029 | |
11030 | template<typename Functor> |
11031 | void setLhs(VirtualRegister value, Functor func) |
11032 | { |
11033 | if (isWide()) |
11034 | setLhs<OpcodeSize::Wide>(value, func); |
11035 | else |
11036 | setLhs<OpcodeSize::Narrow>(value, func); |
11037 | } |
11038 | |
11039 | template <OpcodeSize size, typename Functor> |
11040 | void setLhs(VirtualRegister value, Functor func) |
11041 | { |
11042 | if (!Fits<VirtualRegister, size>::check(value)) |
11043 | value = func(); |
11044 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
11045 | *stream = Fits<VirtualRegister, size>::convert(value); |
11046 | } |
11047 | |
11048 | template<typename Functor> |
11049 | void setRhs(VirtualRegister value, Functor func) |
11050 | { |
11051 | if (isWide()) |
11052 | setRhs<OpcodeSize::Wide>(value, func); |
11053 | else |
11054 | setRhs<OpcodeSize::Narrow>(value, func); |
11055 | } |
11056 | |
11057 | template <OpcodeSize size, typename Functor> |
11058 | void setRhs(VirtualRegister value, Functor func) |
11059 | { |
11060 | if (!Fits<VirtualRegister, size>::check(value)) |
11061 | value = func(); |
11062 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
11063 | *stream = Fits<VirtualRegister, size>::convert(value); |
11064 | } |
11065 | |
11066 | VirtualRegister m_dst; |
11067 | VirtualRegister m_lhs; |
11068 | VirtualRegister m_rhs; |
11069 | }; |
11070 | |
11071 | struct OpMod : public Instruction { |
11072 | static constexpr OpcodeID opcodeID = op_mod; |
11073 | |
11074 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11075 | { |
11076 | |
11077 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
11078 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
11079 | } |
11080 | |
11081 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
11082 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11083 | { |
11084 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
11085 | if (shouldAssert == Assert) |
11086 | ASSERT(didEmit); |
11087 | return didEmit; |
11088 | } |
11089 | |
11090 | private: |
11091 | template<OpcodeSize size, bool recordOpcode> |
11092 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11093 | { |
11094 | if (size == OpcodeSize::Wide) |
11095 | gen->alignWideOpcode(); |
11096 | if (Fits<unsigned, size>::check(opcodeID) |
11097 | && Fits<VirtualRegister, size>::check(dst) |
11098 | && Fits<VirtualRegister, size>::check(lhs) |
11099 | && Fits<VirtualRegister, size>::check(rhs) |
11100 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
11101 | if (recordOpcode) |
11102 | gen->recordOpcode(opcodeID); |
11103 | if (size == OpcodeSize::Wide) |
11104 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
11105 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
11106 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
11107 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
11108 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
11109 | return true; |
11110 | } |
11111 | return false; |
11112 | } |
11113 | |
11114 | public: |
11115 | template<typename Block> |
11116 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
11117 | { |
11118 | dumper->printLocationAndOp(__location, &"*mod" [!__isWide]); |
11119 | dumper->dumpOperand(m_dst, true); |
11120 | dumper->dumpOperand(m_lhs, false); |
11121 | dumper->dumpOperand(m_rhs, false); |
11122 | } |
11123 | |
11124 | OpMod(const uint8_t* stream) |
11125 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
11126 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
11127 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
11128 | { |
11129 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11130 | } |
11131 | |
11132 | OpMod(const uint32_t* stream) |
11133 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
11134 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
11135 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
11136 | { |
11137 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11138 | } |
11139 | |
11140 | static OpMod decode(const uint8_t* stream) |
11141 | { |
11142 | if (*stream != op_wide) |
11143 | return { stream }; |
11144 | |
11145 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
11146 | return { wideStream }; |
11147 | } |
11148 | |
11149 | template<typename Functor> |
11150 | void setDst(VirtualRegister value, Functor func) |
11151 | { |
11152 | if (isWide()) |
11153 | setDst<OpcodeSize::Wide>(value, func); |
11154 | else |
11155 | setDst<OpcodeSize::Narrow>(value, func); |
11156 | } |
11157 | |
11158 | template <OpcodeSize size, typename Functor> |
11159 | void setDst(VirtualRegister value, Functor func) |
11160 | { |
11161 | if (!Fits<VirtualRegister, size>::check(value)) |
11162 | value = func(); |
11163 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
11164 | *stream = Fits<VirtualRegister, size>::convert(value); |
11165 | } |
11166 | |
11167 | template<typename Functor> |
11168 | void setLhs(VirtualRegister value, Functor func) |
11169 | { |
11170 | if (isWide()) |
11171 | setLhs<OpcodeSize::Wide>(value, func); |
11172 | else |
11173 | setLhs<OpcodeSize::Narrow>(value, func); |
11174 | } |
11175 | |
11176 | template <OpcodeSize size, typename Functor> |
11177 | void setLhs(VirtualRegister value, Functor func) |
11178 | { |
11179 | if (!Fits<VirtualRegister, size>::check(value)) |
11180 | value = func(); |
11181 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
11182 | *stream = Fits<VirtualRegister, size>::convert(value); |
11183 | } |
11184 | |
11185 | template<typename Functor> |
11186 | void setRhs(VirtualRegister value, Functor func) |
11187 | { |
11188 | if (isWide()) |
11189 | setRhs<OpcodeSize::Wide>(value, func); |
11190 | else |
11191 | setRhs<OpcodeSize::Narrow>(value, func); |
11192 | } |
11193 | |
11194 | template <OpcodeSize size, typename Functor> |
11195 | void setRhs(VirtualRegister value, Functor func) |
11196 | { |
11197 | if (!Fits<VirtualRegister, size>::check(value)) |
11198 | value = func(); |
11199 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
11200 | *stream = Fits<VirtualRegister, size>::convert(value); |
11201 | } |
11202 | |
11203 | VirtualRegister m_dst; |
11204 | VirtualRegister m_lhs; |
11205 | VirtualRegister m_rhs; |
11206 | }; |
11207 | |
11208 | struct OpPow : public Instruction { |
11209 | static constexpr OpcodeID opcodeID = op_pow; |
11210 | |
11211 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11212 | { |
11213 | |
11214 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
11215 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
11216 | } |
11217 | |
11218 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
11219 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11220 | { |
11221 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
11222 | if (shouldAssert == Assert) |
11223 | ASSERT(didEmit); |
11224 | return didEmit; |
11225 | } |
11226 | |
11227 | private: |
11228 | template<OpcodeSize size, bool recordOpcode> |
11229 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11230 | { |
11231 | if (size == OpcodeSize::Wide) |
11232 | gen->alignWideOpcode(); |
11233 | if (Fits<unsigned, size>::check(opcodeID) |
11234 | && Fits<VirtualRegister, size>::check(dst) |
11235 | && Fits<VirtualRegister, size>::check(lhs) |
11236 | && Fits<VirtualRegister, size>::check(rhs) |
11237 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
11238 | if (recordOpcode) |
11239 | gen->recordOpcode(opcodeID); |
11240 | if (size == OpcodeSize::Wide) |
11241 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
11242 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
11243 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
11244 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
11245 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
11246 | return true; |
11247 | } |
11248 | return false; |
11249 | } |
11250 | |
11251 | public: |
11252 | template<typename Block> |
11253 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
11254 | { |
11255 | dumper->printLocationAndOp(__location, &"*pow" [!__isWide]); |
11256 | dumper->dumpOperand(m_dst, true); |
11257 | dumper->dumpOperand(m_lhs, false); |
11258 | dumper->dumpOperand(m_rhs, false); |
11259 | } |
11260 | |
11261 | OpPow(const uint8_t* stream) |
11262 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
11263 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
11264 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
11265 | { |
11266 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11267 | } |
11268 | |
11269 | OpPow(const uint32_t* stream) |
11270 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
11271 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
11272 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
11273 | { |
11274 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11275 | } |
11276 | |
11277 | static OpPow decode(const uint8_t* stream) |
11278 | { |
11279 | if (*stream != op_wide) |
11280 | return { stream }; |
11281 | |
11282 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
11283 | return { wideStream }; |
11284 | } |
11285 | |
11286 | template<typename Functor> |
11287 | void setDst(VirtualRegister value, Functor func) |
11288 | { |
11289 | if (isWide()) |
11290 | setDst<OpcodeSize::Wide>(value, func); |
11291 | else |
11292 | setDst<OpcodeSize::Narrow>(value, func); |
11293 | } |
11294 | |
11295 | template <OpcodeSize size, typename Functor> |
11296 | void setDst(VirtualRegister value, Functor func) |
11297 | { |
11298 | if (!Fits<VirtualRegister, size>::check(value)) |
11299 | value = func(); |
11300 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
11301 | *stream = Fits<VirtualRegister, size>::convert(value); |
11302 | } |
11303 | |
11304 | template<typename Functor> |
11305 | void setLhs(VirtualRegister value, Functor func) |
11306 | { |
11307 | if (isWide()) |
11308 | setLhs<OpcodeSize::Wide>(value, func); |
11309 | else |
11310 | setLhs<OpcodeSize::Narrow>(value, func); |
11311 | } |
11312 | |
11313 | template <OpcodeSize size, typename Functor> |
11314 | void setLhs(VirtualRegister value, Functor func) |
11315 | { |
11316 | if (!Fits<VirtualRegister, size>::check(value)) |
11317 | value = func(); |
11318 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
11319 | *stream = Fits<VirtualRegister, size>::convert(value); |
11320 | } |
11321 | |
11322 | template<typename Functor> |
11323 | void setRhs(VirtualRegister value, Functor func) |
11324 | { |
11325 | if (isWide()) |
11326 | setRhs<OpcodeSize::Wide>(value, func); |
11327 | else |
11328 | setRhs<OpcodeSize::Narrow>(value, func); |
11329 | } |
11330 | |
11331 | template <OpcodeSize size, typename Functor> |
11332 | void setRhs(VirtualRegister value, Functor func) |
11333 | { |
11334 | if (!Fits<VirtualRegister, size>::check(value)) |
11335 | value = func(); |
11336 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
11337 | *stream = Fits<VirtualRegister, size>::convert(value); |
11338 | } |
11339 | |
11340 | VirtualRegister m_dst; |
11341 | VirtualRegister m_lhs; |
11342 | VirtualRegister m_rhs; |
11343 | }; |
11344 | |
11345 | struct OpLshift : public Instruction { |
11346 | static constexpr OpcodeID opcodeID = op_lshift; |
11347 | |
11348 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11349 | { |
11350 | |
11351 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
11352 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
11353 | } |
11354 | |
11355 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
11356 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11357 | { |
11358 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
11359 | if (shouldAssert == Assert) |
11360 | ASSERT(didEmit); |
11361 | return didEmit; |
11362 | } |
11363 | |
11364 | private: |
11365 | template<OpcodeSize size, bool recordOpcode> |
11366 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11367 | { |
11368 | if (size == OpcodeSize::Wide) |
11369 | gen->alignWideOpcode(); |
11370 | if (Fits<unsigned, size>::check(opcodeID) |
11371 | && Fits<VirtualRegister, size>::check(dst) |
11372 | && Fits<VirtualRegister, size>::check(lhs) |
11373 | && Fits<VirtualRegister, size>::check(rhs) |
11374 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
11375 | if (recordOpcode) |
11376 | gen->recordOpcode(opcodeID); |
11377 | if (size == OpcodeSize::Wide) |
11378 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
11379 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
11380 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
11381 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
11382 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
11383 | return true; |
11384 | } |
11385 | return false; |
11386 | } |
11387 | |
11388 | public: |
11389 | template<typename Block> |
11390 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
11391 | { |
11392 | dumper->printLocationAndOp(__location, &"*lshift" [!__isWide]); |
11393 | dumper->dumpOperand(m_dst, true); |
11394 | dumper->dumpOperand(m_lhs, false); |
11395 | dumper->dumpOperand(m_rhs, false); |
11396 | } |
11397 | |
11398 | OpLshift(const uint8_t* stream) |
11399 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
11400 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
11401 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
11402 | { |
11403 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11404 | } |
11405 | |
11406 | OpLshift(const uint32_t* stream) |
11407 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
11408 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
11409 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
11410 | { |
11411 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11412 | } |
11413 | |
11414 | static OpLshift decode(const uint8_t* stream) |
11415 | { |
11416 | if (*stream != op_wide) |
11417 | return { stream }; |
11418 | |
11419 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
11420 | return { wideStream }; |
11421 | } |
11422 | |
11423 | template<typename Functor> |
11424 | void setDst(VirtualRegister value, Functor func) |
11425 | { |
11426 | if (isWide()) |
11427 | setDst<OpcodeSize::Wide>(value, func); |
11428 | else |
11429 | setDst<OpcodeSize::Narrow>(value, func); |
11430 | } |
11431 | |
11432 | template <OpcodeSize size, typename Functor> |
11433 | void setDst(VirtualRegister value, Functor func) |
11434 | { |
11435 | if (!Fits<VirtualRegister, size>::check(value)) |
11436 | value = func(); |
11437 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
11438 | *stream = Fits<VirtualRegister, size>::convert(value); |
11439 | } |
11440 | |
11441 | template<typename Functor> |
11442 | void setLhs(VirtualRegister value, Functor func) |
11443 | { |
11444 | if (isWide()) |
11445 | setLhs<OpcodeSize::Wide>(value, func); |
11446 | else |
11447 | setLhs<OpcodeSize::Narrow>(value, func); |
11448 | } |
11449 | |
11450 | template <OpcodeSize size, typename Functor> |
11451 | void setLhs(VirtualRegister value, Functor func) |
11452 | { |
11453 | if (!Fits<VirtualRegister, size>::check(value)) |
11454 | value = func(); |
11455 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
11456 | *stream = Fits<VirtualRegister, size>::convert(value); |
11457 | } |
11458 | |
11459 | template<typename Functor> |
11460 | void setRhs(VirtualRegister value, Functor func) |
11461 | { |
11462 | if (isWide()) |
11463 | setRhs<OpcodeSize::Wide>(value, func); |
11464 | else |
11465 | setRhs<OpcodeSize::Narrow>(value, func); |
11466 | } |
11467 | |
11468 | template <OpcodeSize size, typename Functor> |
11469 | void setRhs(VirtualRegister value, Functor func) |
11470 | { |
11471 | if (!Fits<VirtualRegister, size>::check(value)) |
11472 | value = func(); |
11473 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
11474 | *stream = Fits<VirtualRegister, size>::convert(value); |
11475 | } |
11476 | |
11477 | VirtualRegister m_dst; |
11478 | VirtualRegister m_lhs; |
11479 | VirtualRegister m_rhs; |
11480 | }; |
11481 | |
11482 | struct OpRshift : public Instruction { |
11483 | static constexpr OpcodeID opcodeID = op_rshift; |
11484 | |
11485 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11486 | { |
11487 | |
11488 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
11489 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
11490 | } |
11491 | |
11492 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
11493 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11494 | { |
11495 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
11496 | if (shouldAssert == Assert) |
11497 | ASSERT(didEmit); |
11498 | return didEmit; |
11499 | } |
11500 | |
11501 | private: |
11502 | template<OpcodeSize size, bool recordOpcode> |
11503 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11504 | { |
11505 | if (size == OpcodeSize::Wide) |
11506 | gen->alignWideOpcode(); |
11507 | if (Fits<unsigned, size>::check(opcodeID) |
11508 | && Fits<VirtualRegister, size>::check(dst) |
11509 | && Fits<VirtualRegister, size>::check(lhs) |
11510 | && Fits<VirtualRegister, size>::check(rhs) |
11511 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
11512 | if (recordOpcode) |
11513 | gen->recordOpcode(opcodeID); |
11514 | if (size == OpcodeSize::Wide) |
11515 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
11516 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
11517 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
11518 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
11519 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
11520 | return true; |
11521 | } |
11522 | return false; |
11523 | } |
11524 | |
11525 | public: |
11526 | template<typename Block> |
11527 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
11528 | { |
11529 | dumper->printLocationAndOp(__location, &"*rshift" [!__isWide]); |
11530 | dumper->dumpOperand(m_dst, true); |
11531 | dumper->dumpOperand(m_lhs, false); |
11532 | dumper->dumpOperand(m_rhs, false); |
11533 | } |
11534 | |
11535 | OpRshift(const uint8_t* stream) |
11536 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
11537 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
11538 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
11539 | { |
11540 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11541 | } |
11542 | |
11543 | OpRshift(const uint32_t* stream) |
11544 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
11545 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
11546 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
11547 | { |
11548 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11549 | } |
11550 | |
11551 | static OpRshift decode(const uint8_t* stream) |
11552 | { |
11553 | if (*stream != op_wide) |
11554 | return { stream }; |
11555 | |
11556 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
11557 | return { wideStream }; |
11558 | } |
11559 | |
11560 | template<typename Functor> |
11561 | void setDst(VirtualRegister value, Functor func) |
11562 | { |
11563 | if (isWide()) |
11564 | setDst<OpcodeSize::Wide>(value, func); |
11565 | else |
11566 | setDst<OpcodeSize::Narrow>(value, func); |
11567 | } |
11568 | |
11569 | template <OpcodeSize size, typename Functor> |
11570 | void setDst(VirtualRegister value, Functor func) |
11571 | { |
11572 | if (!Fits<VirtualRegister, size>::check(value)) |
11573 | value = func(); |
11574 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
11575 | *stream = Fits<VirtualRegister, size>::convert(value); |
11576 | } |
11577 | |
11578 | template<typename Functor> |
11579 | void setLhs(VirtualRegister value, Functor func) |
11580 | { |
11581 | if (isWide()) |
11582 | setLhs<OpcodeSize::Wide>(value, func); |
11583 | else |
11584 | setLhs<OpcodeSize::Narrow>(value, func); |
11585 | } |
11586 | |
11587 | template <OpcodeSize size, typename Functor> |
11588 | void setLhs(VirtualRegister value, Functor func) |
11589 | { |
11590 | if (!Fits<VirtualRegister, size>::check(value)) |
11591 | value = func(); |
11592 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
11593 | *stream = Fits<VirtualRegister, size>::convert(value); |
11594 | } |
11595 | |
11596 | template<typename Functor> |
11597 | void setRhs(VirtualRegister value, Functor func) |
11598 | { |
11599 | if (isWide()) |
11600 | setRhs<OpcodeSize::Wide>(value, func); |
11601 | else |
11602 | setRhs<OpcodeSize::Narrow>(value, func); |
11603 | } |
11604 | |
11605 | template <OpcodeSize size, typename Functor> |
11606 | void setRhs(VirtualRegister value, Functor func) |
11607 | { |
11608 | if (!Fits<VirtualRegister, size>::check(value)) |
11609 | value = func(); |
11610 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
11611 | *stream = Fits<VirtualRegister, size>::convert(value); |
11612 | } |
11613 | |
11614 | VirtualRegister m_dst; |
11615 | VirtualRegister m_lhs; |
11616 | VirtualRegister m_rhs; |
11617 | }; |
11618 | |
11619 | struct OpUrshift : public Instruction { |
11620 | static constexpr OpcodeID opcodeID = op_urshift; |
11621 | |
11622 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11623 | { |
11624 | |
11625 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs) |
11626 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, lhs, rhs); |
11627 | } |
11628 | |
11629 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
11630 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11631 | { |
11632 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs); |
11633 | if (shouldAssert == Assert) |
11634 | ASSERT(didEmit); |
11635 | return didEmit; |
11636 | } |
11637 | |
11638 | private: |
11639 | template<OpcodeSize size, bool recordOpcode> |
11640 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs) |
11641 | { |
11642 | if (size == OpcodeSize::Wide) |
11643 | gen->alignWideOpcode(); |
11644 | if (Fits<unsigned, size>::check(opcodeID) |
11645 | && Fits<VirtualRegister, size>::check(dst) |
11646 | && Fits<VirtualRegister, size>::check(lhs) |
11647 | && Fits<VirtualRegister, size>::check(rhs) |
11648 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
11649 | if (recordOpcode) |
11650 | gen->recordOpcode(opcodeID); |
11651 | if (size == OpcodeSize::Wide) |
11652 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
11653 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
11654 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
11655 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
11656 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
11657 | return true; |
11658 | } |
11659 | return false; |
11660 | } |
11661 | |
11662 | public: |
11663 | template<typename Block> |
11664 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
11665 | { |
11666 | dumper->printLocationAndOp(__location, &"*urshift" [!__isWide]); |
11667 | dumper->dumpOperand(m_dst, true); |
11668 | dumper->dumpOperand(m_lhs, false); |
11669 | dumper->dumpOperand(m_rhs, false); |
11670 | } |
11671 | |
11672 | OpUrshift(const uint8_t* stream) |
11673 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
11674 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
11675 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
11676 | { |
11677 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11678 | } |
11679 | |
11680 | OpUrshift(const uint32_t* stream) |
11681 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
11682 | , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
11683 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
11684 | { |
11685 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11686 | } |
11687 | |
11688 | static OpUrshift decode(const uint8_t* stream) |
11689 | { |
11690 | if (*stream != op_wide) |
11691 | return { stream }; |
11692 | |
11693 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
11694 | return { wideStream }; |
11695 | } |
11696 | |
11697 | template<typename Functor> |
11698 | void setDst(VirtualRegister value, Functor func) |
11699 | { |
11700 | if (isWide()) |
11701 | setDst<OpcodeSize::Wide>(value, func); |
11702 | else |
11703 | setDst<OpcodeSize::Narrow>(value, func); |
11704 | } |
11705 | |
11706 | template <OpcodeSize size, typename Functor> |
11707 | void setDst(VirtualRegister value, Functor func) |
11708 | { |
11709 | if (!Fits<VirtualRegister, size>::check(value)) |
11710 | value = func(); |
11711 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
11712 | *stream = Fits<VirtualRegister, size>::convert(value); |
11713 | } |
11714 | |
11715 | template<typename Functor> |
11716 | void setLhs(VirtualRegister value, Functor func) |
11717 | { |
11718 | if (isWide()) |
11719 | setLhs<OpcodeSize::Wide>(value, func); |
11720 | else |
11721 | setLhs<OpcodeSize::Narrow>(value, func); |
11722 | } |
11723 | |
11724 | template <OpcodeSize size, typename Functor> |
11725 | void setLhs(VirtualRegister value, Functor func) |
11726 | { |
11727 | if (!Fits<VirtualRegister, size>::check(value)) |
11728 | value = func(); |
11729 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
11730 | *stream = Fits<VirtualRegister, size>::convert(value); |
11731 | } |
11732 | |
11733 | template<typename Functor> |
11734 | void setRhs(VirtualRegister value, Functor func) |
11735 | { |
11736 | if (isWide()) |
11737 | setRhs<OpcodeSize::Wide>(value, func); |
11738 | else |
11739 | setRhs<OpcodeSize::Narrow>(value, func); |
11740 | } |
11741 | |
11742 | template <OpcodeSize size, typename Functor> |
11743 | void setRhs(VirtualRegister value, Functor func) |
11744 | { |
11745 | if (!Fits<VirtualRegister, size>::check(value)) |
11746 | value = func(); |
11747 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
11748 | *stream = Fits<VirtualRegister, size>::convert(value); |
11749 | } |
11750 | |
11751 | VirtualRegister m_dst; |
11752 | VirtualRegister m_lhs; |
11753 | VirtualRegister m_rhs; |
11754 | }; |
11755 | |
11756 | struct OpEqNull : public Instruction { |
11757 | static constexpr OpcodeID opcodeID = op_eq_null; |
11758 | |
11759 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
11760 | { |
11761 | |
11762 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand) |
11763 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand); |
11764 | } |
11765 | |
11766 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
11767 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
11768 | { |
11769 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand); |
11770 | if (shouldAssert == Assert) |
11771 | ASSERT(didEmit); |
11772 | return didEmit; |
11773 | } |
11774 | |
11775 | private: |
11776 | template<OpcodeSize size, bool recordOpcode> |
11777 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
11778 | { |
11779 | if (size == OpcodeSize::Wide) |
11780 | gen->alignWideOpcode(); |
11781 | if (Fits<unsigned, size>::check(opcodeID) |
11782 | && Fits<VirtualRegister, size>::check(dst) |
11783 | && Fits<VirtualRegister, size>::check(operand) |
11784 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
11785 | if (recordOpcode) |
11786 | gen->recordOpcode(opcodeID); |
11787 | if (size == OpcodeSize::Wide) |
11788 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
11789 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
11790 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
11791 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
11792 | return true; |
11793 | } |
11794 | return false; |
11795 | } |
11796 | |
11797 | public: |
11798 | template<typename Block> |
11799 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
11800 | { |
11801 | dumper->printLocationAndOp(__location, &"*eq_null" [!__isWide]); |
11802 | dumper->dumpOperand(m_dst, true); |
11803 | dumper->dumpOperand(m_operand, false); |
11804 | } |
11805 | |
11806 | OpEqNull(const uint8_t* stream) |
11807 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
11808 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
11809 | { |
11810 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11811 | } |
11812 | |
11813 | OpEqNull(const uint32_t* stream) |
11814 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
11815 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
11816 | { |
11817 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11818 | } |
11819 | |
11820 | static OpEqNull decode(const uint8_t* stream) |
11821 | { |
11822 | if (*stream != op_wide) |
11823 | return { stream }; |
11824 | |
11825 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
11826 | return { wideStream }; |
11827 | } |
11828 | |
11829 | template<typename Functor> |
11830 | void setDst(VirtualRegister value, Functor func) |
11831 | { |
11832 | if (isWide()) |
11833 | setDst<OpcodeSize::Wide>(value, func); |
11834 | else |
11835 | setDst<OpcodeSize::Narrow>(value, func); |
11836 | } |
11837 | |
11838 | template <OpcodeSize size, typename Functor> |
11839 | void setDst(VirtualRegister value, Functor func) |
11840 | { |
11841 | if (!Fits<VirtualRegister, size>::check(value)) |
11842 | value = func(); |
11843 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
11844 | *stream = Fits<VirtualRegister, size>::convert(value); |
11845 | } |
11846 | |
11847 | template<typename Functor> |
11848 | void setOperand(VirtualRegister value, Functor func) |
11849 | { |
11850 | if (isWide()) |
11851 | setOperand<OpcodeSize::Wide>(value, func); |
11852 | else |
11853 | setOperand<OpcodeSize::Narrow>(value, func); |
11854 | } |
11855 | |
11856 | template <OpcodeSize size, typename Functor> |
11857 | void setOperand(VirtualRegister value, Functor func) |
11858 | { |
11859 | if (!Fits<VirtualRegister, size>::check(value)) |
11860 | value = func(); |
11861 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
11862 | *stream = Fits<VirtualRegister, size>::convert(value); |
11863 | } |
11864 | |
11865 | VirtualRegister m_dst; |
11866 | VirtualRegister m_operand; |
11867 | }; |
11868 | |
11869 | struct OpNeqNull : public Instruction { |
11870 | static constexpr OpcodeID opcodeID = op_neq_null; |
11871 | |
11872 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
11873 | { |
11874 | |
11875 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand) |
11876 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand); |
11877 | } |
11878 | |
11879 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
11880 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
11881 | { |
11882 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand); |
11883 | if (shouldAssert == Assert) |
11884 | ASSERT(didEmit); |
11885 | return didEmit; |
11886 | } |
11887 | |
11888 | private: |
11889 | template<OpcodeSize size, bool recordOpcode> |
11890 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
11891 | { |
11892 | if (size == OpcodeSize::Wide) |
11893 | gen->alignWideOpcode(); |
11894 | if (Fits<unsigned, size>::check(opcodeID) |
11895 | && Fits<VirtualRegister, size>::check(dst) |
11896 | && Fits<VirtualRegister, size>::check(operand) |
11897 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
11898 | if (recordOpcode) |
11899 | gen->recordOpcode(opcodeID); |
11900 | if (size == OpcodeSize::Wide) |
11901 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
11902 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
11903 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
11904 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
11905 | return true; |
11906 | } |
11907 | return false; |
11908 | } |
11909 | |
11910 | public: |
11911 | template<typename Block> |
11912 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
11913 | { |
11914 | dumper->printLocationAndOp(__location, &"*neq_null" [!__isWide]); |
11915 | dumper->dumpOperand(m_dst, true); |
11916 | dumper->dumpOperand(m_operand, false); |
11917 | } |
11918 | |
11919 | OpNeqNull(const uint8_t* stream) |
11920 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
11921 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
11922 | { |
11923 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11924 | } |
11925 | |
11926 | OpNeqNull(const uint32_t* stream) |
11927 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
11928 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
11929 | { |
11930 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
11931 | } |
11932 | |
11933 | static OpNeqNull decode(const uint8_t* stream) |
11934 | { |
11935 | if (*stream != op_wide) |
11936 | return { stream }; |
11937 | |
11938 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
11939 | return { wideStream }; |
11940 | } |
11941 | |
11942 | template<typename Functor> |
11943 | void setDst(VirtualRegister value, Functor func) |
11944 | { |
11945 | if (isWide()) |
11946 | setDst<OpcodeSize::Wide>(value, func); |
11947 | else |
11948 | setDst<OpcodeSize::Narrow>(value, func); |
11949 | } |
11950 | |
11951 | template <OpcodeSize size, typename Functor> |
11952 | void setDst(VirtualRegister value, Functor func) |
11953 | { |
11954 | if (!Fits<VirtualRegister, size>::check(value)) |
11955 | value = func(); |
11956 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
11957 | *stream = Fits<VirtualRegister, size>::convert(value); |
11958 | } |
11959 | |
11960 | template<typename Functor> |
11961 | void setOperand(VirtualRegister value, Functor func) |
11962 | { |
11963 | if (isWide()) |
11964 | setOperand<OpcodeSize::Wide>(value, func); |
11965 | else |
11966 | setOperand<OpcodeSize::Narrow>(value, func); |
11967 | } |
11968 | |
11969 | template <OpcodeSize size, typename Functor> |
11970 | void setOperand(VirtualRegister value, Functor func) |
11971 | { |
11972 | if (!Fits<VirtualRegister, size>::check(value)) |
11973 | value = func(); |
11974 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
11975 | *stream = Fits<VirtualRegister, size>::convert(value); |
11976 | } |
11977 | |
11978 | VirtualRegister m_dst; |
11979 | VirtualRegister m_operand; |
11980 | }; |
11981 | |
11982 | struct OpToString : public Instruction { |
11983 | static constexpr OpcodeID opcodeID = op_to_string; |
11984 | |
11985 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
11986 | { |
11987 | |
11988 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand) |
11989 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand); |
11990 | } |
11991 | |
11992 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
11993 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
11994 | { |
11995 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand); |
11996 | if (shouldAssert == Assert) |
11997 | ASSERT(didEmit); |
11998 | return didEmit; |
11999 | } |
12000 | |
12001 | private: |
12002 | template<OpcodeSize size, bool recordOpcode> |
12003 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12004 | { |
12005 | if (size == OpcodeSize::Wide) |
12006 | gen->alignWideOpcode(); |
12007 | if (Fits<unsigned, size>::check(opcodeID) |
12008 | && Fits<VirtualRegister, size>::check(dst) |
12009 | && Fits<VirtualRegister, size>::check(operand) |
12010 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
12011 | if (recordOpcode) |
12012 | gen->recordOpcode(opcodeID); |
12013 | if (size == OpcodeSize::Wide) |
12014 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
12015 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
12016 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
12017 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
12018 | return true; |
12019 | } |
12020 | return false; |
12021 | } |
12022 | |
12023 | public: |
12024 | template<typename Block> |
12025 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
12026 | { |
12027 | dumper->printLocationAndOp(__location, &"*to_string" [!__isWide]); |
12028 | dumper->dumpOperand(m_dst, true); |
12029 | dumper->dumpOperand(m_operand, false); |
12030 | } |
12031 | |
12032 | OpToString(const uint8_t* stream) |
12033 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
12034 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
12035 | { |
12036 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12037 | } |
12038 | |
12039 | OpToString(const uint32_t* stream) |
12040 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
12041 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
12042 | { |
12043 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12044 | } |
12045 | |
12046 | static OpToString decode(const uint8_t* stream) |
12047 | { |
12048 | if (*stream != op_wide) |
12049 | return { stream }; |
12050 | |
12051 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
12052 | return { wideStream }; |
12053 | } |
12054 | |
12055 | template<typename Functor> |
12056 | void setDst(VirtualRegister value, Functor func) |
12057 | { |
12058 | if (isWide()) |
12059 | setDst<OpcodeSize::Wide>(value, func); |
12060 | else |
12061 | setDst<OpcodeSize::Narrow>(value, func); |
12062 | } |
12063 | |
12064 | template <OpcodeSize size, typename Functor> |
12065 | void setDst(VirtualRegister value, Functor func) |
12066 | { |
12067 | if (!Fits<VirtualRegister, size>::check(value)) |
12068 | value = func(); |
12069 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
12070 | *stream = Fits<VirtualRegister, size>::convert(value); |
12071 | } |
12072 | |
12073 | template<typename Functor> |
12074 | void setOperand(VirtualRegister value, Functor func) |
12075 | { |
12076 | if (isWide()) |
12077 | setOperand<OpcodeSize::Wide>(value, func); |
12078 | else |
12079 | setOperand<OpcodeSize::Narrow>(value, func); |
12080 | } |
12081 | |
12082 | template <OpcodeSize size, typename Functor> |
12083 | void setOperand(VirtualRegister value, Functor func) |
12084 | { |
12085 | if (!Fits<VirtualRegister, size>::check(value)) |
12086 | value = func(); |
12087 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
12088 | *stream = Fits<VirtualRegister, size>::convert(value); |
12089 | } |
12090 | |
12091 | VirtualRegister m_dst; |
12092 | VirtualRegister m_operand; |
12093 | }; |
12094 | |
12095 | struct OpUnsigned : public Instruction { |
12096 | static constexpr OpcodeID opcodeID = op_unsigned; |
12097 | |
12098 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12099 | { |
12100 | |
12101 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand) |
12102 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand); |
12103 | } |
12104 | |
12105 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
12106 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12107 | { |
12108 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand); |
12109 | if (shouldAssert == Assert) |
12110 | ASSERT(didEmit); |
12111 | return didEmit; |
12112 | } |
12113 | |
12114 | private: |
12115 | template<OpcodeSize size, bool recordOpcode> |
12116 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12117 | { |
12118 | if (size == OpcodeSize::Wide) |
12119 | gen->alignWideOpcode(); |
12120 | if (Fits<unsigned, size>::check(opcodeID) |
12121 | && Fits<VirtualRegister, size>::check(dst) |
12122 | && Fits<VirtualRegister, size>::check(operand) |
12123 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
12124 | if (recordOpcode) |
12125 | gen->recordOpcode(opcodeID); |
12126 | if (size == OpcodeSize::Wide) |
12127 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
12128 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
12129 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
12130 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
12131 | return true; |
12132 | } |
12133 | return false; |
12134 | } |
12135 | |
12136 | public: |
12137 | template<typename Block> |
12138 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
12139 | { |
12140 | dumper->printLocationAndOp(__location, &"*unsigned" [!__isWide]); |
12141 | dumper->dumpOperand(m_dst, true); |
12142 | dumper->dumpOperand(m_operand, false); |
12143 | } |
12144 | |
12145 | OpUnsigned(const uint8_t* stream) |
12146 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
12147 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
12148 | { |
12149 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12150 | } |
12151 | |
12152 | OpUnsigned(const uint32_t* stream) |
12153 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
12154 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
12155 | { |
12156 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12157 | } |
12158 | |
12159 | static OpUnsigned decode(const uint8_t* stream) |
12160 | { |
12161 | if (*stream != op_wide) |
12162 | return { stream }; |
12163 | |
12164 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
12165 | return { wideStream }; |
12166 | } |
12167 | |
12168 | template<typename Functor> |
12169 | void setDst(VirtualRegister value, Functor func) |
12170 | { |
12171 | if (isWide()) |
12172 | setDst<OpcodeSize::Wide>(value, func); |
12173 | else |
12174 | setDst<OpcodeSize::Narrow>(value, func); |
12175 | } |
12176 | |
12177 | template <OpcodeSize size, typename Functor> |
12178 | void setDst(VirtualRegister value, Functor func) |
12179 | { |
12180 | if (!Fits<VirtualRegister, size>::check(value)) |
12181 | value = func(); |
12182 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
12183 | *stream = Fits<VirtualRegister, size>::convert(value); |
12184 | } |
12185 | |
12186 | template<typename Functor> |
12187 | void setOperand(VirtualRegister value, Functor func) |
12188 | { |
12189 | if (isWide()) |
12190 | setOperand<OpcodeSize::Wide>(value, func); |
12191 | else |
12192 | setOperand<OpcodeSize::Narrow>(value, func); |
12193 | } |
12194 | |
12195 | template <OpcodeSize size, typename Functor> |
12196 | void setOperand(VirtualRegister value, Functor func) |
12197 | { |
12198 | if (!Fits<VirtualRegister, size>::check(value)) |
12199 | value = func(); |
12200 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
12201 | *stream = Fits<VirtualRegister, size>::convert(value); |
12202 | } |
12203 | |
12204 | VirtualRegister m_dst; |
12205 | VirtualRegister m_operand; |
12206 | }; |
12207 | |
12208 | struct OpIsEmpty : public Instruction { |
12209 | static constexpr OpcodeID opcodeID = op_is_empty; |
12210 | |
12211 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12212 | { |
12213 | |
12214 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand) |
12215 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand); |
12216 | } |
12217 | |
12218 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
12219 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12220 | { |
12221 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand); |
12222 | if (shouldAssert == Assert) |
12223 | ASSERT(didEmit); |
12224 | return didEmit; |
12225 | } |
12226 | |
12227 | private: |
12228 | template<OpcodeSize size, bool recordOpcode> |
12229 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12230 | { |
12231 | if (size == OpcodeSize::Wide) |
12232 | gen->alignWideOpcode(); |
12233 | if (Fits<unsigned, size>::check(opcodeID) |
12234 | && Fits<VirtualRegister, size>::check(dst) |
12235 | && Fits<VirtualRegister, size>::check(operand) |
12236 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
12237 | if (recordOpcode) |
12238 | gen->recordOpcode(opcodeID); |
12239 | if (size == OpcodeSize::Wide) |
12240 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
12241 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
12242 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
12243 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
12244 | return true; |
12245 | } |
12246 | return false; |
12247 | } |
12248 | |
12249 | public: |
12250 | template<typename Block> |
12251 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
12252 | { |
12253 | dumper->printLocationAndOp(__location, &"*is_empty" [!__isWide]); |
12254 | dumper->dumpOperand(m_dst, true); |
12255 | dumper->dumpOperand(m_operand, false); |
12256 | } |
12257 | |
12258 | OpIsEmpty(const uint8_t* stream) |
12259 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
12260 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
12261 | { |
12262 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12263 | } |
12264 | |
12265 | OpIsEmpty(const uint32_t* stream) |
12266 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
12267 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
12268 | { |
12269 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12270 | } |
12271 | |
12272 | static OpIsEmpty decode(const uint8_t* stream) |
12273 | { |
12274 | if (*stream != op_wide) |
12275 | return { stream }; |
12276 | |
12277 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
12278 | return { wideStream }; |
12279 | } |
12280 | |
12281 | template<typename Functor> |
12282 | void setDst(VirtualRegister value, Functor func) |
12283 | { |
12284 | if (isWide()) |
12285 | setDst<OpcodeSize::Wide>(value, func); |
12286 | else |
12287 | setDst<OpcodeSize::Narrow>(value, func); |
12288 | } |
12289 | |
12290 | template <OpcodeSize size, typename Functor> |
12291 | void setDst(VirtualRegister value, Functor func) |
12292 | { |
12293 | if (!Fits<VirtualRegister, size>::check(value)) |
12294 | value = func(); |
12295 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
12296 | *stream = Fits<VirtualRegister, size>::convert(value); |
12297 | } |
12298 | |
12299 | template<typename Functor> |
12300 | void setOperand(VirtualRegister value, Functor func) |
12301 | { |
12302 | if (isWide()) |
12303 | setOperand<OpcodeSize::Wide>(value, func); |
12304 | else |
12305 | setOperand<OpcodeSize::Narrow>(value, func); |
12306 | } |
12307 | |
12308 | template <OpcodeSize size, typename Functor> |
12309 | void setOperand(VirtualRegister value, Functor func) |
12310 | { |
12311 | if (!Fits<VirtualRegister, size>::check(value)) |
12312 | value = func(); |
12313 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
12314 | *stream = Fits<VirtualRegister, size>::convert(value); |
12315 | } |
12316 | |
12317 | VirtualRegister m_dst; |
12318 | VirtualRegister m_operand; |
12319 | }; |
12320 | |
12321 | struct OpIsUndefined : public Instruction { |
12322 | static constexpr OpcodeID opcodeID = op_is_undefined; |
12323 | |
12324 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12325 | { |
12326 | |
12327 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand) |
12328 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand); |
12329 | } |
12330 | |
12331 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
12332 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12333 | { |
12334 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand); |
12335 | if (shouldAssert == Assert) |
12336 | ASSERT(didEmit); |
12337 | return didEmit; |
12338 | } |
12339 | |
12340 | private: |
12341 | template<OpcodeSize size, bool recordOpcode> |
12342 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12343 | { |
12344 | if (size == OpcodeSize::Wide) |
12345 | gen->alignWideOpcode(); |
12346 | if (Fits<unsigned, size>::check(opcodeID) |
12347 | && Fits<VirtualRegister, size>::check(dst) |
12348 | && Fits<VirtualRegister, size>::check(operand) |
12349 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
12350 | if (recordOpcode) |
12351 | gen->recordOpcode(opcodeID); |
12352 | if (size == OpcodeSize::Wide) |
12353 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
12354 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
12355 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
12356 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
12357 | return true; |
12358 | } |
12359 | return false; |
12360 | } |
12361 | |
12362 | public: |
12363 | template<typename Block> |
12364 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
12365 | { |
12366 | dumper->printLocationAndOp(__location, &"*is_undefined" [!__isWide]); |
12367 | dumper->dumpOperand(m_dst, true); |
12368 | dumper->dumpOperand(m_operand, false); |
12369 | } |
12370 | |
12371 | OpIsUndefined(const uint8_t* stream) |
12372 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
12373 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
12374 | { |
12375 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12376 | } |
12377 | |
12378 | OpIsUndefined(const uint32_t* stream) |
12379 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
12380 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
12381 | { |
12382 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12383 | } |
12384 | |
12385 | static OpIsUndefined decode(const uint8_t* stream) |
12386 | { |
12387 | if (*stream != op_wide) |
12388 | return { stream }; |
12389 | |
12390 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
12391 | return { wideStream }; |
12392 | } |
12393 | |
12394 | template<typename Functor> |
12395 | void setDst(VirtualRegister value, Functor func) |
12396 | { |
12397 | if (isWide()) |
12398 | setDst<OpcodeSize::Wide>(value, func); |
12399 | else |
12400 | setDst<OpcodeSize::Narrow>(value, func); |
12401 | } |
12402 | |
12403 | template <OpcodeSize size, typename Functor> |
12404 | void setDst(VirtualRegister value, Functor func) |
12405 | { |
12406 | if (!Fits<VirtualRegister, size>::check(value)) |
12407 | value = func(); |
12408 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
12409 | *stream = Fits<VirtualRegister, size>::convert(value); |
12410 | } |
12411 | |
12412 | template<typename Functor> |
12413 | void setOperand(VirtualRegister value, Functor func) |
12414 | { |
12415 | if (isWide()) |
12416 | setOperand<OpcodeSize::Wide>(value, func); |
12417 | else |
12418 | setOperand<OpcodeSize::Narrow>(value, func); |
12419 | } |
12420 | |
12421 | template <OpcodeSize size, typename Functor> |
12422 | void setOperand(VirtualRegister value, Functor func) |
12423 | { |
12424 | if (!Fits<VirtualRegister, size>::check(value)) |
12425 | value = func(); |
12426 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
12427 | *stream = Fits<VirtualRegister, size>::convert(value); |
12428 | } |
12429 | |
12430 | VirtualRegister m_dst; |
12431 | VirtualRegister m_operand; |
12432 | }; |
12433 | |
12434 | struct OpIsUndefinedOrNull : public Instruction { |
12435 | static constexpr OpcodeID opcodeID = op_is_undefined_or_null; |
12436 | |
12437 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12438 | { |
12439 | |
12440 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand) |
12441 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand); |
12442 | } |
12443 | |
12444 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
12445 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12446 | { |
12447 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand); |
12448 | if (shouldAssert == Assert) |
12449 | ASSERT(didEmit); |
12450 | return didEmit; |
12451 | } |
12452 | |
12453 | private: |
12454 | template<OpcodeSize size, bool recordOpcode> |
12455 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12456 | { |
12457 | if (size == OpcodeSize::Wide) |
12458 | gen->alignWideOpcode(); |
12459 | if (Fits<unsigned, size>::check(opcodeID) |
12460 | && Fits<VirtualRegister, size>::check(dst) |
12461 | && Fits<VirtualRegister, size>::check(operand) |
12462 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
12463 | if (recordOpcode) |
12464 | gen->recordOpcode(opcodeID); |
12465 | if (size == OpcodeSize::Wide) |
12466 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
12467 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
12468 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
12469 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
12470 | return true; |
12471 | } |
12472 | return false; |
12473 | } |
12474 | |
12475 | public: |
12476 | template<typename Block> |
12477 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
12478 | { |
12479 | dumper->printLocationAndOp(__location, &"*is_undefined_or_null" [!__isWide]); |
12480 | dumper->dumpOperand(m_dst, true); |
12481 | dumper->dumpOperand(m_operand, false); |
12482 | } |
12483 | |
12484 | OpIsUndefinedOrNull(const uint8_t* stream) |
12485 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
12486 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
12487 | { |
12488 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12489 | } |
12490 | |
12491 | OpIsUndefinedOrNull(const uint32_t* stream) |
12492 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
12493 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
12494 | { |
12495 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12496 | } |
12497 | |
12498 | static OpIsUndefinedOrNull decode(const uint8_t* stream) |
12499 | { |
12500 | if (*stream != op_wide) |
12501 | return { stream }; |
12502 | |
12503 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
12504 | return { wideStream }; |
12505 | } |
12506 | |
12507 | template<typename Functor> |
12508 | void setDst(VirtualRegister value, Functor func) |
12509 | { |
12510 | if (isWide()) |
12511 | setDst<OpcodeSize::Wide>(value, func); |
12512 | else |
12513 | setDst<OpcodeSize::Narrow>(value, func); |
12514 | } |
12515 | |
12516 | template <OpcodeSize size, typename Functor> |
12517 | void setDst(VirtualRegister value, Functor func) |
12518 | { |
12519 | if (!Fits<VirtualRegister, size>::check(value)) |
12520 | value = func(); |
12521 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
12522 | *stream = Fits<VirtualRegister, size>::convert(value); |
12523 | } |
12524 | |
12525 | template<typename Functor> |
12526 | void setOperand(VirtualRegister value, Functor func) |
12527 | { |
12528 | if (isWide()) |
12529 | setOperand<OpcodeSize::Wide>(value, func); |
12530 | else |
12531 | setOperand<OpcodeSize::Narrow>(value, func); |
12532 | } |
12533 | |
12534 | template <OpcodeSize size, typename Functor> |
12535 | void setOperand(VirtualRegister value, Functor func) |
12536 | { |
12537 | if (!Fits<VirtualRegister, size>::check(value)) |
12538 | value = func(); |
12539 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
12540 | *stream = Fits<VirtualRegister, size>::convert(value); |
12541 | } |
12542 | |
12543 | VirtualRegister m_dst; |
12544 | VirtualRegister m_operand; |
12545 | }; |
12546 | |
12547 | struct OpIsBoolean : public Instruction { |
12548 | static constexpr OpcodeID opcodeID = op_is_boolean; |
12549 | |
12550 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12551 | { |
12552 | |
12553 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand) |
12554 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand); |
12555 | } |
12556 | |
12557 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
12558 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12559 | { |
12560 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand); |
12561 | if (shouldAssert == Assert) |
12562 | ASSERT(didEmit); |
12563 | return didEmit; |
12564 | } |
12565 | |
12566 | private: |
12567 | template<OpcodeSize size, bool recordOpcode> |
12568 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12569 | { |
12570 | if (size == OpcodeSize::Wide) |
12571 | gen->alignWideOpcode(); |
12572 | if (Fits<unsigned, size>::check(opcodeID) |
12573 | && Fits<VirtualRegister, size>::check(dst) |
12574 | && Fits<VirtualRegister, size>::check(operand) |
12575 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
12576 | if (recordOpcode) |
12577 | gen->recordOpcode(opcodeID); |
12578 | if (size == OpcodeSize::Wide) |
12579 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
12580 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
12581 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
12582 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
12583 | return true; |
12584 | } |
12585 | return false; |
12586 | } |
12587 | |
12588 | public: |
12589 | template<typename Block> |
12590 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
12591 | { |
12592 | dumper->printLocationAndOp(__location, &"*is_boolean" [!__isWide]); |
12593 | dumper->dumpOperand(m_dst, true); |
12594 | dumper->dumpOperand(m_operand, false); |
12595 | } |
12596 | |
12597 | OpIsBoolean(const uint8_t* stream) |
12598 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
12599 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
12600 | { |
12601 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12602 | } |
12603 | |
12604 | OpIsBoolean(const uint32_t* stream) |
12605 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
12606 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
12607 | { |
12608 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12609 | } |
12610 | |
12611 | static OpIsBoolean decode(const uint8_t* stream) |
12612 | { |
12613 | if (*stream != op_wide) |
12614 | return { stream }; |
12615 | |
12616 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
12617 | return { wideStream }; |
12618 | } |
12619 | |
12620 | template<typename Functor> |
12621 | void setDst(VirtualRegister value, Functor func) |
12622 | { |
12623 | if (isWide()) |
12624 | setDst<OpcodeSize::Wide>(value, func); |
12625 | else |
12626 | setDst<OpcodeSize::Narrow>(value, func); |
12627 | } |
12628 | |
12629 | template <OpcodeSize size, typename Functor> |
12630 | void setDst(VirtualRegister value, Functor func) |
12631 | { |
12632 | if (!Fits<VirtualRegister, size>::check(value)) |
12633 | value = func(); |
12634 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
12635 | *stream = Fits<VirtualRegister, size>::convert(value); |
12636 | } |
12637 | |
12638 | template<typename Functor> |
12639 | void setOperand(VirtualRegister value, Functor func) |
12640 | { |
12641 | if (isWide()) |
12642 | setOperand<OpcodeSize::Wide>(value, func); |
12643 | else |
12644 | setOperand<OpcodeSize::Narrow>(value, func); |
12645 | } |
12646 | |
12647 | template <OpcodeSize size, typename Functor> |
12648 | void setOperand(VirtualRegister value, Functor func) |
12649 | { |
12650 | if (!Fits<VirtualRegister, size>::check(value)) |
12651 | value = func(); |
12652 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
12653 | *stream = Fits<VirtualRegister, size>::convert(value); |
12654 | } |
12655 | |
12656 | VirtualRegister m_dst; |
12657 | VirtualRegister m_operand; |
12658 | }; |
12659 | |
12660 | struct OpIsNumber : public Instruction { |
12661 | static constexpr OpcodeID opcodeID = op_is_number; |
12662 | |
12663 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12664 | { |
12665 | |
12666 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand) |
12667 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand); |
12668 | } |
12669 | |
12670 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
12671 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12672 | { |
12673 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand); |
12674 | if (shouldAssert == Assert) |
12675 | ASSERT(didEmit); |
12676 | return didEmit; |
12677 | } |
12678 | |
12679 | private: |
12680 | template<OpcodeSize size, bool recordOpcode> |
12681 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12682 | { |
12683 | if (size == OpcodeSize::Wide) |
12684 | gen->alignWideOpcode(); |
12685 | if (Fits<unsigned, size>::check(opcodeID) |
12686 | && Fits<VirtualRegister, size>::check(dst) |
12687 | && Fits<VirtualRegister, size>::check(operand) |
12688 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
12689 | if (recordOpcode) |
12690 | gen->recordOpcode(opcodeID); |
12691 | if (size == OpcodeSize::Wide) |
12692 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
12693 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
12694 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
12695 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
12696 | return true; |
12697 | } |
12698 | return false; |
12699 | } |
12700 | |
12701 | public: |
12702 | template<typename Block> |
12703 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
12704 | { |
12705 | dumper->printLocationAndOp(__location, &"*is_number" [!__isWide]); |
12706 | dumper->dumpOperand(m_dst, true); |
12707 | dumper->dumpOperand(m_operand, false); |
12708 | } |
12709 | |
12710 | OpIsNumber(const uint8_t* stream) |
12711 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
12712 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
12713 | { |
12714 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12715 | } |
12716 | |
12717 | OpIsNumber(const uint32_t* stream) |
12718 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
12719 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
12720 | { |
12721 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12722 | } |
12723 | |
12724 | static OpIsNumber decode(const uint8_t* stream) |
12725 | { |
12726 | if (*stream != op_wide) |
12727 | return { stream }; |
12728 | |
12729 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
12730 | return { wideStream }; |
12731 | } |
12732 | |
12733 | template<typename Functor> |
12734 | void setDst(VirtualRegister value, Functor func) |
12735 | { |
12736 | if (isWide()) |
12737 | setDst<OpcodeSize::Wide>(value, func); |
12738 | else |
12739 | setDst<OpcodeSize::Narrow>(value, func); |
12740 | } |
12741 | |
12742 | template <OpcodeSize size, typename Functor> |
12743 | void setDst(VirtualRegister value, Functor func) |
12744 | { |
12745 | if (!Fits<VirtualRegister, size>::check(value)) |
12746 | value = func(); |
12747 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
12748 | *stream = Fits<VirtualRegister, size>::convert(value); |
12749 | } |
12750 | |
12751 | template<typename Functor> |
12752 | void setOperand(VirtualRegister value, Functor func) |
12753 | { |
12754 | if (isWide()) |
12755 | setOperand<OpcodeSize::Wide>(value, func); |
12756 | else |
12757 | setOperand<OpcodeSize::Narrow>(value, func); |
12758 | } |
12759 | |
12760 | template <OpcodeSize size, typename Functor> |
12761 | void setOperand(VirtualRegister value, Functor func) |
12762 | { |
12763 | if (!Fits<VirtualRegister, size>::check(value)) |
12764 | value = func(); |
12765 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
12766 | *stream = Fits<VirtualRegister, size>::convert(value); |
12767 | } |
12768 | |
12769 | VirtualRegister m_dst; |
12770 | VirtualRegister m_operand; |
12771 | }; |
12772 | |
12773 | struct OpIsObject : public Instruction { |
12774 | static constexpr OpcodeID opcodeID = op_is_object; |
12775 | |
12776 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12777 | { |
12778 | |
12779 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand) |
12780 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand); |
12781 | } |
12782 | |
12783 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
12784 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12785 | { |
12786 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand); |
12787 | if (shouldAssert == Assert) |
12788 | ASSERT(didEmit); |
12789 | return didEmit; |
12790 | } |
12791 | |
12792 | private: |
12793 | template<OpcodeSize size, bool recordOpcode> |
12794 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12795 | { |
12796 | if (size == OpcodeSize::Wide) |
12797 | gen->alignWideOpcode(); |
12798 | if (Fits<unsigned, size>::check(opcodeID) |
12799 | && Fits<VirtualRegister, size>::check(dst) |
12800 | && Fits<VirtualRegister, size>::check(operand) |
12801 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
12802 | if (recordOpcode) |
12803 | gen->recordOpcode(opcodeID); |
12804 | if (size == OpcodeSize::Wide) |
12805 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
12806 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
12807 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
12808 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
12809 | return true; |
12810 | } |
12811 | return false; |
12812 | } |
12813 | |
12814 | public: |
12815 | template<typename Block> |
12816 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
12817 | { |
12818 | dumper->printLocationAndOp(__location, &"*is_object" [!__isWide]); |
12819 | dumper->dumpOperand(m_dst, true); |
12820 | dumper->dumpOperand(m_operand, false); |
12821 | } |
12822 | |
12823 | OpIsObject(const uint8_t* stream) |
12824 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
12825 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
12826 | { |
12827 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12828 | } |
12829 | |
12830 | OpIsObject(const uint32_t* stream) |
12831 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
12832 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
12833 | { |
12834 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12835 | } |
12836 | |
12837 | static OpIsObject decode(const uint8_t* stream) |
12838 | { |
12839 | if (*stream != op_wide) |
12840 | return { stream }; |
12841 | |
12842 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
12843 | return { wideStream }; |
12844 | } |
12845 | |
12846 | template<typename Functor> |
12847 | void setDst(VirtualRegister value, Functor func) |
12848 | { |
12849 | if (isWide()) |
12850 | setDst<OpcodeSize::Wide>(value, func); |
12851 | else |
12852 | setDst<OpcodeSize::Narrow>(value, func); |
12853 | } |
12854 | |
12855 | template <OpcodeSize size, typename Functor> |
12856 | void setDst(VirtualRegister value, Functor func) |
12857 | { |
12858 | if (!Fits<VirtualRegister, size>::check(value)) |
12859 | value = func(); |
12860 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
12861 | *stream = Fits<VirtualRegister, size>::convert(value); |
12862 | } |
12863 | |
12864 | template<typename Functor> |
12865 | void setOperand(VirtualRegister value, Functor func) |
12866 | { |
12867 | if (isWide()) |
12868 | setOperand<OpcodeSize::Wide>(value, func); |
12869 | else |
12870 | setOperand<OpcodeSize::Narrow>(value, func); |
12871 | } |
12872 | |
12873 | template <OpcodeSize size, typename Functor> |
12874 | void setOperand(VirtualRegister value, Functor func) |
12875 | { |
12876 | if (!Fits<VirtualRegister, size>::check(value)) |
12877 | value = func(); |
12878 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
12879 | *stream = Fits<VirtualRegister, size>::convert(value); |
12880 | } |
12881 | |
12882 | VirtualRegister m_dst; |
12883 | VirtualRegister m_operand; |
12884 | }; |
12885 | |
12886 | struct OpIsObjectOrNull : public Instruction { |
12887 | static constexpr OpcodeID opcodeID = op_is_object_or_null; |
12888 | |
12889 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12890 | { |
12891 | |
12892 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand) |
12893 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand); |
12894 | } |
12895 | |
12896 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
12897 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12898 | { |
12899 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand); |
12900 | if (shouldAssert == Assert) |
12901 | ASSERT(didEmit); |
12902 | return didEmit; |
12903 | } |
12904 | |
12905 | private: |
12906 | template<OpcodeSize size, bool recordOpcode> |
12907 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
12908 | { |
12909 | if (size == OpcodeSize::Wide) |
12910 | gen->alignWideOpcode(); |
12911 | if (Fits<unsigned, size>::check(opcodeID) |
12912 | && Fits<VirtualRegister, size>::check(dst) |
12913 | && Fits<VirtualRegister, size>::check(operand) |
12914 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
12915 | if (recordOpcode) |
12916 | gen->recordOpcode(opcodeID); |
12917 | if (size == OpcodeSize::Wide) |
12918 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
12919 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
12920 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
12921 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
12922 | return true; |
12923 | } |
12924 | return false; |
12925 | } |
12926 | |
12927 | public: |
12928 | template<typename Block> |
12929 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
12930 | { |
12931 | dumper->printLocationAndOp(__location, &"*is_object_or_null" [!__isWide]); |
12932 | dumper->dumpOperand(m_dst, true); |
12933 | dumper->dumpOperand(m_operand, false); |
12934 | } |
12935 | |
12936 | OpIsObjectOrNull(const uint8_t* stream) |
12937 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
12938 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
12939 | { |
12940 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12941 | } |
12942 | |
12943 | OpIsObjectOrNull(const uint32_t* stream) |
12944 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
12945 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
12946 | { |
12947 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
12948 | } |
12949 | |
12950 | static OpIsObjectOrNull decode(const uint8_t* stream) |
12951 | { |
12952 | if (*stream != op_wide) |
12953 | return { stream }; |
12954 | |
12955 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
12956 | return { wideStream }; |
12957 | } |
12958 | |
12959 | template<typename Functor> |
12960 | void setDst(VirtualRegister value, Functor func) |
12961 | { |
12962 | if (isWide()) |
12963 | setDst<OpcodeSize::Wide>(value, func); |
12964 | else |
12965 | setDst<OpcodeSize::Narrow>(value, func); |
12966 | } |
12967 | |
12968 | template <OpcodeSize size, typename Functor> |
12969 | void setDst(VirtualRegister value, Functor func) |
12970 | { |
12971 | if (!Fits<VirtualRegister, size>::check(value)) |
12972 | value = func(); |
12973 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
12974 | *stream = Fits<VirtualRegister, size>::convert(value); |
12975 | } |
12976 | |
12977 | template<typename Functor> |
12978 | void setOperand(VirtualRegister value, Functor func) |
12979 | { |
12980 | if (isWide()) |
12981 | setOperand<OpcodeSize::Wide>(value, func); |
12982 | else |
12983 | setOperand<OpcodeSize::Narrow>(value, func); |
12984 | } |
12985 | |
12986 | template <OpcodeSize size, typename Functor> |
12987 | void setOperand(VirtualRegister value, Functor func) |
12988 | { |
12989 | if (!Fits<VirtualRegister, size>::check(value)) |
12990 | value = func(); |
12991 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
12992 | *stream = Fits<VirtualRegister, size>::convert(value); |
12993 | } |
12994 | |
12995 | VirtualRegister m_dst; |
12996 | VirtualRegister m_operand; |
12997 | }; |
12998 | |
12999 | struct OpIsFunction : public Instruction { |
13000 | static constexpr OpcodeID opcodeID = op_is_function; |
13001 | |
13002 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
13003 | { |
13004 | |
13005 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand) |
13006 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand); |
13007 | } |
13008 | |
13009 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
13010 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
13011 | { |
13012 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand); |
13013 | if (shouldAssert == Assert) |
13014 | ASSERT(didEmit); |
13015 | return didEmit; |
13016 | } |
13017 | |
13018 | private: |
13019 | template<OpcodeSize size, bool recordOpcode> |
13020 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
13021 | { |
13022 | if (size == OpcodeSize::Wide) |
13023 | gen->alignWideOpcode(); |
13024 | if (Fits<unsigned, size>::check(opcodeID) |
13025 | && Fits<VirtualRegister, size>::check(dst) |
13026 | && Fits<VirtualRegister, size>::check(operand) |
13027 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
13028 | if (recordOpcode) |
13029 | gen->recordOpcode(opcodeID); |
13030 | if (size == OpcodeSize::Wide) |
13031 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
13032 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
13033 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
13034 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
13035 | return true; |
13036 | } |
13037 | return false; |
13038 | } |
13039 | |
13040 | public: |
13041 | template<typename Block> |
13042 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
13043 | { |
13044 | dumper->printLocationAndOp(__location, &"*is_function" [!__isWide]); |
13045 | dumper->dumpOperand(m_dst, true); |
13046 | dumper->dumpOperand(m_operand, false); |
13047 | } |
13048 | |
13049 | OpIsFunction(const uint8_t* stream) |
13050 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
13051 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
13052 | { |
13053 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13054 | } |
13055 | |
13056 | OpIsFunction(const uint32_t* stream) |
13057 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
13058 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
13059 | { |
13060 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13061 | } |
13062 | |
13063 | static OpIsFunction decode(const uint8_t* stream) |
13064 | { |
13065 | if (*stream != op_wide) |
13066 | return { stream }; |
13067 | |
13068 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
13069 | return { wideStream }; |
13070 | } |
13071 | |
13072 | template<typename Functor> |
13073 | void setDst(VirtualRegister value, Functor func) |
13074 | { |
13075 | if (isWide()) |
13076 | setDst<OpcodeSize::Wide>(value, func); |
13077 | else |
13078 | setDst<OpcodeSize::Narrow>(value, func); |
13079 | } |
13080 | |
13081 | template <OpcodeSize size, typename Functor> |
13082 | void setDst(VirtualRegister value, Functor func) |
13083 | { |
13084 | if (!Fits<VirtualRegister, size>::check(value)) |
13085 | value = func(); |
13086 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
13087 | *stream = Fits<VirtualRegister, size>::convert(value); |
13088 | } |
13089 | |
13090 | template<typename Functor> |
13091 | void setOperand(VirtualRegister value, Functor func) |
13092 | { |
13093 | if (isWide()) |
13094 | setOperand<OpcodeSize::Wide>(value, func); |
13095 | else |
13096 | setOperand<OpcodeSize::Narrow>(value, func); |
13097 | } |
13098 | |
13099 | template <OpcodeSize size, typename Functor> |
13100 | void setOperand(VirtualRegister value, Functor func) |
13101 | { |
13102 | if (!Fits<VirtualRegister, size>::check(value)) |
13103 | value = func(); |
13104 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
13105 | *stream = Fits<VirtualRegister, size>::convert(value); |
13106 | } |
13107 | |
13108 | VirtualRegister m_dst; |
13109 | VirtualRegister m_operand; |
13110 | }; |
13111 | |
13112 | struct OpInc : public Instruction { |
13113 | static constexpr OpcodeID opcodeID = op_inc; |
13114 | |
13115 | static void emit(BytecodeGenerator* gen, VirtualRegister srcDst) |
13116 | { |
13117 | |
13118 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, srcDst) |
13119 | || emit<OpcodeSize::Wide, Assert, true>(gen, srcDst); |
13120 | } |
13121 | |
13122 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
13123 | static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst) |
13124 | { |
13125 | bool didEmit = emitImpl<size, recordOpcode>(gen, srcDst); |
13126 | if (shouldAssert == Assert) |
13127 | ASSERT(didEmit); |
13128 | return didEmit; |
13129 | } |
13130 | |
13131 | private: |
13132 | template<OpcodeSize size, bool recordOpcode> |
13133 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst) |
13134 | { |
13135 | if (size == OpcodeSize::Wide) |
13136 | gen->alignWideOpcode(); |
13137 | if (Fits<unsigned, size>::check(opcodeID) |
13138 | && Fits<VirtualRegister, size>::check(srcDst) |
13139 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
13140 | if (recordOpcode) |
13141 | gen->recordOpcode(opcodeID); |
13142 | if (size == OpcodeSize::Wide) |
13143 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
13144 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
13145 | gen->write(Fits<VirtualRegister, size>::convert(srcDst)); |
13146 | return true; |
13147 | } |
13148 | return false; |
13149 | } |
13150 | |
13151 | public: |
13152 | template<typename Block> |
13153 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
13154 | { |
13155 | dumper->printLocationAndOp(__location, &"*inc" [!__isWide]); |
13156 | dumper->dumpOperand(m_srcDst, true); |
13157 | } |
13158 | |
13159 | OpInc(const uint8_t* stream) |
13160 | : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
13161 | { |
13162 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13163 | } |
13164 | |
13165 | OpInc(const uint32_t* stream) |
13166 | : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
13167 | { |
13168 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13169 | } |
13170 | |
13171 | static OpInc decode(const uint8_t* stream) |
13172 | { |
13173 | if (*stream != op_wide) |
13174 | return { stream }; |
13175 | |
13176 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
13177 | return { wideStream }; |
13178 | } |
13179 | |
13180 | template<typename Functor> |
13181 | void setSrcDst(VirtualRegister value, Functor func) |
13182 | { |
13183 | if (isWide()) |
13184 | setSrcDst<OpcodeSize::Wide>(value, func); |
13185 | else |
13186 | setSrcDst<OpcodeSize::Narrow>(value, func); |
13187 | } |
13188 | |
13189 | template <OpcodeSize size, typename Functor> |
13190 | void setSrcDst(VirtualRegister value, Functor func) |
13191 | { |
13192 | if (!Fits<VirtualRegister, size>::check(value)) |
13193 | value = func(); |
13194 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
13195 | *stream = Fits<VirtualRegister, size>::convert(value); |
13196 | } |
13197 | |
13198 | VirtualRegister m_srcDst; |
13199 | }; |
13200 | |
13201 | struct OpDec : public Instruction { |
13202 | static constexpr OpcodeID opcodeID = op_dec; |
13203 | |
13204 | static void emit(BytecodeGenerator* gen, VirtualRegister srcDst) |
13205 | { |
13206 | |
13207 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, srcDst) |
13208 | || emit<OpcodeSize::Wide, Assert, true>(gen, srcDst); |
13209 | } |
13210 | |
13211 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
13212 | static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst) |
13213 | { |
13214 | bool didEmit = emitImpl<size, recordOpcode>(gen, srcDst); |
13215 | if (shouldAssert == Assert) |
13216 | ASSERT(didEmit); |
13217 | return didEmit; |
13218 | } |
13219 | |
13220 | private: |
13221 | template<OpcodeSize size, bool recordOpcode> |
13222 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst) |
13223 | { |
13224 | if (size == OpcodeSize::Wide) |
13225 | gen->alignWideOpcode(); |
13226 | if (Fits<unsigned, size>::check(opcodeID) |
13227 | && Fits<VirtualRegister, size>::check(srcDst) |
13228 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
13229 | if (recordOpcode) |
13230 | gen->recordOpcode(opcodeID); |
13231 | if (size == OpcodeSize::Wide) |
13232 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
13233 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
13234 | gen->write(Fits<VirtualRegister, size>::convert(srcDst)); |
13235 | return true; |
13236 | } |
13237 | return false; |
13238 | } |
13239 | |
13240 | public: |
13241 | template<typename Block> |
13242 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
13243 | { |
13244 | dumper->printLocationAndOp(__location, &"*dec" [!__isWide]); |
13245 | dumper->dumpOperand(m_srcDst, true); |
13246 | } |
13247 | |
13248 | OpDec(const uint8_t* stream) |
13249 | : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
13250 | { |
13251 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13252 | } |
13253 | |
13254 | OpDec(const uint32_t* stream) |
13255 | : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
13256 | { |
13257 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13258 | } |
13259 | |
13260 | static OpDec decode(const uint8_t* stream) |
13261 | { |
13262 | if (*stream != op_wide) |
13263 | return { stream }; |
13264 | |
13265 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
13266 | return { wideStream }; |
13267 | } |
13268 | |
13269 | template<typename Functor> |
13270 | void setSrcDst(VirtualRegister value, Functor func) |
13271 | { |
13272 | if (isWide()) |
13273 | setSrcDst<OpcodeSize::Wide>(value, func); |
13274 | else |
13275 | setSrcDst<OpcodeSize::Narrow>(value, func); |
13276 | } |
13277 | |
13278 | template <OpcodeSize size, typename Functor> |
13279 | void setSrcDst(VirtualRegister value, Functor func) |
13280 | { |
13281 | if (!Fits<VirtualRegister, size>::check(value)) |
13282 | value = func(); |
13283 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
13284 | *stream = Fits<VirtualRegister, size>::convert(value); |
13285 | } |
13286 | |
13287 | VirtualRegister m_srcDst; |
13288 | }; |
13289 | |
13290 | struct OpNot : public Instruction { |
13291 | static constexpr OpcodeID opcodeID = op_not; |
13292 | |
13293 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
13294 | { |
13295 | |
13296 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand) |
13297 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand); |
13298 | } |
13299 | |
13300 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
13301 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
13302 | { |
13303 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand); |
13304 | if (shouldAssert == Assert) |
13305 | ASSERT(didEmit); |
13306 | return didEmit; |
13307 | } |
13308 | |
13309 | private: |
13310 | template<OpcodeSize size, bool recordOpcode> |
13311 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand) |
13312 | { |
13313 | if (size == OpcodeSize::Wide) |
13314 | gen->alignWideOpcode(); |
13315 | if (Fits<unsigned, size>::check(opcodeID) |
13316 | && Fits<VirtualRegister, size>::check(dst) |
13317 | && Fits<VirtualRegister, size>::check(operand) |
13318 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
13319 | if (recordOpcode) |
13320 | gen->recordOpcode(opcodeID); |
13321 | if (size == OpcodeSize::Wide) |
13322 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
13323 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
13324 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
13325 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
13326 | return true; |
13327 | } |
13328 | return false; |
13329 | } |
13330 | |
13331 | public: |
13332 | template<typename Block> |
13333 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
13334 | { |
13335 | dumper->printLocationAndOp(__location, &"*not" [!__isWide]); |
13336 | dumper->dumpOperand(m_dst, true); |
13337 | dumper->dumpOperand(m_operand, false); |
13338 | } |
13339 | |
13340 | OpNot(const uint8_t* stream) |
13341 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
13342 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
13343 | { |
13344 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13345 | } |
13346 | |
13347 | OpNot(const uint32_t* stream) |
13348 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
13349 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
13350 | { |
13351 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13352 | } |
13353 | |
13354 | static OpNot decode(const uint8_t* stream) |
13355 | { |
13356 | if (*stream != op_wide) |
13357 | return { stream }; |
13358 | |
13359 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
13360 | return { wideStream }; |
13361 | } |
13362 | |
13363 | template<typename Functor> |
13364 | void setDst(VirtualRegister value, Functor func) |
13365 | { |
13366 | if (isWide()) |
13367 | setDst<OpcodeSize::Wide>(value, func); |
13368 | else |
13369 | setDst<OpcodeSize::Narrow>(value, func); |
13370 | } |
13371 | |
13372 | template <OpcodeSize size, typename Functor> |
13373 | void setDst(VirtualRegister value, Functor func) |
13374 | { |
13375 | if (!Fits<VirtualRegister, size>::check(value)) |
13376 | value = func(); |
13377 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
13378 | *stream = Fits<VirtualRegister, size>::convert(value); |
13379 | } |
13380 | |
13381 | template<typename Functor> |
13382 | void setOperand(VirtualRegister value, Functor func) |
13383 | { |
13384 | if (isWide()) |
13385 | setOperand<OpcodeSize::Wide>(value, func); |
13386 | else |
13387 | setOperand<OpcodeSize::Narrow>(value, func); |
13388 | } |
13389 | |
13390 | template <OpcodeSize size, typename Functor> |
13391 | void setOperand(VirtualRegister value, Functor func) |
13392 | { |
13393 | if (!Fits<VirtualRegister, size>::check(value)) |
13394 | value = func(); |
13395 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
13396 | *stream = Fits<VirtualRegister, size>::convert(value); |
13397 | } |
13398 | |
13399 | VirtualRegister m_dst; |
13400 | VirtualRegister m_operand; |
13401 | }; |
13402 | |
13403 | struct OpIdentityWithProfile : public Instruction { |
13404 | static constexpr OpcodeID opcodeID = op_identity_with_profile; |
13405 | |
13406 | static void emit(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned topProfile, unsigned bottomProfile) |
13407 | { |
13408 | |
13409 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, srcDst, topProfile, bottomProfile) |
13410 | || emit<OpcodeSize::Wide, Assert, true>(gen, srcDst, topProfile, bottomProfile); |
13411 | } |
13412 | |
13413 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
13414 | static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned topProfile, unsigned bottomProfile) |
13415 | { |
13416 | bool didEmit = emitImpl<size, recordOpcode>(gen, srcDst, topProfile, bottomProfile); |
13417 | if (shouldAssert == Assert) |
13418 | ASSERT(didEmit); |
13419 | return didEmit; |
13420 | } |
13421 | |
13422 | private: |
13423 | template<OpcodeSize size, bool recordOpcode> |
13424 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned topProfile, unsigned bottomProfile) |
13425 | { |
13426 | if (size == OpcodeSize::Wide) |
13427 | gen->alignWideOpcode(); |
13428 | if (Fits<unsigned, size>::check(opcodeID) |
13429 | && Fits<VirtualRegister, size>::check(srcDst) |
13430 | && Fits<unsigned, size>::check(topProfile) |
13431 | && Fits<unsigned, size>::check(bottomProfile) |
13432 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
13433 | if (recordOpcode) |
13434 | gen->recordOpcode(opcodeID); |
13435 | if (size == OpcodeSize::Wide) |
13436 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
13437 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
13438 | gen->write(Fits<VirtualRegister, size>::convert(srcDst)); |
13439 | gen->write(Fits<unsigned, size>::convert(topProfile)); |
13440 | gen->write(Fits<unsigned, size>::convert(bottomProfile)); |
13441 | return true; |
13442 | } |
13443 | return false; |
13444 | } |
13445 | |
13446 | public: |
13447 | template<typename Block> |
13448 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
13449 | { |
13450 | dumper->printLocationAndOp(__location, &"*identity_with_profile" [!__isWide]); |
13451 | dumper->dumpOperand(m_srcDst, true); |
13452 | dumper->dumpOperand(m_topProfile, false); |
13453 | dumper->dumpOperand(m_bottomProfile, false); |
13454 | } |
13455 | |
13456 | OpIdentityWithProfile(const uint8_t* stream) |
13457 | : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
13458 | , m_topProfile(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2])) |
13459 | , m_bottomProfile(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
13460 | { |
13461 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13462 | } |
13463 | |
13464 | OpIdentityWithProfile(const uint32_t* stream) |
13465 | : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
13466 | , m_topProfile(Fits<unsigned, OpcodeSize::Wide>::convert(stream[2])) |
13467 | , m_bottomProfile(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
13468 | { |
13469 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13470 | } |
13471 | |
13472 | static OpIdentityWithProfile decode(const uint8_t* stream) |
13473 | { |
13474 | if (*stream != op_wide) |
13475 | return { stream }; |
13476 | |
13477 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
13478 | return { wideStream }; |
13479 | } |
13480 | |
13481 | template<typename Functor> |
13482 | void setSrcDst(VirtualRegister value, Functor func) |
13483 | { |
13484 | if (isWide()) |
13485 | setSrcDst<OpcodeSize::Wide>(value, func); |
13486 | else |
13487 | setSrcDst<OpcodeSize::Narrow>(value, func); |
13488 | } |
13489 | |
13490 | template <OpcodeSize size, typename Functor> |
13491 | void setSrcDst(VirtualRegister value, Functor func) |
13492 | { |
13493 | if (!Fits<VirtualRegister, size>::check(value)) |
13494 | value = func(); |
13495 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
13496 | *stream = Fits<VirtualRegister, size>::convert(value); |
13497 | } |
13498 | |
13499 | template<typename Functor> |
13500 | void setTopProfile(unsigned value, Functor func) |
13501 | { |
13502 | if (isWide()) |
13503 | setTopProfile<OpcodeSize::Wide>(value, func); |
13504 | else |
13505 | setTopProfile<OpcodeSize::Narrow>(value, func); |
13506 | } |
13507 | |
13508 | template <OpcodeSize size, typename Functor> |
13509 | void setTopProfile(unsigned value, Functor func) |
13510 | { |
13511 | if (!Fits<unsigned, size>::check(value)) |
13512 | value = func(); |
13513 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
13514 | *stream = Fits<unsigned, size>::convert(value); |
13515 | } |
13516 | |
13517 | template<typename Functor> |
13518 | void setBottomProfile(unsigned value, Functor func) |
13519 | { |
13520 | if (isWide()) |
13521 | setBottomProfile<OpcodeSize::Wide>(value, func); |
13522 | else |
13523 | setBottomProfile<OpcodeSize::Narrow>(value, func); |
13524 | } |
13525 | |
13526 | template <OpcodeSize size, typename Functor> |
13527 | void setBottomProfile(unsigned value, Functor func) |
13528 | { |
13529 | if (!Fits<unsigned, size>::check(value)) |
13530 | value = func(); |
13531 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
13532 | *stream = Fits<unsigned, size>::convert(value); |
13533 | } |
13534 | |
13535 | VirtualRegister m_srcDst; |
13536 | unsigned m_topProfile; |
13537 | unsigned m_bottomProfile; |
13538 | }; |
13539 | |
13540 | struct OpOverridesHasInstance : public Instruction { |
13541 | static constexpr OpcodeID opcodeID = op_overrides_has_instance; |
13542 | |
13543 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister constructor, VirtualRegister hasInstanceValue) |
13544 | { |
13545 | |
13546 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, constructor, hasInstanceValue) |
13547 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, constructor, hasInstanceValue); |
13548 | } |
13549 | |
13550 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
13551 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister constructor, VirtualRegister hasInstanceValue) |
13552 | { |
13553 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, constructor, hasInstanceValue); |
13554 | if (shouldAssert == Assert) |
13555 | ASSERT(didEmit); |
13556 | return didEmit; |
13557 | } |
13558 | |
13559 | private: |
13560 | template<OpcodeSize size, bool recordOpcode> |
13561 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister constructor, VirtualRegister hasInstanceValue) |
13562 | { |
13563 | if (size == OpcodeSize::Wide) |
13564 | gen->alignWideOpcode(); |
13565 | if (Fits<unsigned, size>::check(opcodeID) |
13566 | && Fits<VirtualRegister, size>::check(dst) |
13567 | && Fits<VirtualRegister, size>::check(constructor) |
13568 | && Fits<VirtualRegister, size>::check(hasInstanceValue) |
13569 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
13570 | if (recordOpcode) |
13571 | gen->recordOpcode(opcodeID); |
13572 | if (size == OpcodeSize::Wide) |
13573 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
13574 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
13575 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
13576 | gen->write(Fits<VirtualRegister, size>::convert(constructor)); |
13577 | gen->write(Fits<VirtualRegister, size>::convert(hasInstanceValue)); |
13578 | return true; |
13579 | } |
13580 | return false; |
13581 | } |
13582 | |
13583 | public: |
13584 | template<typename Block> |
13585 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
13586 | { |
13587 | dumper->printLocationAndOp(__location, &"*overrides_has_instance" [!__isWide]); |
13588 | dumper->dumpOperand(m_dst, true); |
13589 | dumper->dumpOperand(m_constructor, false); |
13590 | dumper->dumpOperand(m_hasInstanceValue, false); |
13591 | } |
13592 | |
13593 | OpOverridesHasInstance(const uint8_t* stream) |
13594 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
13595 | , m_constructor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
13596 | , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
13597 | { |
13598 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13599 | } |
13600 | |
13601 | OpOverridesHasInstance(const uint32_t* stream) |
13602 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
13603 | , m_constructor(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
13604 | , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
13605 | { |
13606 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13607 | } |
13608 | |
13609 | static OpOverridesHasInstance decode(const uint8_t* stream) |
13610 | { |
13611 | if (*stream != op_wide) |
13612 | return { stream }; |
13613 | |
13614 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
13615 | return { wideStream }; |
13616 | } |
13617 | |
13618 | template<typename Functor> |
13619 | void setDst(VirtualRegister value, Functor func) |
13620 | { |
13621 | if (isWide()) |
13622 | setDst<OpcodeSize::Wide>(value, func); |
13623 | else |
13624 | setDst<OpcodeSize::Narrow>(value, func); |
13625 | } |
13626 | |
13627 | template <OpcodeSize size, typename Functor> |
13628 | void setDst(VirtualRegister value, Functor func) |
13629 | { |
13630 | if (!Fits<VirtualRegister, size>::check(value)) |
13631 | value = func(); |
13632 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
13633 | *stream = Fits<VirtualRegister, size>::convert(value); |
13634 | } |
13635 | |
13636 | template<typename Functor> |
13637 | void setConstructor(VirtualRegister value, Functor func) |
13638 | { |
13639 | if (isWide()) |
13640 | setConstructor<OpcodeSize::Wide>(value, func); |
13641 | else |
13642 | setConstructor<OpcodeSize::Narrow>(value, func); |
13643 | } |
13644 | |
13645 | template <OpcodeSize size, typename Functor> |
13646 | void setConstructor(VirtualRegister value, Functor func) |
13647 | { |
13648 | if (!Fits<VirtualRegister, size>::check(value)) |
13649 | value = func(); |
13650 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
13651 | *stream = Fits<VirtualRegister, size>::convert(value); |
13652 | } |
13653 | |
13654 | template<typename Functor> |
13655 | void setHasInstanceValue(VirtualRegister value, Functor func) |
13656 | { |
13657 | if (isWide()) |
13658 | setHasInstanceValue<OpcodeSize::Wide>(value, func); |
13659 | else |
13660 | setHasInstanceValue<OpcodeSize::Narrow>(value, func); |
13661 | } |
13662 | |
13663 | template <OpcodeSize size, typename Functor> |
13664 | void setHasInstanceValue(VirtualRegister value, Functor func) |
13665 | { |
13666 | if (!Fits<VirtualRegister, size>::check(value)) |
13667 | value = func(); |
13668 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
13669 | *stream = Fits<VirtualRegister, size>::convert(value); |
13670 | } |
13671 | |
13672 | VirtualRegister m_dst; |
13673 | VirtualRegister m_constructor; |
13674 | VirtualRegister m_hasInstanceValue; |
13675 | }; |
13676 | |
13677 | struct OpInstanceof : public Instruction { |
13678 | static constexpr OpcodeID opcodeID = op_instanceof; |
13679 | |
13680 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister prototype) |
13681 | { |
13682 | |
13683 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, value, prototype) |
13684 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, value, prototype); |
13685 | } |
13686 | |
13687 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
13688 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister prototype) |
13689 | { |
13690 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, value, prototype); |
13691 | if (shouldAssert == Assert) |
13692 | ASSERT(didEmit); |
13693 | return didEmit; |
13694 | } |
13695 | |
13696 | private: |
13697 | template<OpcodeSize size, bool recordOpcode> |
13698 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister prototype) |
13699 | { |
13700 | if (size == OpcodeSize::Wide) |
13701 | gen->alignWideOpcode(); |
13702 | if (Fits<unsigned, size>::check(opcodeID) |
13703 | && Fits<VirtualRegister, size>::check(dst) |
13704 | && Fits<VirtualRegister, size>::check(value) |
13705 | && Fits<VirtualRegister, size>::check(prototype) |
13706 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
13707 | if (recordOpcode) |
13708 | gen->recordOpcode(opcodeID); |
13709 | if (size == OpcodeSize::Wide) |
13710 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
13711 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
13712 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
13713 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
13714 | gen->write(Fits<VirtualRegister, size>::convert(prototype)); |
13715 | return true; |
13716 | } |
13717 | return false; |
13718 | } |
13719 | |
13720 | public: |
13721 | template<typename Block> |
13722 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
13723 | { |
13724 | dumper->printLocationAndOp(__location, &"*instanceof" [!__isWide]); |
13725 | dumper->dumpOperand(m_dst, true); |
13726 | dumper->dumpOperand(m_value, false); |
13727 | dumper->dumpOperand(m_prototype, false); |
13728 | } |
13729 | |
13730 | OpInstanceof(const uint8_t* stream) |
13731 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
13732 | , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
13733 | , m_prototype(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
13734 | { |
13735 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13736 | } |
13737 | |
13738 | OpInstanceof(const uint32_t* stream) |
13739 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
13740 | , m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
13741 | , m_prototype(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
13742 | { |
13743 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13744 | } |
13745 | |
13746 | static OpInstanceof decode(const uint8_t* stream) |
13747 | { |
13748 | if (*stream != op_wide) |
13749 | return { stream }; |
13750 | |
13751 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
13752 | return { wideStream }; |
13753 | } |
13754 | |
13755 | template<typename Functor> |
13756 | void setDst(VirtualRegister value, Functor func) |
13757 | { |
13758 | if (isWide()) |
13759 | setDst<OpcodeSize::Wide>(value, func); |
13760 | else |
13761 | setDst<OpcodeSize::Narrow>(value, func); |
13762 | } |
13763 | |
13764 | template <OpcodeSize size, typename Functor> |
13765 | void setDst(VirtualRegister value, Functor func) |
13766 | { |
13767 | if (!Fits<VirtualRegister, size>::check(value)) |
13768 | value = func(); |
13769 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
13770 | *stream = Fits<VirtualRegister, size>::convert(value); |
13771 | } |
13772 | |
13773 | template<typename Functor> |
13774 | void setValue(VirtualRegister value, Functor func) |
13775 | { |
13776 | if (isWide()) |
13777 | setValue<OpcodeSize::Wide>(value, func); |
13778 | else |
13779 | setValue<OpcodeSize::Narrow>(value, func); |
13780 | } |
13781 | |
13782 | template <OpcodeSize size, typename Functor> |
13783 | void setValue(VirtualRegister value, Functor func) |
13784 | { |
13785 | if (!Fits<VirtualRegister, size>::check(value)) |
13786 | value = func(); |
13787 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
13788 | *stream = Fits<VirtualRegister, size>::convert(value); |
13789 | } |
13790 | |
13791 | template<typename Functor> |
13792 | void setPrototype(VirtualRegister value, Functor func) |
13793 | { |
13794 | if (isWide()) |
13795 | setPrototype<OpcodeSize::Wide>(value, func); |
13796 | else |
13797 | setPrototype<OpcodeSize::Narrow>(value, func); |
13798 | } |
13799 | |
13800 | template <OpcodeSize size, typename Functor> |
13801 | void setPrototype(VirtualRegister value, Functor func) |
13802 | { |
13803 | if (!Fits<VirtualRegister, size>::check(value)) |
13804 | value = func(); |
13805 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
13806 | *stream = Fits<VirtualRegister, size>::convert(value); |
13807 | } |
13808 | |
13809 | VirtualRegister m_dst; |
13810 | VirtualRegister m_value; |
13811 | VirtualRegister m_prototype; |
13812 | }; |
13813 | |
13814 | struct OpInstanceofCustom : public Instruction { |
13815 | static constexpr OpcodeID opcodeID = op_instanceof_custom; |
13816 | |
13817 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister constructor, VirtualRegister hasInstanceValue) |
13818 | { |
13819 | |
13820 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, value, constructor, hasInstanceValue) |
13821 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, value, constructor, hasInstanceValue); |
13822 | } |
13823 | |
13824 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
13825 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister constructor, VirtualRegister hasInstanceValue) |
13826 | { |
13827 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, value, constructor, hasInstanceValue); |
13828 | if (shouldAssert == Assert) |
13829 | ASSERT(didEmit); |
13830 | return didEmit; |
13831 | } |
13832 | |
13833 | private: |
13834 | template<OpcodeSize size, bool recordOpcode> |
13835 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister constructor, VirtualRegister hasInstanceValue) |
13836 | { |
13837 | if (size == OpcodeSize::Wide) |
13838 | gen->alignWideOpcode(); |
13839 | if (Fits<unsigned, size>::check(opcodeID) |
13840 | && Fits<VirtualRegister, size>::check(dst) |
13841 | && Fits<VirtualRegister, size>::check(value) |
13842 | && Fits<VirtualRegister, size>::check(constructor) |
13843 | && Fits<VirtualRegister, size>::check(hasInstanceValue) |
13844 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
13845 | if (recordOpcode) |
13846 | gen->recordOpcode(opcodeID); |
13847 | if (size == OpcodeSize::Wide) |
13848 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
13849 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
13850 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
13851 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
13852 | gen->write(Fits<VirtualRegister, size>::convert(constructor)); |
13853 | gen->write(Fits<VirtualRegister, size>::convert(hasInstanceValue)); |
13854 | return true; |
13855 | } |
13856 | return false; |
13857 | } |
13858 | |
13859 | public: |
13860 | template<typename Block> |
13861 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
13862 | { |
13863 | dumper->printLocationAndOp(__location, &"*instanceof_custom" [!__isWide]); |
13864 | dumper->dumpOperand(m_dst, true); |
13865 | dumper->dumpOperand(m_value, false); |
13866 | dumper->dumpOperand(m_constructor, false); |
13867 | dumper->dumpOperand(m_hasInstanceValue, false); |
13868 | } |
13869 | |
13870 | OpInstanceofCustom(const uint8_t* stream) |
13871 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
13872 | , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
13873 | , m_constructor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
13874 | , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
13875 | { |
13876 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13877 | } |
13878 | |
13879 | OpInstanceofCustom(const uint32_t* stream) |
13880 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
13881 | , m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
13882 | , m_constructor(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
13883 | , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
13884 | { |
13885 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
13886 | } |
13887 | |
13888 | static OpInstanceofCustom decode(const uint8_t* stream) |
13889 | { |
13890 | if (*stream != op_wide) |
13891 | return { stream }; |
13892 | |
13893 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
13894 | return { wideStream }; |
13895 | } |
13896 | |
13897 | template<typename Functor> |
13898 | void setDst(VirtualRegister value, Functor func) |
13899 | { |
13900 | if (isWide()) |
13901 | setDst<OpcodeSize::Wide>(value, func); |
13902 | else |
13903 | setDst<OpcodeSize::Narrow>(value, func); |
13904 | } |
13905 | |
13906 | template <OpcodeSize size, typename Functor> |
13907 | void setDst(VirtualRegister value, Functor func) |
13908 | { |
13909 | if (!Fits<VirtualRegister, size>::check(value)) |
13910 | value = func(); |
13911 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
13912 | *stream = Fits<VirtualRegister, size>::convert(value); |
13913 | } |
13914 | |
13915 | template<typename Functor> |
13916 | void setValue(VirtualRegister value, Functor func) |
13917 | { |
13918 | if (isWide()) |
13919 | setValue<OpcodeSize::Wide>(value, func); |
13920 | else |
13921 | setValue<OpcodeSize::Narrow>(value, func); |
13922 | } |
13923 | |
13924 | template <OpcodeSize size, typename Functor> |
13925 | void setValue(VirtualRegister value, Functor func) |
13926 | { |
13927 | if (!Fits<VirtualRegister, size>::check(value)) |
13928 | value = func(); |
13929 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
13930 | *stream = Fits<VirtualRegister, size>::convert(value); |
13931 | } |
13932 | |
13933 | template<typename Functor> |
13934 | void setConstructor(VirtualRegister value, Functor func) |
13935 | { |
13936 | if (isWide()) |
13937 | setConstructor<OpcodeSize::Wide>(value, func); |
13938 | else |
13939 | setConstructor<OpcodeSize::Narrow>(value, func); |
13940 | } |
13941 | |
13942 | template <OpcodeSize size, typename Functor> |
13943 | void setConstructor(VirtualRegister value, Functor func) |
13944 | { |
13945 | if (!Fits<VirtualRegister, size>::check(value)) |
13946 | value = func(); |
13947 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
13948 | *stream = Fits<VirtualRegister, size>::convert(value); |
13949 | } |
13950 | |
13951 | template<typename Functor> |
13952 | void setHasInstanceValue(VirtualRegister value, Functor func) |
13953 | { |
13954 | if (isWide()) |
13955 | setHasInstanceValue<OpcodeSize::Wide>(value, func); |
13956 | else |
13957 | setHasInstanceValue<OpcodeSize::Narrow>(value, func); |
13958 | } |
13959 | |
13960 | template <OpcodeSize size, typename Functor> |
13961 | void setHasInstanceValue(VirtualRegister value, Functor func) |
13962 | { |
13963 | if (!Fits<VirtualRegister, size>::check(value)) |
13964 | value = func(); |
13965 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
13966 | *stream = Fits<VirtualRegister, size>::convert(value); |
13967 | } |
13968 | |
13969 | VirtualRegister m_dst; |
13970 | VirtualRegister m_value; |
13971 | VirtualRegister m_constructor; |
13972 | VirtualRegister m_hasInstanceValue; |
13973 | }; |
13974 | |
13975 | struct OpTypeof : public Instruction { |
13976 | static constexpr OpcodeID opcodeID = op_typeof; |
13977 | |
13978 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value) |
13979 | { |
13980 | |
13981 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, value) |
13982 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, value); |
13983 | } |
13984 | |
13985 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
13986 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value) |
13987 | { |
13988 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, value); |
13989 | if (shouldAssert == Assert) |
13990 | ASSERT(didEmit); |
13991 | return didEmit; |
13992 | } |
13993 | |
13994 | private: |
13995 | template<OpcodeSize size, bool recordOpcode> |
13996 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value) |
13997 | { |
13998 | if (size == OpcodeSize::Wide) |
13999 | gen->alignWideOpcode(); |
14000 | if (Fits<unsigned, size>::check(opcodeID) |
14001 | && Fits<VirtualRegister, size>::check(dst) |
14002 | && Fits<VirtualRegister, size>::check(value) |
14003 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
14004 | if (recordOpcode) |
14005 | gen->recordOpcode(opcodeID); |
14006 | if (size == OpcodeSize::Wide) |
14007 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
14008 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
14009 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
14010 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
14011 | return true; |
14012 | } |
14013 | return false; |
14014 | } |
14015 | |
14016 | public: |
14017 | template<typename Block> |
14018 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
14019 | { |
14020 | dumper->printLocationAndOp(__location, &"*typeof" [!__isWide]); |
14021 | dumper->dumpOperand(m_dst, true); |
14022 | dumper->dumpOperand(m_value, false); |
14023 | } |
14024 | |
14025 | OpTypeof(const uint8_t* stream) |
14026 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
14027 | , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
14028 | { |
14029 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14030 | } |
14031 | |
14032 | OpTypeof(const uint32_t* stream) |
14033 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
14034 | , m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
14035 | { |
14036 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14037 | } |
14038 | |
14039 | static OpTypeof decode(const uint8_t* stream) |
14040 | { |
14041 | if (*stream != op_wide) |
14042 | return { stream }; |
14043 | |
14044 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
14045 | return { wideStream }; |
14046 | } |
14047 | |
14048 | template<typename Functor> |
14049 | void setDst(VirtualRegister value, Functor func) |
14050 | { |
14051 | if (isWide()) |
14052 | setDst<OpcodeSize::Wide>(value, func); |
14053 | else |
14054 | setDst<OpcodeSize::Narrow>(value, func); |
14055 | } |
14056 | |
14057 | template <OpcodeSize size, typename Functor> |
14058 | void setDst(VirtualRegister value, Functor func) |
14059 | { |
14060 | if (!Fits<VirtualRegister, size>::check(value)) |
14061 | value = func(); |
14062 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
14063 | *stream = Fits<VirtualRegister, size>::convert(value); |
14064 | } |
14065 | |
14066 | template<typename Functor> |
14067 | void setValue(VirtualRegister value, Functor func) |
14068 | { |
14069 | if (isWide()) |
14070 | setValue<OpcodeSize::Wide>(value, func); |
14071 | else |
14072 | setValue<OpcodeSize::Narrow>(value, func); |
14073 | } |
14074 | |
14075 | template <OpcodeSize size, typename Functor> |
14076 | void setValue(VirtualRegister value, Functor func) |
14077 | { |
14078 | if (!Fits<VirtualRegister, size>::check(value)) |
14079 | value = func(); |
14080 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
14081 | *stream = Fits<VirtualRegister, size>::convert(value); |
14082 | } |
14083 | |
14084 | VirtualRegister m_dst; |
14085 | VirtualRegister m_value; |
14086 | }; |
14087 | |
14088 | struct OpIsCellWithType : public Instruction { |
14089 | static constexpr OpcodeID opcodeID = op_is_cell_with_type; |
14090 | |
14091 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, JSType type) |
14092 | { |
14093 | |
14094 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand, type) |
14095 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, operand, type); |
14096 | } |
14097 | |
14098 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
14099 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, JSType type) |
14100 | { |
14101 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand, type); |
14102 | if (shouldAssert == Assert) |
14103 | ASSERT(didEmit); |
14104 | return didEmit; |
14105 | } |
14106 | |
14107 | private: |
14108 | template<OpcodeSize size, bool recordOpcode> |
14109 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, JSType type) |
14110 | { |
14111 | if (size == OpcodeSize::Wide) |
14112 | gen->alignWideOpcode(); |
14113 | if (Fits<unsigned, size>::check(opcodeID) |
14114 | && Fits<VirtualRegister, size>::check(dst) |
14115 | && Fits<VirtualRegister, size>::check(operand) |
14116 | && Fits<JSType, size>::check(type) |
14117 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
14118 | if (recordOpcode) |
14119 | gen->recordOpcode(opcodeID); |
14120 | if (size == OpcodeSize::Wide) |
14121 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
14122 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
14123 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
14124 | gen->write(Fits<VirtualRegister, size>::convert(operand)); |
14125 | gen->write(Fits<JSType, size>::convert(type)); |
14126 | return true; |
14127 | } |
14128 | return false; |
14129 | } |
14130 | |
14131 | public: |
14132 | template<typename Block> |
14133 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
14134 | { |
14135 | dumper->printLocationAndOp(__location, &"*is_cell_with_type" [!__isWide]); |
14136 | dumper->dumpOperand(m_dst, true); |
14137 | dumper->dumpOperand(m_operand, false); |
14138 | dumper->dumpOperand(m_type, false); |
14139 | } |
14140 | |
14141 | OpIsCellWithType(const uint8_t* stream) |
14142 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
14143 | , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
14144 | , m_type(Fits<JSType, OpcodeSize::Narrow>::convert(stream[3])) |
14145 | { |
14146 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14147 | } |
14148 | |
14149 | OpIsCellWithType(const uint32_t* stream) |
14150 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
14151 | , m_operand(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
14152 | , m_type(Fits<JSType, OpcodeSize::Wide>::convert(stream[3])) |
14153 | { |
14154 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14155 | } |
14156 | |
14157 | static OpIsCellWithType decode(const uint8_t* stream) |
14158 | { |
14159 | if (*stream != op_wide) |
14160 | return { stream }; |
14161 | |
14162 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
14163 | return { wideStream }; |
14164 | } |
14165 | |
14166 | template<typename Functor> |
14167 | void setDst(VirtualRegister value, Functor func) |
14168 | { |
14169 | if (isWide()) |
14170 | setDst<OpcodeSize::Wide>(value, func); |
14171 | else |
14172 | setDst<OpcodeSize::Narrow>(value, func); |
14173 | } |
14174 | |
14175 | template <OpcodeSize size, typename Functor> |
14176 | void setDst(VirtualRegister value, Functor func) |
14177 | { |
14178 | if (!Fits<VirtualRegister, size>::check(value)) |
14179 | value = func(); |
14180 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
14181 | *stream = Fits<VirtualRegister, size>::convert(value); |
14182 | } |
14183 | |
14184 | template<typename Functor> |
14185 | void setOperand(VirtualRegister value, Functor func) |
14186 | { |
14187 | if (isWide()) |
14188 | setOperand<OpcodeSize::Wide>(value, func); |
14189 | else |
14190 | setOperand<OpcodeSize::Narrow>(value, func); |
14191 | } |
14192 | |
14193 | template <OpcodeSize size, typename Functor> |
14194 | void setOperand(VirtualRegister value, Functor func) |
14195 | { |
14196 | if (!Fits<VirtualRegister, size>::check(value)) |
14197 | value = func(); |
14198 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
14199 | *stream = Fits<VirtualRegister, size>::convert(value); |
14200 | } |
14201 | |
14202 | template<typename Functor> |
14203 | void setType(JSType value, Functor func) |
14204 | { |
14205 | if (isWide()) |
14206 | setType<OpcodeSize::Wide>(value, func); |
14207 | else |
14208 | setType<OpcodeSize::Narrow>(value, func); |
14209 | } |
14210 | |
14211 | template <OpcodeSize size, typename Functor> |
14212 | void setType(JSType value, Functor func) |
14213 | { |
14214 | if (!Fits<JSType, size>::check(value)) |
14215 | value = func(); |
14216 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
14217 | *stream = Fits<JSType, size>::convert(value); |
14218 | } |
14219 | |
14220 | VirtualRegister m_dst; |
14221 | VirtualRegister m_operand; |
14222 | JSType m_type; |
14223 | }; |
14224 | |
14225 | struct OpInById : public Instruction { |
14226 | static constexpr OpcodeID opcodeID = op_in_by_id; |
14227 | |
14228 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property) |
14229 | { |
14230 | |
14231 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property) |
14232 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, property); |
14233 | } |
14234 | |
14235 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
14236 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property) |
14237 | { |
14238 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property); |
14239 | if (shouldAssert == Assert) |
14240 | ASSERT(didEmit); |
14241 | return didEmit; |
14242 | } |
14243 | |
14244 | private: |
14245 | template<OpcodeSize size, bool recordOpcode> |
14246 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property) |
14247 | { |
14248 | if (size == OpcodeSize::Wide) |
14249 | gen->alignWideOpcode(); |
14250 | if (Fits<unsigned, size>::check(opcodeID) |
14251 | && Fits<VirtualRegister, size>::check(dst) |
14252 | && Fits<VirtualRegister, size>::check(base) |
14253 | && Fits<unsigned, size>::check(property) |
14254 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
14255 | if (recordOpcode) |
14256 | gen->recordOpcode(opcodeID); |
14257 | if (size == OpcodeSize::Wide) |
14258 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
14259 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
14260 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
14261 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
14262 | gen->write(Fits<unsigned, size>::convert(property)); |
14263 | return true; |
14264 | } |
14265 | return false; |
14266 | } |
14267 | |
14268 | public: |
14269 | template<typename Block> |
14270 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
14271 | { |
14272 | dumper->printLocationAndOp(__location, &"*in_by_id" [!__isWide]); |
14273 | dumper->dumpOperand(m_dst, true); |
14274 | dumper->dumpOperand(m_base, false); |
14275 | dumper->dumpOperand(m_property, false); |
14276 | } |
14277 | |
14278 | OpInById(const uint8_t* stream) |
14279 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
14280 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
14281 | , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
14282 | { |
14283 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14284 | } |
14285 | |
14286 | OpInById(const uint32_t* stream) |
14287 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
14288 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
14289 | , m_property(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
14290 | { |
14291 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14292 | } |
14293 | |
14294 | static OpInById decode(const uint8_t* stream) |
14295 | { |
14296 | if (*stream != op_wide) |
14297 | return { stream }; |
14298 | |
14299 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
14300 | return { wideStream }; |
14301 | } |
14302 | |
14303 | template<typename Functor> |
14304 | void setDst(VirtualRegister value, Functor func) |
14305 | { |
14306 | if (isWide()) |
14307 | setDst<OpcodeSize::Wide>(value, func); |
14308 | else |
14309 | setDst<OpcodeSize::Narrow>(value, func); |
14310 | } |
14311 | |
14312 | template <OpcodeSize size, typename Functor> |
14313 | void setDst(VirtualRegister value, Functor func) |
14314 | { |
14315 | if (!Fits<VirtualRegister, size>::check(value)) |
14316 | value = func(); |
14317 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
14318 | *stream = Fits<VirtualRegister, size>::convert(value); |
14319 | } |
14320 | |
14321 | template<typename Functor> |
14322 | void setBase(VirtualRegister value, Functor func) |
14323 | { |
14324 | if (isWide()) |
14325 | setBase<OpcodeSize::Wide>(value, func); |
14326 | else |
14327 | setBase<OpcodeSize::Narrow>(value, func); |
14328 | } |
14329 | |
14330 | template <OpcodeSize size, typename Functor> |
14331 | void setBase(VirtualRegister value, Functor func) |
14332 | { |
14333 | if (!Fits<VirtualRegister, size>::check(value)) |
14334 | value = func(); |
14335 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
14336 | *stream = Fits<VirtualRegister, size>::convert(value); |
14337 | } |
14338 | |
14339 | template<typename Functor> |
14340 | void setProperty(unsigned value, Functor func) |
14341 | { |
14342 | if (isWide()) |
14343 | setProperty<OpcodeSize::Wide>(value, func); |
14344 | else |
14345 | setProperty<OpcodeSize::Narrow>(value, func); |
14346 | } |
14347 | |
14348 | template <OpcodeSize size, typename Functor> |
14349 | void setProperty(unsigned value, Functor func) |
14350 | { |
14351 | if (!Fits<unsigned, size>::check(value)) |
14352 | value = func(); |
14353 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
14354 | *stream = Fits<unsigned, size>::convert(value); |
14355 | } |
14356 | |
14357 | VirtualRegister m_dst; |
14358 | VirtualRegister m_base; |
14359 | unsigned m_property; |
14360 | }; |
14361 | |
14362 | struct OpPutByIdWithThis : public Instruction { |
14363 | static constexpr OpcodeID opcodeID = op_put_by_id_with_this; |
14364 | |
14365 | static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, unsigned property, VirtualRegister value) |
14366 | { |
14367 | |
14368 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, thisValue, property, value) |
14369 | || emit<OpcodeSize::Wide, Assert, true>(gen, base, thisValue, property, value); |
14370 | } |
14371 | |
14372 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
14373 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, unsigned property, VirtualRegister value) |
14374 | { |
14375 | bool didEmit = emitImpl<size, recordOpcode>(gen, base, thisValue, property, value); |
14376 | if (shouldAssert == Assert) |
14377 | ASSERT(didEmit); |
14378 | return didEmit; |
14379 | } |
14380 | |
14381 | private: |
14382 | template<OpcodeSize size, bool recordOpcode> |
14383 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, unsigned property, VirtualRegister value) |
14384 | { |
14385 | if (size == OpcodeSize::Wide) |
14386 | gen->alignWideOpcode(); |
14387 | if (Fits<unsigned, size>::check(opcodeID) |
14388 | && Fits<VirtualRegister, size>::check(base) |
14389 | && Fits<VirtualRegister, size>::check(thisValue) |
14390 | && Fits<unsigned, size>::check(property) |
14391 | && Fits<VirtualRegister, size>::check(value) |
14392 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
14393 | if (recordOpcode) |
14394 | gen->recordOpcode(opcodeID); |
14395 | if (size == OpcodeSize::Wide) |
14396 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
14397 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
14398 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
14399 | gen->write(Fits<VirtualRegister, size>::convert(thisValue)); |
14400 | gen->write(Fits<unsigned, size>::convert(property)); |
14401 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
14402 | return true; |
14403 | } |
14404 | return false; |
14405 | } |
14406 | |
14407 | public: |
14408 | template<typename Block> |
14409 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
14410 | { |
14411 | dumper->printLocationAndOp(__location, &"*put_by_id_with_this" [!__isWide]); |
14412 | dumper->dumpOperand(m_base, true); |
14413 | dumper->dumpOperand(m_thisValue, false); |
14414 | dumper->dumpOperand(m_property, false); |
14415 | dumper->dumpOperand(m_value, false); |
14416 | } |
14417 | |
14418 | OpPutByIdWithThis(const uint8_t* stream) |
14419 | : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
14420 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
14421 | , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
14422 | , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
14423 | { |
14424 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14425 | } |
14426 | |
14427 | OpPutByIdWithThis(const uint32_t* stream) |
14428 | : m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
14429 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
14430 | , m_property(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
14431 | , m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
14432 | { |
14433 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14434 | } |
14435 | |
14436 | static OpPutByIdWithThis decode(const uint8_t* stream) |
14437 | { |
14438 | if (*stream != op_wide) |
14439 | return { stream }; |
14440 | |
14441 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
14442 | return { wideStream }; |
14443 | } |
14444 | |
14445 | template<typename Functor> |
14446 | void setBase(VirtualRegister value, Functor func) |
14447 | { |
14448 | if (isWide()) |
14449 | setBase<OpcodeSize::Wide>(value, func); |
14450 | else |
14451 | setBase<OpcodeSize::Narrow>(value, func); |
14452 | } |
14453 | |
14454 | template <OpcodeSize size, typename Functor> |
14455 | void setBase(VirtualRegister value, Functor func) |
14456 | { |
14457 | if (!Fits<VirtualRegister, size>::check(value)) |
14458 | value = func(); |
14459 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
14460 | *stream = Fits<VirtualRegister, size>::convert(value); |
14461 | } |
14462 | |
14463 | template<typename Functor> |
14464 | void setThisValue(VirtualRegister value, Functor func) |
14465 | { |
14466 | if (isWide()) |
14467 | setThisValue<OpcodeSize::Wide>(value, func); |
14468 | else |
14469 | setThisValue<OpcodeSize::Narrow>(value, func); |
14470 | } |
14471 | |
14472 | template <OpcodeSize size, typename Functor> |
14473 | void setThisValue(VirtualRegister value, Functor func) |
14474 | { |
14475 | if (!Fits<VirtualRegister, size>::check(value)) |
14476 | value = func(); |
14477 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
14478 | *stream = Fits<VirtualRegister, size>::convert(value); |
14479 | } |
14480 | |
14481 | template<typename Functor> |
14482 | void setProperty(unsigned value, Functor func) |
14483 | { |
14484 | if (isWide()) |
14485 | setProperty<OpcodeSize::Wide>(value, func); |
14486 | else |
14487 | setProperty<OpcodeSize::Narrow>(value, func); |
14488 | } |
14489 | |
14490 | template <OpcodeSize size, typename Functor> |
14491 | void setProperty(unsigned value, Functor func) |
14492 | { |
14493 | if (!Fits<unsigned, size>::check(value)) |
14494 | value = func(); |
14495 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
14496 | *stream = Fits<unsigned, size>::convert(value); |
14497 | } |
14498 | |
14499 | template<typename Functor> |
14500 | void setValue(VirtualRegister value, Functor func) |
14501 | { |
14502 | if (isWide()) |
14503 | setValue<OpcodeSize::Wide>(value, func); |
14504 | else |
14505 | setValue<OpcodeSize::Narrow>(value, func); |
14506 | } |
14507 | |
14508 | template <OpcodeSize size, typename Functor> |
14509 | void setValue(VirtualRegister value, Functor func) |
14510 | { |
14511 | if (!Fits<VirtualRegister, size>::check(value)) |
14512 | value = func(); |
14513 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
14514 | *stream = Fits<VirtualRegister, size>::convert(value); |
14515 | } |
14516 | |
14517 | VirtualRegister m_base; |
14518 | VirtualRegister m_thisValue; |
14519 | unsigned m_property; |
14520 | VirtualRegister m_value; |
14521 | }; |
14522 | |
14523 | struct OpDelById : public Instruction { |
14524 | static constexpr OpcodeID opcodeID = op_del_by_id; |
14525 | |
14526 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property) |
14527 | { |
14528 | |
14529 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property) |
14530 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, property); |
14531 | } |
14532 | |
14533 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
14534 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property) |
14535 | { |
14536 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property); |
14537 | if (shouldAssert == Assert) |
14538 | ASSERT(didEmit); |
14539 | return didEmit; |
14540 | } |
14541 | |
14542 | private: |
14543 | template<OpcodeSize size, bool recordOpcode> |
14544 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property) |
14545 | { |
14546 | if (size == OpcodeSize::Wide) |
14547 | gen->alignWideOpcode(); |
14548 | if (Fits<unsigned, size>::check(opcodeID) |
14549 | && Fits<VirtualRegister, size>::check(dst) |
14550 | && Fits<VirtualRegister, size>::check(base) |
14551 | && Fits<unsigned, size>::check(property) |
14552 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
14553 | if (recordOpcode) |
14554 | gen->recordOpcode(opcodeID); |
14555 | if (size == OpcodeSize::Wide) |
14556 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
14557 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
14558 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
14559 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
14560 | gen->write(Fits<unsigned, size>::convert(property)); |
14561 | return true; |
14562 | } |
14563 | return false; |
14564 | } |
14565 | |
14566 | public: |
14567 | template<typename Block> |
14568 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
14569 | { |
14570 | dumper->printLocationAndOp(__location, &"*del_by_id" [!__isWide]); |
14571 | dumper->dumpOperand(m_dst, true); |
14572 | dumper->dumpOperand(m_base, false); |
14573 | dumper->dumpOperand(m_property, false); |
14574 | } |
14575 | |
14576 | OpDelById(const uint8_t* stream) |
14577 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
14578 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
14579 | , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
14580 | { |
14581 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14582 | } |
14583 | |
14584 | OpDelById(const uint32_t* stream) |
14585 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
14586 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
14587 | , m_property(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
14588 | { |
14589 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14590 | } |
14591 | |
14592 | static OpDelById decode(const uint8_t* stream) |
14593 | { |
14594 | if (*stream != op_wide) |
14595 | return { stream }; |
14596 | |
14597 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
14598 | return { wideStream }; |
14599 | } |
14600 | |
14601 | template<typename Functor> |
14602 | void setDst(VirtualRegister value, Functor func) |
14603 | { |
14604 | if (isWide()) |
14605 | setDst<OpcodeSize::Wide>(value, func); |
14606 | else |
14607 | setDst<OpcodeSize::Narrow>(value, func); |
14608 | } |
14609 | |
14610 | template <OpcodeSize size, typename Functor> |
14611 | void setDst(VirtualRegister value, Functor func) |
14612 | { |
14613 | if (!Fits<VirtualRegister, size>::check(value)) |
14614 | value = func(); |
14615 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
14616 | *stream = Fits<VirtualRegister, size>::convert(value); |
14617 | } |
14618 | |
14619 | template<typename Functor> |
14620 | void setBase(VirtualRegister value, Functor func) |
14621 | { |
14622 | if (isWide()) |
14623 | setBase<OpcodeSize::Wide>(value, func); |
14624 | else |
14625 | setBase<OpcodeSize::Narrow>(value, func); |
14626 | } |
14627 | |
14628 | template <OpcodeSize size, typename Functor> |
14629 | void setBase(VirtualRegister value, Functor func) |
14630 | { |
14631 | if (!Fits<VirtualRegister, size>::check(value)) |
14632 | value = func(); |
14633 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
14634 | *stream = Fits<VirtualRegister, size>::convert(value); |
14635 | } |
14636 | |
14637 | template<typename Functor> |
14638 | void setProperty(unsigned value, Functor func) |
14639 | { |
14640 | if (isWide()) |
14641 | setProperty<OpcodeSize::Wide>(value, func); |
14642 | else |
14643 | setProperty<OpcodeSize::Narrow>(value, func); |
14644 | } |
14645 | |
14646 | template <OpcodeSize size, typename Functor> |
14647 | void setProperty(unsigned value, Functor func) |
14648 | { |
14649 | if (!Fits<unsigned, size>::check(value)) |
14650 | value = func(); |
14651 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
14652 | *stream = Fits<unsigned, size>::convert(value); |
14653 | } |
14654 | |
14655 | VirtualRegister m_dst; |
14656 | VirtualRegister m_base; |
14657 | unsigned m_property; |
14658 | }; |
14659 | |
14660 | struct OpPutByValWithThis : public Instruction { |
14661 | static constexpr OpcodeID opcodeID = op_put_by_val_with_this; |
14662 | |
14663 | static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, VirtualRegister value) |
14664 | { |
14665 | |
14666 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, thisValue, property, value) |
14667 | || emit<OpcodeSize::Wide, Assert, true>(gen, base, thisValue, property, value); |
14668 | } |
14669 | |
14670 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
14671 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, VirtualRegister value) |
14672 | { |
14673 | bool didEmit = emitImpl<size, recordOpcode>(gen, base, thisValue, property, value); |
14674 | if (shouldAssert == Assert) |
14675 | ASSERT(didEmit); |
14676 | return didEmit; |
14677 | } |
14678 | |
14679 | private: |
14680 | template<OpcodeSize size, bool recordOpcode> |
14681 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, VirtualRegister value) |
14682 | { |
14683 | if (size == OpcodeSize::Wide) |
14684 | gen->alignWideOpcode(); |
14685 | if (Fits<unsigned, size>::check(opcodeID) |
14686 | && Fits<VirtualRegister, size>::check(base) |
14687 | && Fits<VirtualRegister, size>::check(thisValue) |
14688 | && Fits<VirtualRegister, size>::check(property) |
14689 | && Fits<VirtualRegister, size>::check(value) |
14690 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
14691 | if (recordOpcode) |
14692 | gen->recordOpcode(opcodeID); |
14693 | if (size == OpcodeSize::Wide) |
14694 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
14695 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
14696 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
14697 | gen->write(Fits<VirtualRegister, size>::convert(thisValue)); |
14698 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
14699 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
14700 | return true; |
14701 | } |
14702 | return false; |
14703 | } |
14704 | |
14705 | public: |
14706 | template<typename Block> |
14707 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
14708 | { |
14709 | dumper->printLocationAndOp(__location, &"*put_by_val_with_this" [!__isWide]); |
14710 | dumper->dumpOperand(m_base, true); |
14711 | dumper->dumpOperand(m_thisValue, false); |
14712 | dumper->dumpOperand(m_property, false); |
14713 | dumper->dumpOperand(m_value, false); |
14714 | } |
14715 | |
14716 | OpPutByValWithThis(const uint8_t* stream) |
14717 | : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
14718 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
14719 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
14720 | , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
14721 | { |
14722 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14723 | } |
14724 | |
14725 | OpPutByValWithThis(const uint32_t* stream) |
14726 | : m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
14727 | , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
14728 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
14729 | , m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
14730 | { |
14731 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14732 | } |
14733 | |
14734 | static OpPutByValWithThis decode(const uint8_t* stream) |
14735 | { |
14736 | if (*stream != op_wide) |
14737 | return { stream }; |
14738 | |
14739 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
14740 | return { wideStream }; |
14741 | } |
14742 | |
14743 | template<typename Functor> |
14744 | void setBase(VirtualRegister value, Functor func) |
14745 | { |
14746 | if (isWide()) |
14747 | setBase<OpcodeSize::Wide>(value, func); |
14748 | else |
14749 | setBase<OpcodeSize::Narrow>(value, func); |
14750 | } |
14751 | |
14752 | template <OpcodeSize size, typename Functor> |
14753 | void setBase(VirtualRegister value, Functor func) |
14754 | { |
14755 | if (!Fits<VirtualRegister, size>::check(value)) |
14756 | value = func(); |
14757 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
14758 | *stream = Fits<VirtualRegister, size>::convert(value); |
14759 | } |
14760 | |
14761 | template<typename Functor> |
14762 | void setThisValue(VirtualRegister value, Functor func) |
14763 | { |
14764 | if (isWide()) |
14765 | setThisValue<OpcodeSize::Wide>(value, func); |
14766 | else |
14767 | setThisValue<OpcodeSize::Narrow>(value, func); |
14768 | } |
14769 | |
14770 | template <OpcodeSize size, typename Functor> |
14771 | void setThisValue(VirtualRegister value, Functor func) |
14772 | { |
14773 | if (!Fits<VirtualRegister, size>::check(value)) |
14774 | value = func(); |
14775 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
14776 | *stream = Fits<VirtualRegister, size>::convert(value); |
14777 | } |
14778 | |
14779 | template<typename Functor> |
14780 | void setProperty(VirtualRegister value, Functor func) |
14781 | { |
14782 | if (isWide()) |
14783 | setProperty<OpcodeSize::Wide>(value, func); |
14784 | else |
14785 | setProperty<OpcodeSize::Narrow>(value, func); |
14786 | } |
14787 | |
14788 | template <OpcodeSize size, typename Functor> |
14789 | void setProperty(VirtualRegister value, Functor func) |
14790 | { |
14791 | if (!Fits<VirtualRegister, size>::check(value)) |
14792 | value = func(); |
14793 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
14794 | *stream = Fits<VirtualRegister, size>::convert(value); |
14795 | } |
14796 | |
14797 | template<typename Functor> |
14798 | void setValue(VirtualRegister value, Functor func) |
14799 | { |
14800 | if (isWide()) |
14801 | setValue<OpcodeSize::Wide>(value, func); |
14802 | else |
14803 | setValue<OpcodeSize::Narrow>(value, func); |
14804 | } |
14805 | |
14806 | template <OpcodeSize size, typename Functor> |
14807 | void setValue(VirtualRegister value, Functor func) |
14808 | { |
14809 | if (!Fits<VirtualRegister, size>::check(value)) |
14810 | value = func(); |
14811 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
14812 | *stream = Fits<VirtualRegister, size>::convert(value); |
14813 | } |
14814 | |
14815 | VirtualRegister m_base; |
14816 | VirtualRegister m_thisValue; |
14817 | VirtualRegister m_property; |
14818 | VirtualRegister m_value; |
14819 | }; |
14820 | |
14821 | struct OpDelByVal : public Instruction { |
14822 | static constexpr OpcodeID opcodeID = op_del_by_val; |
14823 | |
14824 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property) |
14825 | { |
14826 | |
14827 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property) |
14828 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, property); |
14829 | } |
14830 | |
14831 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
14832 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property) |
14833 | { |
14834 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property); |
14835 | if (shouldAssert == Assert) |
14836 | ASSERT(didEmit); |
14837 | return didEmit; |
14838 | } |
14839 | |
14840 | private: |
14841 | template<OpcodeSize size, bool recordOpcode> |
14842 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property) |
14843 | { |
14844 | if (size == OpcodeSize::Wide) |
14845 | gen->alignWideOpcode(); |
14846 | if (Fits<unsigned, size>::check(opcodeID) |
14847 | && Fits<VirtualRegister, size>::check(dst) |
14848 | && Fits<VirtualRegister, size>::check(base) |
14849 | && Fits<VirtualRegister, size>::check(property) |
14850 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
14851 | if (recordOpcode) |
14852 | gen->recordOpcode(opcodeID); |
14853 | if (size == OpcodeSize::Wide) |
14854 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
14855 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
14856 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
14857 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
14858 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
14859 | return true; |
14860 | } |
14861 | return false; |
14862 | } |
14863 | |
14864 | public: |
14865 | template<typename Block> |
14866 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
14867 | { |
14868 | dumper->printLocationAndOp(__location, &"*del_by_val" [!__isWide]); |
14869 | dumper->dumpOperand(m_dst, true); |
14870 | dumper->dumpOperand(m_base, false); |
14871 | dumper->dumpOperand(m_property, false); |
14872 | } |
14873 | |
14874 | OpDelByVal(const uint8_t* stream) |
14875 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
14876 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
14877 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
14878 | { |
14879 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14880 | } |
14881 | |
14882 | OpDelByVal(const uint32_t* stream) |
14883 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
14884 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
14885 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
14886 | { |
14887 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
14888 | } |
14889 | |
14890 | static OpDelByVal decode(const uint8_t* stream) |
14891 | { |
14892 | if (*stream != op_wide) |
14893 | return { stream }; |
14894 | |
14895 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
14896 | return { wideStream }; |
14897 | } |
14898 | |
14899 | template<typename Functor> |
14900 | void setDst(VirtualRegister value, Functor func) |
14901 | { |
14902 | if (isWide()) |
14903 | setDst<OpcodeSize::Wide>(value, func); |
14904 | else |
14905 | setDst<OpcodeSize::Narrow>(value, func); |
14906 | } |
14907 | |
14908 | template <OpcodeSize size, typename Functor> |
14909 | void setDst(VirtualRegister value, Functor func) |
14910 | { |
14911 | if (!Fits<VirtualRegister, size>::check(value)) |
14912 | value = func(); |
14913 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
14914 | *stream = Fits<VirtualRegister, size>::convert(value); |
14915 | } |
14916 | |
14917 | template<typename Functor> |
14918 | void setBase(VirtualRegister value, Functor func) |
14919 | { |
14920 | if (isWide()) |
14921 | setBase<OpcodeSize::Wide>(value, func); |
14922 | else |
14923 | setBase<OpcodeSize::Narrow>(value, func); |
14924 | } |
14925 | |
14926 | template <OpcodeSize size, typename Functor> |
14927 | void setBase(VirtualRegister value, Functor func) |
14928 | { |
14929 | if (!Fits<VirtualRegister, size>::check(value)) |
14930 | value = func(); |
14931 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
14932 | *stream = Fits<VirtualRegister, size>::convert(value); |
14933 | } |
14934 | |
14935 | template<typename Functor> |
14936 | void setProperty(VirtualRegister value, Functor func) |
14937 | { |
14938 | if (isWide()) |
14939 | setProperty<OpcodeSize::Wide>(value, func); |
14940 | else |
14941 | setProperty<OpcodeSize::Narrow>(value, func); |
14942 | } |
14943 | |
14944 | template <OpcodeSize size, typename Functor> |
14945 | void setProperty(VirtualRegister value, Functor func) |
14946 | { |
14947 | if (!Fits<VirtualRegister, size>::check(value)) |
14948 | value = func(); |
14949 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
14950 | *stream = Fits<VirtualRegister, size>::convert(value); |
14951 | } |
14952 | |
14953 | VirtualRegister m_dst; |
14954 | VirtualRegister m_base; |
14955 | VirtualRegister m_property; |
14956 | }; |
14957 | |
14958 | struct OpPutGetterById : public Instruction { |
14959 | static constexpr OpcodeID opcodeID = op_put_getter_by_id; |
14960 | |
14961 | static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor) |
14962 | { |
14963 | |
14964 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, attributes, accessor) |
14965 | || emit<OpcodeSize::Wide, Assert, true>(gen, base, property, attributes, accessor); |
14966 | } |
14967 | |
14968 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
14969 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor) |
14970 | { |
14971 | bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, attributes, accessor); |
14972 | if (shouldAssert == Assert) |
14973 | ASSERT(didEmit); |
14974 | return didEmit; |
14975 | } |
14976 | |
14977 | private: |
14978 | template<OpcodeSize size, bool recordOpcode> |
14979 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor) |
14980 | { |
14981 | if (size == OpcodeSize::Wide) |
14982 | gen->alignWideOpcode(); |
14983 | if (Fits<unsigned, size>::check(opcodeID) |
14984 | && Fits<VirtualRegister, size>::check(base) |
14985 | && Fits<unsigned, size>::check(property) |
14986 | && Fits<unsigned, size>::check(attributes) |
14987 | && Fits<VirtualRegister, size>::check(accessor) |
14988 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
14989 | if (recordOpcode) |
14990 | gen->recordOpcode(opcodeID); |
14991 | if (size == OpcodeSize::Wide) |
14992 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
14993 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
14994 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
14995 | gen->write(Fits<unsigned, size>::convert(property)); |
14996 | gen->write(Fits<unsigned, size>::convert(attributes)); |
14997 | gen->write(Fits<VirtualRegister, size>::convert(accessor)); |
14998 | return true; |
14999 | } |
15000 | return false; |
15001 | } |
15002 | |
15003 | public: |
15004 | template<typename Block> |
15005 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
15006 | { |
15007 | dumper->printLocationAndOp(__location, &"*put_getter_by_id" [!__isWide]); |
15008 | dumper->dumpOperand(m_base, true); |
15009 | dumper->dumpOperand(m_property, false); |
15010 | dumper->dumpOperand(m_attributes, false); |
15011 | dumper->dumpOperand(m_accessor, false); |
15012 | } |
15013 | |
15014 | OpPutGetterById(const uint8_t* stream) |
15015 | : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
15016 | , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2])) |
15017 | , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
15018 | , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
15019 | { |
15020 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
15021 | } |
15022 | |
15023 | OpPutGetterById(const uint32_t* stream) |
15024 | : m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
15025 | , m_property(Fits<unsigned, OpcodeSize::Wide>::convert(stream[2])) |
15026 | , m_attributes(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
15027 | , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
15028 | { |
15029 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
15030 | } |
15031 | |
15032 | static OpPutGetterById decode(const uint8_t* stream) |
15033 | { |
15034 | if (*stream != op_wide) |
15035 | return { stream }; |
15036 | |
15037 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
15038 | return { wideStream }; |
15039 | } |
15040 | |
15041 | template<typename Functor> |
15042 | void setBase(VirtualRegister value, Functor func) |
15043 | { |
15044 | if (isWide()) |
15045 | setBase<OpcodeSize::Wide>(value, func); |
15046 | else |
15047 | setBase<OpcodeSize::Narrow>(value, func); |
15048 | } |
15049 | |
15050 | template <OpcodeSize size, typename Functor> |
15051 | void setBase(VirtualRegister value, Functor func) |
15052 | { |
15053 | if (!Fits<VirtualRegister, size>::check(value)) |
15054 | value = func(); |
15055 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
15056 | *stream = Fits<VirtualRegister, size>::convert(value); |
15057 | } |
15058 | |
15059 | template<typename Functor> |
15060 | void setProperty(unsigned value, Functor func) |
15061 | { |
15062 | if (isWide()) |
15063 | setProperty<OpcodeSize::Wide>(value, func); |
15064 | else |
15065 | setProperty<OpcodeSize::Narrow>(value, func); |
15066 | } |
15067 | |
15068 | template <OpcodeSize size, typename Functor> |
15069 | void setProperty(unsigned value, Functor func) |
15070 | { |
15071 | if (!Fits<unsigned, size>::check(value)) |
15072 | value = func(); |
15073 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
15074 | *stream = Fits<unsigned, size>::convert(value); |
15075 | } |
15076 | |
15077 | template<typename Functor> |
15078 | void setAttributes(unsigned value, Functor func) |
15079 | { |
15080 | if (isWide()) |
15081 | setAttributes<OpcodeSize::Wide>(value, func); |
15082 | else |
15083 | setAttributes<OpcodeSize::Narrow>(value, func); |
15084 | } |
15085 | |
15086 | template <OpcodeSize size, typename Functor> |
15087 | void setAttributes(unsigned value, Functor func) |
15088 | { |
15089 | if (!Fits<unsigned, size>::check(value)) |
15090 | value = func(); |
15091 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
15092 | *stream = Fits<unsigned, size>::convert(value); |
15093 | } |
15094 | |
15095 | template<typename Functor> |
15096 | void setAccessor(VirtualRegister value, Functor func) |
15097 | { |
15098 | if (isWide()) |
15099 | setAccessor<OpcodeSize::Wide>(value, func); |
15100 | else |
15101 | setAccessor<OpcodeSize::Narrow>(value, func); |
15102 | } |
15103 | |
15104 | template <OpcodeSize size, typename Functor> |
15105 | void setAccessor(VirtualRegister value, Functor func) |
15106 | { |
15107 | if (!Fits<VirtualRegister, size>::check(value)) |
15108 | value = func(); |
15109 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
15110 | *stream = Fits<VirtualRegister, size>::convert(value); |
15111 | } |
15112 | |
15113 | VirtualRegister m_base; |
15114 | unsigned m_property; |
15115 | unsigned m_attributes; |
15116 | VirtualRegister m_accessor; |
15117 | }; |
15118 | |
15119 | struct OpPutSetterById : public Instruction { |
15120 | static constexpr OpcodeID opcodeID = op_put_setter_by_id; |
15121 | |
15122 | static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor) |
15123 | { |
15124 | |
15125 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, attributes, accessor) |
15126 | || emit<OpcodeSize::Wide, Assert, true>(gen, base, property, attributes, accessor); |
15127 | } |
15128 | |
15129 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
15130 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor) |
15131 | { |
15132 | bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, attributes, accessor); |
15133 | if (shouldAssert == Assert) |
15134 | ASSERT(didEmit); |
15135 | return didEmit; |
15136 | } |
15137 | |
15138 | private: |
15139 | template<OpcodeSize size, bool recordOpcode> |
15140 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor) |
15141 | { |
15142 | if (size == OpcodeSize::Wide) |
15143 | gen->alignWideOpcode(); |
15144 | if (Fits<unsigned, size>::check(opcodeID) |
15145 | && Fits<VirtualRegister, size>::check(base) |
15146 | && Fits<unsigned, size>::check(property) |
15147 | && Fits<unsigned, size>::check(attributes) |
15148 | && Fits<VirtualRegister, size>::check(accessor) |
15149 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
15150 | if (recordOpcode) |
15151 | gen->recordOpcode(opcodeID); |
15152 | if (size == OpcodeSize::Wide) |
15153 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
15154 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
15155 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
15156 | gen->write(Fits<unsigned, size>::convert(property)); |
15157 | gen->write(Fits<unsigned, size>::convert(attributes)); |
15158 | gen->write(Fits<VirtualRegister, size>::convert(accessor)); |
15159 | return true; |
15160 | } |
15161 | return false; |
15162 | } |
15163 | |
15164 | public: |
15165 | template<typename Block> |
15166 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
15167 | { |
15168 | dumper->printLocationAndOp(__location, &"*put_setter_by_id" [!__isWide]); |
15169 | dumper->dumpOperand(m_base, true); |
15170 | dumper->dumpOperand(m_property, false); |
15171 | dumper->dumpOperand(m_attributes, false); |
15172 | dumper->dumpOperand(m_accessor, false); |
15173 | } |
15174 | |
15175 | OpPutSetterById(const uint8_t* stream) |
15176 | : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
15177 | , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2])) |
15178 | , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
15179 | , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
15180 | { |
15181 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
15182 | } |
15183 | |
15184 | OpPutSetterById(const uint32_t* stream) |
15185 | : m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
15186 | , m_property(Fits<unsigned, OpcodeSize::Wide>::convert(stream[2])) |
15187 | , m_attributes(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
15188 | , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
15189 | { |
15190 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
15191 | } |
15192 | |
15193 | static OpPutSetterById decode(const uint8_t* stream) |
15194 | { |
15195 | if (*stream != op_wide) |
15196 | return { stream }; |
15197 | |
15198 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
15199 | return { wideStream }; |
15200 | } |
15201 | |
15202 | template<typename Functor> |
15203 | void setBase(VirtualRegister value, Functor func) |
15204 | { |
15205 | if (isWide()) |
15206 | setBase<OpcodeSize::Wide>(value, func); |
15207 | else |
15208 | setBase<OpcodeSize::Narrow>(value, func); |
15209 | } |
15210 | |
15211 | template <OpcodeSize size, typename Functor> |
15212 | void setBase(VirtualRegister value, Functor func) |
15213 | { |
15214 | if (!Fits<VirtualRegister, size>::check(value)) |
15215 | value = func(); |
15216 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
15217 | *stream = Fits<VirtualRegister, size>::convert(value); |
15218 | } |
15219 | |
15220 | template<typename Functor> |
15221 | void setProperty(unsigned value, Functor func) |
15222 | { |
15223 | if (isWide()) |
15224 | setProperty<OpcodeSize::Wide>(value, func); |
15225 | else |
15226 | setProperty<OpcodeSize::Narrow>(value, func); |
15227 | } |
15228 | |
15229 | template <OpcodeSize size, typename Functor> |
15230 | void setProperty(unsigned value, Functor func) |
15231 | { |
15232 | if (!Fits<unsigned, size>::check(value)) |
15233 | value = func(); |
15234 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
15235 | *stream = Fits<unsigned, size>::convert(value); |
15236 | } |
15237 | |
15238 | template<typename Functor> |
15239 | void setAttributes(unsigned value, Functor func) |
15240 | { |
15241 | if (isWide()) |
15242 | setAttributes<OpcodeSize::Wide>(value, func); |
15243 | else |
15244 | setAttributes<OpcodeSize::Narrow>(value, func); |
15245 | } |
15246 | |
15247 | template <OpcodeSize size, typename Functor> |
15248 | void setAttributes(unsigned value, Functor func) |
15249 | { |
15250 | if (!Fits<unsigned, size>::check(value)) |
15251 | value = func(); |
15252 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
15253 | *stream = Fits<unsigned, size>::convert(value); |
15254 | } |
15255 | |
15256 | template<typename Functor> |
15257 | void setAccessor(VirtualRegister value, Functor func) |
15258 | { |
15259 | if (isWide()) |
15260 | setAccessor<OpcodeSize::Wide>(value, func); |
15261 | else |
15262 | setAccessor<OpcodeSize::Narrow>(value, func); |
15263 | } |
15264 | |
15265 | template <OpcodeSize size, typename Functor> |
15266 | void setAccessor(VirtualRegister value, Functor func) |
15267 | { |
15268 | if (!Fits<VirtualRegister, size>::check(value)) |
15269 | value = func(); |
15270 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
15271 | *stream = Fits<VirtualRegister, size>::convert(value); |
15272 | } |
15273 | |
15274 | VirtualRegister m_base; |
15275 | unsigned m_property; |
15276 | unsigned m_attributes; |
15277 | VirtualRegister m_accessor; |
15278 | }; |
15279 | |
15280 | struct OpPutGetterSetterById : public Instruction { |
15281 | static constexpr OpcodeID opcodeID = op_put_getter_setter_by_id; |
15282 | |
15283 | static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister getter, VirtualRegister setter) |
15284 | { |
15285 | |
15286 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, attributes, getter, setter) |
15287 | || emit<OpcodeSize::Wide, Assert, true>(gen, base, property, attributes, getter, setter); |
15288 | } |
15289 | |
15290 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
15291 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister getter, VirtualRegister setter) |
15292 | { |
15293 | bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, attributes, getter, setter); |
15294 | if (shouldAssert == Assert) |
15295 | ASSERT(didEmit); |
15296 | return didEmit; |
15297 | } |
15298 | |
15299 | private: |
15300 | template<OpcodeSize size, bool recordOpcode> |
15301 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister getter, VirtualRegister setter) |
15302 | { |
15303 | if (size == OpcodeSize::Wide) |
15304 | gen->alignWideOpcode(); |
15305 | if (Fits<unsigned, size>::check(opcodeID) |
15306 | && Fits<VirtualRegister, size>::check(base) |
15307 | && Fits<unsigned, size>::check(property) |
15308 | && Fits<unsigned, size>::check(attributes) |
15309 | && Fits<VirtualRegister, size>::check(getter) |
15310 | && Fits<VirtualRegister, size>::check(setter) |
15311 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
15312 | if (recordOpcode) |
15313 | gen->recordOpcode(opcodeID); |
15314 | if (size == OpcodeSize::Wide) |
15315 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
15316 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
15317 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
15318 | gen->write(Fits<unsigned, size>::convert(property)); |
15319 | gen->write(Fits<unsigned, size>::convert(attributes)); |
15320 | gen->write(Fits<VirtualRegister, size>::convert(getter)); |
15321 | gen->write(Fits<VirtualRegister, size>::convert(setter)); |
15322 | return true; |
15323 | } |
15324 | return false; |
15325 | } |
15326 | |
15327 | public: |
15328 | template<typename Block> |
15329 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
15330 | { |
15331 | dumper->printLocationAndOp(__location, &"*put_getter_setter_by_id" [!__isWide]); |
15332 | dumper->dumpOperand(m_base, true); |
15333 | dumper->dumpOperand(m_property, false); |
15334 | dumper->dumpOperand(m_attributes, false); |
15335 | dumper->dumpOperand(m_getter, false); |
15336 | dumper->dumpOperand(m_setter, false); |
15337 | } |
15338 | |
15339 | OpPutGetterSetterById(const uint8_t* stream) |
15340 | : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
15341 | , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2])) |
15342 | , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
15343 | , m_getter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
15344 | , m_setter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5])) |
15345 | { |
15346 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
15347 | } |
15348 | |
15349 | OpPutGetterSetterById(const uint32_t* stream) |
15350 | : m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
15351 | , m_property(Fits<unsigned, OpcodeSize::Wide>::convert(stream[2])) |
15352 | , m_attributes(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
15353 | , m_getter(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
15354 | , m_setter(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[5])) |
15355 | { |
15356 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
15357 | } |
15358 | |
15359 | static OpPutGetterSetterById decode(const uint8_t* stream) |
15360 | { |
15361 | if (*stream != op_wide) |
15362 | return { stream }; |
15363 | |
15364 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
15365 | return { wideStream }; |
15366 | } |
15367 | |
15368 | template<typename Functor> |
15369 | void setBase(VirtualRegister value, Functor func) |
15370 | { |
15371 | if (isWide()) |
15372 | setBase<OpcodeSize::Wide>(value, func); |
15373 | else |
15374 | setBase<OpcodeSize::Narrow>(value, func); |
15375 | } |
15376 | |
15377 | template <OpcodeSize size, typename Functor> |
15378 | void setBase(VirtualRegister value, Functor func) |
15379 | { |
15380 | if (!Fits<VirtualRegister, size>::check(value)) |
15381 | value = func(); |
15382 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
15383 | *stream = Fits<VirtualRegister, size>::convert(value); |
15384 | } |
15385 | |
15386 | template<typename Functor> |
15387 | void setProperty(unsigned value, Functor func) |
15388 | { |
15389 | if (isWide()) |
15390 | setProperty<OpcodeSize::Wide>(value, func); |
15391 | else |
15392 | setProperty<OpcodeSize::Narrow>(value, func); |
15393 | } |
15394 | |
15395 | template <OpcodeSize size, typename Functor> |
15396 | void setProperty(unsigned value, Functor func) |
15397 | { |
15398 | if (!Fits<unsigned, size>::check(value)) |
15399 | value = func(); |
15400 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
15401 | *stream = Fits<unsigned, size>::convert(value); |
15402 | } |
15403 | |
15404 | template<typename Functor> |
15405 | void setAttributes(unsigned value, Functor func) |
15406 | { |
15407 | if (isWide()) |
15408 | setAttributes<OpcodeSize::Wide>(value, func); |
15409 | else |
15410 | setAttributes<OpcodeSize::Narrow>(value, func); |
15411 | } |
15412 | |
15413 | template <OpcodeSize size, typename Functor> |
15414 | void setAttributes(unsigned value, Functor func) |
15415 | { |
15416 | if (!Fits<unsigned, size>::check(value)) |
15417 | value = func(); |
15418 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
15419 | *stream = Fits<unsigned, size>::convert(value); |
15420 | } |
15421 | |
15422 | template<typename Functor> |
15423 | void setGetter(VirtualRegister value, Functor func) |
15424 | { |
15425 | if (isWide()) |
15426 | setGetter<OpcodeSize::Wide>(value, func); |
15427 | else |
15428 | setGetter<OpcodeSize::Narrow>(value, func); |
15429 | } |
15430 | |
15431 | template <OpcodeSize size, typename Functor> |
15432 | void setGetter(VirtualRegister value, Functor func) |
15433 | { |
15434 | if (!Fits<VirtualRegister, size>::check(value)) |
15435 | value = func(); |
15436 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
15437 | *stream = Fits<VirtualRegister, size>::convert(value); |
15438 | } |
15439 | |
15440 | template<typename Functor> |
15441 | void setSetter(VirtualRegister value, Functor func) |
15442 | { |
15443 | if (isWide()) |
15444 | setSetter<OpcodeSize::Wide>(value, func); |
15445 | else |
15446 | setSetter<OpcodeSize::Narrow>(value, func); |
15447 | } |
15448 | |
15449 | template <OpcodeSize size, typename Functor> |
15450 | void setSetter(VirtualRegister value, Functor func) |
15451 | { |
15452 | if (!Fits<VirtualRegister, size>::check(value)) |
15453 | value = func(); |
15454 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value); |
15455 | *stream = Fits<VirtualRegister, size>::convert(value); |
15456 | } |
15457 | |
15458 | VirtualRegister m_base; |
15459 | unsigned m_property; |
15460 | unsigned m_attributes; |
15461 | VirtualRegister m_getter; |
15462 | VirtualRegister m_setter; |
15463 | }; |
15464 | |
15465 | struct OpPutGetterByVal : public Instruction { |
15466 | static constexpr OpcodeID opcodeID = op_put_getter_by_val; |
15467 | |
15468 | static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor) |
15469 | { |
15470 | |
15471 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, attributes, accessor) |
15472 | || emit<OpcodeSize::Wide, Assert, true>(gen, base, property, attributes, accessor); |
15473 | } |
15474 | |
15475 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
15476 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor) |
15477 | { |
15478 | bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, attributes, accessor); |
15479 | if (shouldAssert == Assert) |
15480 | ASSERT(didEmit); |
15481 | return didEmit; |
15482 | } |
15483 | |
15484 | private: |
15485 | template<OpcodeSize size, bool recordOpcode> |
15486 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor) |
15487 | { |
15488 | if (size == OpcodeSize::Wide) |
15489 | gen->alignWideOpcode(); |
15490 | if (Fits<unsigned, size>::check(opcodeID) |
15491 | && Fits<VirtualRegister, size>::check(base) |
15492 | && Fits<VirtualRegister, size>::check(property) |
15493 | && Fits<unsigned, size>::check(attributes) |
15494 | && Fits<VirtualRegister, size>::check(accessor) |
15495 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
15496 | if (recordOpcode) |
15497 | gen->recordOpcode(opcodeID); |
15498 | if (size == OpcodeSize::Wide) |
15499 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
15500 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
15501 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
15502 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
15503 | gen->write(Fits<unsigned, size>::convert(attributes)); |
15504 | gen->write(Fits<VirtualRegister, size>::convert(accessor)); |
15505 | return true; |
15506 | } |
15507 | return false; |
15508 | } |
15509 | |
15510 | public: |
15511 | template<typename Block> |
15512 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
15513 | { |
15514 | dumper->printLocationAndOp(__location, &"*put_getter_by_val" [!__isWide]); |
15515 | dumper->dumpOperand(m_base, true); |
15516 | dumper->dumpOperand(m_property, false); |
15517 | dumper->dumpOperand(m_attributes, false); |
15518 | dumper->dumpOperand(m_accessor, false); |
15519 | } |
15520 | |
15521 | OpPutGetterByVal(const uint8_t* stream) |
15522 | : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
15523 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
15524 | , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
15525 | , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
15526 | { |
15527 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
15528 | } |
15529 | |
15530 | OpPutGetterByVal(const uint32_t* stream) |
15531 | : m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
15532 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
15533 | , m_attributes(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
15534 | , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
15535 | { |
15536 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
15537 | } |
15538 | |
15539 | static OpPutGetterByVal decode(const uint8_t* stream) |
15540 | { |
15541 | if (*stream != op_wide) |
15542 | return { stream }; |
15543 | |
15544 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
15545 | return { wideStream }; |
15546 | } |
15547 | |
15548 | template<typename Functor> |
15549 | void setBase(VirtualRegister value, Functor func) |
15550 | { |
15551 | if (isWide()) |
15552 | setBase<OpcodeSize::Wide>(value, func); |
15553 | else |
15554 | setBase<OpcodeSize::Narrow>(value, func); |
15555 | } |
15556 | |
15557 | template <OpcodeSize size, typename Functor> |
15558 | void setBase(VirtualRegister value, Functor func) |
15559 | { |
15560 | if (!Fits<VirtualRegister, size>::check(value)) |
15561 | value = func(); |
15562 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
15563 | *stream = Fits<VirtualRegister, size>::convert(value); |
15564 | } |
15565 | |
15566 | template<typename Functor> |
15567 | void setProperty(VirtualRegister value, Functor func) |
15568 | { |
15569 | if (isWide()) |
15570 | setProperty<OpcodeSize::Wide>(value, func); |
15571 | else |
15572 | setProperty<OpcodeSize::Narrow>(value, func); |
15573 | } |
15574 | |
15575 | template <OpcodeSize size, typename Functor> |
15576 | void setProperty(VirtualRegister value, Functor func) |
15577 | { |
15578 | if (!Fits<VirtualRegister, size>::check(value)) |
15579 | value = func(); |
15580 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
15581 | *stream = Fits<VirtualRegister, size>::convert(value); |
15582 | } |
15583 | |
15584 | template<typename Functor> |
15585 | void setAttributes(unsigned value, Functor func) |
15586 | { |
15587 | if (isWide()) |
15588 | setAttributes<OpcodeSize::Wide>(value, func); |
15589 | else |
15590 | setAttributes<OpcodeSize::Narrow>(value, func); |
15591 | } |
15592 | |
15593 | template <OpcodeSize size, typename Functor> |
15594 | void setAttributes(unsigned value, Functor func) |
15595 | { |
15596 | if (!Fits<unsigned, size>::check(value)) |
15597 | value = func(); |
15598 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
15599 | *stream = Fits<unsigned, size>::convert(value); |
15600 | } |
15601 | |
15602 | template<typename Functor> |
15603 | void setAccessor(VirtualRegister value, Functor func) |
15604 | { |
15605 | if (isWide()) |
15606 | setAccessor<OpcodeSize::Wide>(value, func); |
15607 | else |
15608 | setAccessor<OpcodeSize::Narrow>(value, func); |
15609 | } |
15610 | |
15611 | template <OpcodeSize size, typename Functor> |
15612 | void setAccessor(VirtualRegister value, Functor func) |
15613 | { |
15614 | if (!Fits<VirtualRegister, size>::check(value)) |
15615 | value = func(); |
15616 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
15617 | *stream = Fits<VirtualRegister, size>::convert(value); |
15618 | } |
15619 | |
15620 | VirtualRegister m_base; |
15621 | VirtualRegister m_property; |
15622 | unsigned m_attributes; |
15623 | VirtualRegister m_accessor; |
15624 | }; |
15625 | |
15626 | struct OpPutSetterByVal : public Instruction { |
15627 | static constexpr OpcodeID opcodeID = op_put_setter_by_val; |
15628 | |
15629 | static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor) |
15630 | { |
15631 | |
15632 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, attributes, accessor) |
15633 | || emit<OpcodeSize::Wide, Assert, true>(gen, base, property, attributes, accessor); |
15634 | } |
15635 | |
15636 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
15637 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor) |
15638 | { |
15639 | bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, attributes, accessor); |
15640 | if (shouldAssert == Assert) |
15641 | ASSERT(didEmit); |
15642 | return didEmit; |
15643 | } |
15644 | |
15645 | private: |
15646 | template<OpcodeSize size, bool recordOpcode> |
15647 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor) |
15648 | { |
15649 | if (size == OpcodeSize::Wide) |
15650 | gen->alignWideOpcode(); |
15651 | if (Fits<unsigned, size>::check(opcodeID) |
15652 | && Fits<VirtualRegister, size>::check(base) |
15653 | && Fits<VirtualRegister, size>::check(property) |
15654 | && Fits<unsigned, size>::check(attributes) |
15655 | && Fits<VirtualRegister, size>::check(accessor) |
15656 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
15657 | if (recordOpcode) |
15658 | gen->recordOpcode(opcodeID); |
15659 | if (size == OpcodeSize::Wide) |
15660 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
15661 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
15662 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
15663 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
15664 | gen->write(Fits<unsigned, size>::convert(attributes)); |
15665 | gen->write(Fits<VirtualRegister, size>::convert(accessor)); |
15666 | return true; |
15667 | } |
15668 | return false; |
15669 | } |
15670 | |
15671 | public: |
15672 | template<typename Block> |
15673 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
15674 | { |
15675 | dumper->printLocationAndOp(__location, &"*put_setter_by_val" [!__isWide]); |
15676 | dumper->dumpOperand(m_base, true); |
15677 | dumper->dumpOperand(m_property, false); |
15678 | dumper->dumpOperand(m_attributes, false); |
15679 | dumper->dumpOperand(m_accessor, false); |
15680 | } |
15681 | |
15682 | OpPutSetterByVal(const uint8_t* stream) |
15683 | : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
15684 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
15685 | , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
15686 | , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
15687 | { |
15688 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
15689 | } |
15690 | |
15691 | OpPutSetterByVal(const uint32_t* stream) |
15692 | : m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
15693 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
15694 | , m_attributes(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
15695 | , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
15696 | { |
15697 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
15698 | } |
15699 | |
15700 | static OpPutSetterByVal decode(const uint8_t* stream) |
15701 | { |
15702 | if (*stream != op_wide) |
15703 | return { stream }; |
15704 | |
15705 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
15706 | return { wideStream }; |
15707 | } |
15708 | |
15709 | template<typename Functor> |
15710 | void setBase(VirtualRegister value, Functor func) |
15711 | { |
15712 | if (isWide()) |
15713 | setBase<OpcodeSize::Wide>(value, func); |
15714 | else |
15715 | setBase<OpcodeSize::Narrow>(value, func); |
15716 | } |
15717 | |
15718 | template <OpcodeSize size, typename Functor> |
15719 | void setBase(VirtualRegister value, Functor func) |
15720 | { |
15721 | if (!Fits<VirtualRegister, size>::check(value)) |
15722 | value = func(); |
15723 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
15724 | *stream = Fits<VirtualRegister, size>::convert(value); |
15725 | } |
15726 | |
15727 | template<typename Functor> |
15728 | void setProperty(VirtualRegister value, Functor func) |
15729 | { |
15730 | if (isWide()) |
15731 | setProperty<OpcodeSize::Wide>(value, func); |
15732 | else |
15733 | setProperty<OpcodeSize::Narrow>(value, func); |
15734 | } |
15735 | |
15736 | template <OpcodeSize size, typename Functor> |
15737 | void setProperty(VirtualRegister value, Functor func) |
15738 | { |
15739 | if (!Fits<VirtualRegister, size>::check(value)) |
15740 | value = func(); |
15741 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
15742 | *stream = Fits<VirtualRegister, size>::convert(value); |
15743 | } |
15744 | |
15745 | template<typename Functor> |
15746 | void setAttributes(unsigned value, Functor func) |
15747 | { |
15748 | if (isWide()) |
15749 | setAttributes<OpcodeSize::Wide>(value, func); |
15750 | else |
15751 | setAttributes<OpcodeSize::Narrow>(value, func); |
15752 | } |
15753 | |
15754 | template <OpcodeSize size, typename Functor> |
15755 | void setAttributes(unsigned value, Functor func) |
15756 | { |
15757 | if (!Fits<unsigned, size>::check(value)) |
15758 | value = func(); |
15759 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
15760 | *stream = Fits<unsigned, size>::convert(value); |
15761 | } |
15762 | |
15763 | template<typename Functor> |
15764 | void setAccessor(VirtualRegister value, Functor func) |
15765 | { |
15766 | if (isWide()) |
15767 | setAccessor<OpcodeSize::Wide>(value, func); |
15768 | else |
15769 | setAccessor<OpcodeSize::Narrow>(value, func); |
15770 | } |
15771 | |
15772 | template <OpcodeSize size, typename Functor> |
15773 | void setAccessor(VirtualRegister value, Functor func) |
15774 | { |
15775 | if (!Fits<VirtualRegister, size>::check(value)) |
15776 | value = func(); |
15777 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
15778 | *stream = Fits<VirtualRegister, size>::convert(value); |
15779 | } |
15780 | |
15781 | VirtualRegister m_base; |
15782 | VirtualRegister m_property; |
15783 | unsigned m_attributes; |
15784 | VirtualRegister m_accessor; |
15785 | }; |
15786 | |
15787 | struct OpDefineDataProperty : public Instruction { |
15788 | static constexpr OpcodeID opcodeID = op_define_data_property; |
15789 | |
15790 | static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, VirtualRegister attributes) |
15791 | { |
15792 | |
15793 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, value, attributes) |
15794 | || emit<OpcodeSize::Wide, Assert, true>(gen, base, property, value, attributes); |
15795 | } |
15796 | |
15797 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
15798 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, VirtualRegister attributes) |
15799 | { |
15800 | bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, value, attributes); |
15801 | if (shouldAssert == Assert) |
15802 | ASSERT(didEmit); |
15803 | return didEmit; |
15804 | } |
15805 | |
15806 | private: |
15807 | template<OpcodeSize size, bool recordOpcode> |
15808 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, VirtualRegister attributes) |
15809 | { |
15810 | if (size == OpcodeSize::Wide) |
15811 | gen->alignWideOpcode(); |
15812 | if (Fits<unsigned, size>::check(opcodeID) |
15813 | && Fits<VirtualRegister, size>::check(base) |
15814 | && Fits<VirtualRegister, size>::check(property) |
15815 | && Fits<VirtualRegister, size>::check(value) |
15816 | && Fits<VirtualRegister, size>::check(attributes) |
15817 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
15818 | if (recordOpcode) |
15819 | gen->recordOpcode(opcodeID); |
15820 | if (size == OpcodeSize::Wide) |
15821 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
15822 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
15823 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
15824 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
15825 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
15826 | gen->write(Fits<VirtualRegister, size>::convert(attributes)); |
15827 | return true; |
15828 | } |
15829 | return false; |
15830 | } |
15831 | |
15832 | public: |
15833 | template<typename Block> |
15834 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
15835 | { |
15836 | dumper->printLocationAndOp(__location, &"*define_data_property" [!__isWide]); |
15837 | dumper->dumpOperand(m_base, true); |
15838 | dumper->dumpOperand(m_property, false); |
15839 | dumper->dumpOperand(m_value, false); |
15840 | dumper->dumpOperand(m_attributes, false); |
15841 | } |
15842 | |
15843 | OpDefineDataProperty(const uint8_t* stream) |
15844 | : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
15845 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
15846 | , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
15847 | , m_attributes(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
15848 | { |
15849 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
15850 | } |
15851 | |
15852 | OpDefineDataProperty(const uint32_t* stream) |
15853 | : m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
15854 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
15855 | , m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
15856 | , m_attributes(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
15857 | { |
15858 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
15859 | } |
15860 | |
15861 | static OpDefineDataProperty decode(const uint8_t* stream) |
15862 | { |
15863 | if (*stream != op_wide) |
15864 | return { stream }; |
15865 | |
15866 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
15867 | return { wideStream }; |
15868 | } |
15869 | |
15870 | template<typename Functor> |
15871 | void setBase(VirtualRegister value, Functor func) |
15872 | { |
15873 | if (isWide()) |
15874 | setBase<OpcodeSize::Wide>(value, func); |
15875 | else |
15876 | setBase<OpcodeSize::Narrow>(value, func); |
15877 | } |
15878 | |
15879 | template <OpcodeSize size, typename Functor> |
15880 | void setBase(VirtualRegister value, Functor func) |
15881 | { |
15882 | if (!Fits<VirtualRegister, size>::check(value)) |
15883 | value = func(); |
15884 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
15885 | *stream = Fits<VirtualRegister, size>::convert(value); |
15886 | } |
15887 | |
15888 | template<typename Functor> |
15889 | void setProperty(VirtualRegister value, Functor func) |
15890 | { |
15891 | if (isWide()) |
15892 | setProperty<OpcodeSize::Wide>(value, func); |
15893 | else |
15894 | setProperty<OpcodeSize::Narrow>(value, func); |
15895 | } |
15896 | |
15897 | template <OpcodeSize size, typename Functor> |
15898 | void setProperty(VirtualRegister value, Functor func) |
15899 | { |
15900 | if (!Fits<VirtualRegister, size>::check(value)) |
15901 | value = func(); |
15902 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
15903 | *stream = Fits<VirtualRegister, size>::convert(value); |
15904 | } |
15905 | |
15906 | template<typename Functor> |
15907 | void setValue(VirtualRegister value, Functor func) |
15908 | { |
15909 | if (isWide()) |
15910 | setValue<OpcodeSize::Wide>(value, func); |
15911 | else |
15912 | setValue<OpcodeSize::Narrow>(value, func); |
15913 | } |
15914 | |
15915 | template <OpcodeSize size, typename Functor> |
15916 | void setValue(VirtualRegister value, Functor func) |
15917 | { |
15918 | if (!Fits<VirtualRegister, size>::check(value)) |
15919 | value = func(); |
15920 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
15921 | *stream = Fits<VirtualRegister, size>::convert(value); |
15922 | } |
15923 | |
15924 | template<typename Functor> |
15925 | void setAttributes(VirtualRegister value, Functor func) |
15926 | { |
15927 | if (isWide()) |
15928 | setAttributes<OpcodeSize::Wide>(value, func); |
15929 | else |
15930 | setAttributes<OpcodeSize::Narrow>(value, func); |
15931 | } |
15932 | |
15933 | template <OpcodeSize size, typename Functor> |
15934 | void setAttributes(VirtualRegister value, Functor func) |
15935 | { |
15936 | if (!Fits<VirtualRegister, size>::check(value)) |
15937 | value = func(); |
15938 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
15939 | *stream = Fits<VirtualRegister, size>::convert(value); |
15940 | } |
15941 | |
15942 | VirtualRegister m_base; |
15943 | VirtualRegister m_property; |
15944 | VirtualRegister m_value; |
15945 | VirtualRegister m_attributes; |
15946 | }; |
15947 | |
15948 | struct OpDefineAccessorProperty : public Instruction { |
15949 | static constexpr OpcodeID opcodeID = op_define_accessor_property; |
15950 | |
15951 | static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister getter, VirtualRegister setter, VirtualRegister attributes) |
15952 | { |
15953 | |
15954 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, getter, setter, attributes) |
15955 | || emit<OpcodeSize::Wide, Assert, true>(gen, base, property, getter, setter, attributes); |
15956 | } |
15957 | |
15958 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
15959 | static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister getter, VirtualRegister setter, VirtualRegister attributes) |
15960 | { |
15961 | bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, getter, setter, attributes); |
15962 | if (shouldAssert == Assert) |
15963 | ASSERT(didEmit); |
15964 | return didEmit; |
15965 | } |
15966 | |
15967 | private: |
15968 | template<OpcodeSize size, bool recordOpcode> |
15969 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister getter, VirtualRegister setter, VirtualRegister attributes) |
15970 | { |
15971 | if (size == OpcodeSize::Wide) |
15972 | gen->alignWideOpcode(); |
15973 | if (Fits<unsigned, size>::check(opcodeID) |
15974 | && Fits<VirtualRegister, size>::check(base) |
15975 | && Fits<VirtualRegister, size>::check(property) |
15976 | && Fits<VirtualRegister, size>::check(getter) |
15977 | && Fits<VirtualRegister, size>::check(setter) |
15978 | && Fits<VirtualRegister, size>::check(attributes) |
15979 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
15980 | if (recordOpcode) |
15981 | gen->recordOpcode(opcodeID); |
15982 | if (size == OpcodeSize::Wide) |
15983 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
15984 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
15985 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
15986 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
15987 | gen->write(Fits<VirtualRegister, size>::convert(getter)); |
15988 | gen->write(Fits<VirtualRegister, size>::convert(setter)); |
15989 | gen->write(Fits<VirtualRegister, size>::convert(attributes)); |
15990 | return true; |
15991 | } |
15992 | return false; |
15993 | } |
15994 | |
15995 | public: |
15996 | template<typename Block> |
15997 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
15998 | { |
15999 | dumper->printLocationAndOp(__location, &"*define_accessor_property" [!__isWide]); |
16000 | dumper->dumpOperand(m_base, true); |
16001 | dumper->dumpOperand(m_property, false); |
16002 | dumper->dumpOperand(m_getter, false); |
16003 | dumper->dumpOperand(m_setter, false); |
16004 | dumper->dumpOperand(m_attributes, false); |
16005 | } |
16006 | |
16007 | OpDefineAccessorProperty(const uint8_t* stream) |
16008 | : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
16009 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
16010 | , m_getter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
16011 | , m_setter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
16012 | , m_attributes(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5])) |
16013 | { |
16014 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16015 | } |
16016 | |
16017 | OpDefineAccessorProperty(const uint32_t* stream) |
16018 | : m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
16019 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
16020 | , m_getter(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
16021 | , m_setter(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
16022 | , m_attributes(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[5])) |
16023 | { |
16024 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16025 | } |
16026 | |
16027 | static OpDefineAccessorProperty decode(const uint8_t* stream) |
16028 | { |
16029 | if (*stream != op_wide) |
16030 | return { stream }; |
16031 | |
16032 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
16033 | return { wideStream }; |
16034 | } |
16035 | |
16036 | template<typename Functor> |
16037 | void setBase(VirtualRegister value, Functor func) |
16038 | { |
16039 | if (isWide()) |
16040 | setBase<OpcodeSize::Wide>(value, func); |
16041 | else |
16042 | setBase<OpcodeSize::Narrow>(value, func); |
16043 | } |
16044 | |
16045 | template <OpcodeSize size, typename Functor> |
16046 | void setBase(VirtualRegister value, Functor func) |
16047 | { |
16048 | if (!Fits<VirtualRegister, size>::check(value)) |
16049 | value = func(); |
16050 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
16051 | *stream = Fits<VirtualRegister, size>::convert(value); |
16052 | } |
16053 | |
16054 | template<typename Functor> |
16055 | void setProperty(VirtualRegister value, Functor func) |
16056 | { |
16057 | if (isWide()) |
16058 | setProperty<OpcodeSize::Wide>(value, func); |
16059 | else |
16060 | setProperty<OpcodeSize::Narrow>(value, func); |
16061 | } |
16062 | |
16063 | template <OpcodeSize size, typename Functor> |
16064 | void setProperty(VirtualRegister value, Functor func) |
16065 | { |
16066 | if (!Fits<VirtualRegister, size>::check(value)) |
16067 | value = func(); |
16068 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
16069 | *stream = Fits<VirtualRegister, size>::convert(value); |
16070 | } |
16071 | |
16072 | template<typename Functor> |
16073 | void setGetter(VirtualRegister value, Functor func) |
16074 | { |
16075 | if (isWide()) |
16076 | setGetter<OpcodeSize::Wide>(value, func); |
16077 | else |
16078 | setGetter<OpcodeSize::Narrow>(value, func); |
16079 | } |
16080 | |
16081 | template <OpcodeSize size, typename Functor> |
16082 | void setGetter(VirtualRegister value, Functor func) |
16083 | { |
16084 | if (!Fits<VirtualRegister, size>::check(value)) |
16085 | value = func(); |
16086 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
16087 | *stream = Fits<VirtualRegister, size>::convert(value); |
16088 | } |
16089 | |
16090 | template<typename Functor> |
16091 | void setSetter(VirtualRegister value, Functor func) |
16092 | { |
16093 | if (isWide()) |
16094 | setSetter<OpcodeSize::Wide>(value, func); |
16095 | else |
16096 | setSetter<OpcodeSize::Narrow>(value, func); |
16097 | } |
16098 | |
16099 | template <OpcodeSize size, typename Functor> |
16100 | void setSetter(VirtualRegister value, Functor func) |
16101 | { |
16102 | if (!Fits<VirtualRegister, size>::check(value)) |
16103 | value = func(); |
16104 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
16105 | *stream = Fits<VirtualRegister, size>::convert(value); |
16106 | } |
16107 | |
16108 | template<typename Functor> |
16109 | void setAttributes(VirtualRegister value, Functor func) |
16110 | { |
16111 | if (isWide()) |
16112 | setAttributes<OpcodeSize::Wide>(value, func); |
16113 | else |
16114 | setAttributes<OpcodeSize::Narrow>(value, func); |
16115 | } |
16116 | |
16117 | template <OpcodeSize size, typename Functor> |
16118 | void setAttributes(VirtualRegister value, Functor func) |
16119 | { |
16120 | if (!Fits<VirtualRegister, size>::check(value)) |
16121 | value = func(); |
16122 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value); |
16123 | *stream = Fits<VirtualRegister, size>::convert(value); |
16124 | } |
16125 | |
16126 | VirtualRegister m_base; |
16127 | VirtualRegister m_property; |
16128 | VirtualRegister m_getter; |
16129 | VirtualRegister m_setter; |
16130 | VirtualRegister m_attributes; |
16131 | }; |
16132 | |
16133 | struct OpJmp : public Instruction { |
16134 | static constexpr OpcodeID opcodeID = op_jmp; |
16135 | |
16136 | static void emit(BytecodeGenerator* gen, BoundLabel targetLabel) |
16137 | { |
16138 | |
16139 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, targetLabel) |
16140 | || emit<OpcodeSize::Wide, Assert, true>(gen, targetLabel); |
16141 | } |
16142 | |
16143 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
16144 | static bool emit(BytecodeGenerator* gen, BoundLabel targetLabel) |
16145 | { |
16146 | bool didEmit = emitImpl<size, recordOpcode>(gen, targetLabel); |
16147 | if (shouldAssert == Assert) |
16148 | ASSERT(didEmit); |
16149 | return didEmit; |
16150 | } |
16151 | |
16152 | private: |
16153 | template<OpcodeSize size, bool recordOpcode> |
16154 | static bool emitImpl(BytecodeGenerator* gen, BoundLabel targetLabel) |
16155 | { |
16156 | if (size == OpcodeSize::Wide) |
16157 | gen->alignWideOpcode(); |
16158 | if (Fits<unsigned, size>::check(opcodeID) |
16159 | && Fits<BoundLabel, size>::check(targetLabel) |
16160 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
16161 | if (recordOpcode) |
16162 | gen->recordOpcode(opcodeID); |
16163 | if (size == OpcodeSize::Wide) |
16164 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
16165 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
16166 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
16167 | return true; |
16168 | } |
16169 | return false; |
16170 | } |
16171 | |
16172 | public: |
16173 | template<typename Block> |
16174 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
16175 | { |
16176 | dumper->printLocationAndOp(__location, &"*jmp" [!__isWide]); |
16177 | dumper->dumpOperand(m_targetLabel, true); |
16178 | } |
16179 | |
16180 | OpJmp(const uint8_t* stream) |
16181 | : m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[1])) |
16182 | { |
16183 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16184 | } |
16185 | |
16186 | OpJmp(const uint32_t* stream) |
16187 | : m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[1])) |
16188 | { |
16189 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16190 | } |
16191 | |
16192 | static OpJmp decode(const uint8_t* stream) |
16193 | { |
16194 | if (*stream != op_wide) |
16195 | return { stream }; |
16196 | |
16197 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
16198 | return { wideStream }; |
16199 | } |
16200 | |
16201 | template<typename Functor> |
16202 | void setTargetLabel(BoundLabel value, Functor func) |
16203 | { |
16204 | if (isWide()) |
16205 | setTargetLabel<OpcodeSize::Wide>(value, func); |
16206 | else |
16207 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
16208 | } |
16209 | |
16210 | template <OpcodeSize size, typename Functor> |
16211 | void setTargetLabel(BoundLabel value, Functor func) |
16212 | { |
16213 | if (!Fits<BoundLabel, size>::check(value)) |
16214 | value = func(); |
16215 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
16216 | *stream = Fits<BoundLabel, size>::convert(value); |
16217 | } |
16218 | |
16219 | BoundLabel m_targetLabel; |
16220 | }; |
16221 | |
16222 | struct OpJtrue : public Instruction { |
16223 | static constexpr OpcodeID opcodeID = op_jtrue; |
16224 | |
16225 | static void emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel) |
16226 | { |
16227 | |
16228 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, condition, targetLabel) |
16229 | || emit<OpcodeSize::Wide, Assert, true>(gen, condition, targetLabel); |
16230 | } |
16231 | |
16232 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
16233 | static bool emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel) |
16234 | { |
16235 | bool didEmit = emitImpl<size, recordOpcode>(gen, condition, targetLabel); |
16236 | if (shouldAssert == Assert) |
16237 | ASSERT(didEmit); |
16238 | return didEmit; |
16239 | } |
16240 | |
16241 | private: |
16242 | template<OpcodeSize size, bool recordOpcode> |
16243 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel) |
16244 | { |
16245 | if (size == OpcodeSize::Wide) |
16246 | gen->alignWideOpcode(); |
16247 | if (Fits<unsigned, size>::check(opcodeID) |
16248 | && Fits<VirtualRegister, size>::check(condition) |
16249 | && Fits<BoundLabel, size>::check(targetLabel) |
16250 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
16251 | if (recordOpcode) |
16252 | gen->recordOpcode(opcodeID); |
16253 | if (size == OpcodeSize::Wide) |
16254 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
16255 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
16256 | gen->write(Fits<VirtualRegister, size>::convert(condition)); |
16257 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
16258 | return true; |
16259 | } |
16260 | return false; |
16261 | } |
16262 | |
16263 | public: |
16264 | template<typename Block> |
16265 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
16266 | { |
16267 | dumper->printLocationAndOp(__location, &"*jtrue" [!__isWide]); |
16268 | dumper->dumpOperand(m_condition, true); |
16269 | dumper->dumpOperand(m_targetLabel, false); |
16270 | } |
16271 | |
16272 | OpJtrue(const uint8_t* stream) |
16273 | : m_condition(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
16274 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2])) |
16275 | { |
16276 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16277 | } |
16278 | |
16279 | OpJtrue(const uint32_t* stream) |
16280 | : m_condition(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
16281 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[2])) |
16282 | { |
16283 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16284 | } |
16285 | |
16286 | static OpJtrue decode(const uint8_t* stream) |
16287 | { |
16288 | if (*stream != op_wide) |
16289 | return { stream }; |
16290 | |
16291 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
16292 | return { wideStream }; |
16293 | } |
16294 | |
16295 | template<typename Functor> |
16296 | void setCondition(VirtualRegister value, Functor func) |
16297 | { |
16298 | if (isWide()) |
16299 | setCondition<OpcodeSize::Wide>(value, func); |
16300 | else |
16301 | setCondition<OpcodeSize::Narrow>(value, func); |
16302 | } |
16303 | |
16304 | template <OpcodeSize size, typename Functor> |
16305 | void setCondition(VirtualRegister value, Functor func) |
16306 | { |
16307 | if (!Fits<VirtualRegister, size>::check(value)) |
16308 | value = func(); |
16309 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
16310 | *stream = Fits<VirtualRegister, size>::convert(value); |
16311 | } |
16312 | |
16313 | template<typename Functor> |
16314 | void setTargetLabel(BoundLabel value, Functor func) |
16315 | { |
16316 | if (isWide()) |
16317 | setTargetLabel<OpcodeSize::Wide>(value, func); |
16318 | else |
16319 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
16320 | } |
16321 | |
16322 | template <OpcodeSize size, typename Functor> |
16323 | void setTargetLabel(BoundLabel value, Functor func) |
16324 | { |
16325 | if (!Fits<BoundLabel, size>::check(value)) |
16326 | value = func(); |
16327 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
16328 | *stream = Fits<BoundLabel, size>::convert(value); |
16329 | } |
16330 | |
16331 | VirtualRegister m_condition; |
16332 | BoundLabel m_targetLabel; |
16333 | }; |
16334 | |
16335 | struct OpJfalse : public Instruction { |
16336 | static constexpr OpcodeID opcodeID = op_jfalse; |
16337 | |
16338 | static void emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel) |
16339 | { |
16340 | |
16341 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, condition, targetLabel) |
16342 | || emit<OpcodeSize::Wide, Assert, true>(gen, condition, targetLabel); |
16343 | } |
16344 | |
16345 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
16346 | static bool emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel) |
16347 | { |
16348 | bool didEmit = emitImpl<size, recordOpcode>(gen, condition, targetLabel); |
16349 | if (shouldAssert == Assert) |
16350 | ASSERT(didEmit); |
16351 | return didEmit; |
16352 | } |
16353 | |
16354 | private: |
16355 | template<OpcodeSize size, bool recordOpcode> |
16356 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel) |
16357 | { |
16358 | if (size == OpcodeSize::Wide) |
16359 | gen->alignWideOpcode(); |
16360 | if (Fits<unsigned, size>::check(opcodeID) |
16361 | && Fits<VirtualRegister, size>::check(condition) |
16362 | && Fits<BoundLabel, size>::check(targetLabel) |
16363 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
16364 | if (recordOpcode) |
16365 | gen->recordOpcode(opcodeID); |
16366 | if (size == OpcodeSize::Wide) |
16367 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
16368 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
16369 | gen->write(Fits<VirtualRegister, size>::convert(condition)); |
16370 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
16371 | return true; |
16372 | } |
16373 | return false; |
16374 | } |
16375 | |
16376 | public: |
16377 | template<typename Block> |
16378 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
16379 | { |
16380 | dumper->printLocationAndOp(__location, &"*jfalse" [!__isWide]); |
16381 | dumper->dumpOperand(m_condition, true); |
16382 | dumper->dumpOperand(m_targetLabel, false); |
16383 | } |
16384 | |
16385 | OpJfalse(const uint8_t* stream) |
16386 | : m_condition(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
16387 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2])) |
16388 | { |
16389 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16390 | } |
16391 | |
16392 | OpJfalse(const uint32_t* stream) |
16393 | : m_condition(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
16394 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[2])) |
16395 | { |
16396 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16397 | } |
16398 | |
16399 | static OpJfalse decode(const uint8_t* stream) |
16400 | { |
16401 | if (*stream != op_wide) |
16402 | return { stream }; |
16403 | |
16404 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
16405 | return { wideStream }; |
16406 | } |
16407 | |
16408 | template<typename Functor> |
16409 | void setCondition(VirtualRegister value, Functor func) |
16410 | { |
16411 | if (isWide()) |
16412 | setCondition<OpcodeSize::Wide>(value, func); |
16413 | else |
16414 | setCondition<OpcodeSize::Narrow>(value, func); |
16415 | } |
16416 | |
16417 | template <OpcodeSize size, typename Functor> |
16418 | void setCondition(VirtualRegister value, Functor func) |
16419 | { |
16420 | if (!Fits<VirtualRegister, size>::check(value)) |
16421 | value = func(); |
16422 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
16423 | *stream = Fits<VirtualRegister, size>::convert(value); |
16424 | } |
16425 | |
16426 | template<typename Functor> |
16427 | void setTargetLabel(BoundLabel value, Functor func) |
16428 | { |
16429 | if (isWide()) |
16430 | setTargetLabel<OpcodeSize::Wide>(value, func); |
16431 | else |
16432 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
16433 | } |
16434 | |
16435 | template <OpcodeSize size, typename Functor> |
16436 | void setTargetLabel(BoundLabel value, Functor func) |
16437 | { |
16438 | if (!Fits<BoundLabel, size>::check(value)) |
16439 | value = func(); |
16440 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
16441 | *stream = Fits<BoundLabel, size>::convert(value); |
16442 | } |
16443 | |
16444 | VirtualRegister m_condition; |
16445 | BoundLabel m_targetLabel; |
16446 | }; |
16447 | |
16448 | struct OpJeqNull : public Instruction { |
16449 | static constexpr OpcodeID opcodeID = op_jeq_null; |
16450 | |
16451 | static void emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel) |
16452 | { |
16453 | |
16454 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, value, targetLabel) |
16455 | || emit<OpcodeSize::Wide, Assert, true>(gen, value, targetLabel); |
16456 | } |
16457 | |
16458 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
16459 | static bool emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel) |
16460 | { |
16461 | bool didEmit = emitImpl<size, recordOpcode>(gen, value, targetLabel); |
16462 | if (shouldAssert == Assert) |
16463 | ASSERT(didEmit); |
16464 | return didEmit; |
16465 | } |
16466 | |
16467 | private: |
16468 | template<OpcodeSize size, bool recordOpcode> |
16469 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel) |
16470 | { |
16471 | if (size == OpcodeSize::Wide) |
16472 | gen->alignWideOpcode(); |
16473 | if (Fits<unsigned, size>::check(opcodeID) |
16474 | && Fits<VirtualRegister, size>::check(value) |
16475 | && Fits<BoundLabel, size>::check(targetLabel) |
16476 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
16477 | if (recordOpcode) |
16478 | gen->recordOpcode(opcodeID); |
16479 | if (size == OpcodeSize::Wide) |
16480 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
16481 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
16482 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
16483 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
16484 | return true; |
16485 | } |
16486 | return false; |
16487 | } |
16488 | |
16489 | public: |
16490 | template<typename Block> |
16491 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
16492 | { |
16493 | dumper->printLocationAndOp(__location, &"*jeq_null" [!__isWide]); |
16494 | dumper->dumpOperand(m_value, true); |
16495 | dumper->dumpOperand(m_targetLabel, false); |
16496 | } |
16497 | |
16498 | OpJeqNull(const uint8_t* stream) |
16499 | : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
16500 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2])) |
16501 | { |
16502 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16503 | } |
16504 | |
16505 | OpJeqNull(const uint32_t* stream) |
16506 | : m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
16507 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[2])) |
16508 | { |
16509 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16510 | } |
16511 | |
16512 | static OpJeqNull decode(const uint8_t* stream) |
16513 | { |
16514 | if (*stream != op_wide) |
16515 | return { stream }; |
16516 | |
16517 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
16518 | return { wideStream }; |
16519 | } |
16520 | |
16521 | template<typename Functor> |
16522 | void setValue(VirtualRegister value, Functor func) |
16523 | { |
16524 | if (isWide()) |
16525 | setValue<OpcodeSize::Wide>(value, func); |
16526 | else |
16527 | setValue<OpcodeSize::Narrow>(value, func); |
16528 | } |
16529 | |
16530 | template <OpcodeSize size, typename Functor> |
16531 | void setValue(VirtualRegister value, Functor func) |
16532 | { |
16533 | if (!Fits<VirtualRegister, size>::check(value)) |
16534 | value = func(); |
16535 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
16536 | *stream = Fits<VirtualRegister, size>::convert(value); |
16537 | } |
16538 | |
16539 | template<typename Functor> |
16540 | void setTargetLabel(BoundLabel value, Functor func) |
16541 | { |
16542 | if (isWide()) |
16543 | setTargetLabel<OpcodeSize::Wide>(value, func); |
16544 | else |
16545 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
16546 | } |
16547 | |
16548 | template <OpcodeSize size, typename Functor> |
16549 | void setTargetLabel(BoundLabel value, Functor func) |
16550 | { |
16551 | if (!Fits<BoundLabel, size>::check(value)) |
16552 | value = func(); |
16553 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
16554 | *stream = Fits<BoundLabel, size>::convert(value); |
16555 | } |
16556 | |
16557 | VirtualRegister m_value; |
16558 | BoundLabel m_targetLabel; |
16559 | }; |
16560 | |
16561 | struct OpJneqNull : public Instruction { |
16562 | static constexpr OpcodeID opcodeID = op_jneq_null; |
16563 | |
16564 | static void emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel) |
16565 | { |
16566 | |
16567 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, value, targetLabel) |
16568 | || emit<OpcodeSize::Wide, Assert, true>(gen, value, targetLabel); |
16569 | } |
16570 | |
16571 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
16572 | static bool emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel) |
16573 | { |
16574 | bool didEmit = emitImpl<size, recordOpcode>(gen, value, targetLabel); |
16575 | if (shouldAssert == Assert) |
16576 | ASSERT(didEmit); |
16577 | return didEmit; |
16578 | } |
16579 | |
16580 | private: |
16581 | template<OpcodeSize size, bool recordOpcode> |
16582 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel) |
16583 | { |
16584 | if (size == OpcodeSize::Wide) |
16585 | gen->alignWideOpcode(); |
16586 | if (Fits<unsigned, size>::check(opcodeID) |
16587 | && Fits<VirtualRegister, size>::check(value) |
16588 | && Fits<BoundLabel, size>::check(targetLabel) |
16589 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
16590 | if (recordOpcode) |
16591 | gen->recordOpcode(opcodeID); |
16592 | if (size == OpcodeSize::Wide) |
16593 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
16594 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
16595 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
16596 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
16597 | return true; |
16598 | } |
16599 | return false; |
16600 | } |
16601 | |
16602 | public: |
16603 | template<typename Block> |
16604 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
16605 | { |
16606 | dumper->printLocationAndOp(__location, &"*jneq_null" [!__isWide]); |
16607 | dumper->dumpOperand(m_value, true); |
16608 | dumper->dumpOperand(m_targetLabel, false); |
16609 | } |
16610 | |
16611 | OpJneqNull(const uint8_t* stream) |
16612 | : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
16613 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2])) |
16614 | { |
16615 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16616 | } |
16617 | |
16618 | OpJneqNull(const uint32_t* stream) |
16619 | : m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
16620 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[2])) |
16621 | { |
16622 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16623 | } |
16624 | |
16625 | static OpJneqNull decode(const uint8_t* stream) |
16626 | { |
16627 | if (*stream != op_wide) |
16628 | return { stream }; |
16629 | |
16630 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
16631 | return { wideStream }; |
16632 | } |
16633 | |
16634 | template<typename Functor> |
16635 | void setValue(VirtualRegister value, Functor func) |
16636 | { |
16637 | if (isWide()) |
16638 | setValue<OpcodeSize::Wide>(value, func); |
16639 | else |
16640 | setValue<OpcodeSize::Narrow>(value, func); |
16641 | } |
16642 | |
16643 | template <OpcodeSize size, typename Functor> |
16644 | void setValue(VirtualRegister value, Functor func) |
16645 | { |
16646 | if (!Fits<VirtualRegister, size>::check(value)) |
16647 | value = func(); |
16648 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
16649 | *stream = Fits<VirtualRegister, size>::convert(value); |
16650 | } |
16651 | |
16652 | template<typename Functor> |
16653 | void setTargetLabel(BoundLabel value, Functor func) |
16654 | { |
16655 | if (isWide()) |
16656 | setTargetLabel<OpcodeSize::Wide>(value, func); |
16657 | else |
16658 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
16659 | } |
16660 | |
16661 | template <OpcodeSize size, typename Functor> |
16662 | void setTargetLabel(BoundLabel value, Functor func) |
16663 | { |
16664 | if (!Fits<BoundLabel, size>::check(value)) |
16665 | value = func(); |
16666 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
16667 | *stream = Fits<BoundLabel, size>::convert(value); |
16668 | } |
16669 | |
16670 | VirtualRegister m_value; |
16671 | BoundLabel m_targetLabel; |
16672 | }; |
16673 | |
16674 | struct OpJeq : public Instruction { |
16675 | static constexpr OpcodeID opcodeID = op_jeq; |
16676 | |
16677 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
16678 | { |
16679 | |
16680 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
16681 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
16682 | } |
16683 | |
16684 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
16685 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
16686 | { |
16687 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
16688 | if (shouldAssert == Assert) |
16689 | ASSERT(didEmit); |
16690 | return didEmit; |
16691 | } |
16692 | |
16693 | private: |
16694 | template<OpcodeSize size, bool recordOpcode> |
16695 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
16696 | { |
16697 | if (size == OpcodeSize::Wide) |
16698 | gen->alignWideOpcode(); |
16699 | if (Fits<unsigned, size>::check(opcodeID) |
16700 | && Fits<VirtualRegister, size>::check(lhs) |
16701 | && Fits<VirtualRegister, size>::check(rhs) |
16702 | && Fits<BoundLabel, size>::check(targetLabel) |
16703 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
16704 | if (recordOpcode) |
16705 | gen->recordOpcode(opcodeID); |
16706 | if (size == OpcodeSize::Wide) |
16707 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
16708 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
16709 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
16710 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
16711 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
16712 | return true; |
16713 | } |
16714 | return false; |
16715 | } |
16716 | |
16717 | public: |
16718 | template<typename Block> |
16719 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
16720 | { |
16721 | dumper->printLocationAndOp(__location, &"*jeq" [!__isWide]); |
16722 | dumper->dumpOperand(m_lhs, true); |
16723 | dumper->dumpOperand(m_rhs, false); |
16724 | dumper->dumpOperand(m_targetLabel, false); |
16725 | } |
16726 | |
16727 | OpJeq(const uint8_t* stream) |
16728 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
16729 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
16730 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
16731 | { |
16732 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16733 | } |
16734 | |
16735 | OpJeq(const uint32_t* stream) |
16736 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
16737 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
16738 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
16739 | { |
16740 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16741 | } |
16742 | |
16743 | static OpJeq decode(const uint8_t* stream) |
16744 | { |
16745 | if (*stream != op_wide) |
16746 | return { stream }; |
16747 | |
16748 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
16749 | return { wideStream }; |
16750 | } |
16751 | |
16752 | template<typename Functor> |
16753 | void setLhs(VirtualRegister value, Functor func) |
16754 | { |
16755 | if (isWide()) |
16756 | setLhs<OpcodeSize::Wide>(value, func); |
16757 | else |
16758 | setLhs<OpcodeSize::Narrow>(value, func); |
16759 | } |
16760 | |
16761 | template <OpcodeSize size, typename Functor> |
16762 | void setLhs(VirtualRegister value, Functor func) |
16763 | { |
16764 | if (!Fits<VirtualRegister, size>::check(value)) |
16765 | value = func(); |
16766 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
16767 | *stream = Fits<VirtualRegister, size>::convert(value); |
16768 | } |
16769 | |
16770 | template<typename Functor> |
16771 | void setRhs(VirtualRegister value, Functor func) |
16772 | { |
16773 | if (isWide()) |
16774 | setRhs<OpcodeSize::Wide>(value, func); |
16775 | else |
16776 | setRhs<OpcodeSize::Narrow>(value, func); |
16777 | } |
16778 | |
16779 | template <OpcodeSize size, typename Functor> |
16780 | void setRhs(VirtualRegister value, Functor func) |
16781 | { |
16782 | if (!Fits<VirtualRegister, size>::check(value)) |
16783 | value = func(); |
16784 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
16785 | *stream = Fits<VirtualRegister, size>::convert(value); |
16786 | } |
16787 | |
16788 | template<typename Functor> |
16789 | void setTargetLabel(BoundLabel value, Functor func) |
16790 | { |
16791 | if (isWide()) |
16792 | setTargetLabel<OpcodeSize::Wide>(value, func); |
16793 | else |
16794 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
16795 | } |
16796 | |
16797 | template <OpcodeSize size, typename Functor> |
16798 | void setTargetLabel(BoundLabel value, Functor func) |
16799 | { |
16800 | if (!Fits<BoundLabel, size>::check(value)) |
16801 | value = func(); |
16802 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
16803 | *stream = Fits<BoundLabel, size>::convert(value); |
16804 | } |
16805 | |
16806 | VirtualRegister m_lhs; |
16807 | VirtualRegister m_rhs; |
16808 | BoundLabel m_targetLabel; |
16809 | }; |
16810 | |
16811 | struct OpJstricteq : public Instruction { |
16812 | static constexpr OpcodeID opcodeID = op_jstricteq; |
16813 | |
16814 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
16815 | { |
16816 | |
16817 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
16818 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
16819 | } |
16820 | |
16821 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
16822 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
16823 | { |
16824 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
16825 | if (shouldAssert == Assert) |
16826 | ASSERT(didEmit); |
16827 | return didEmit; |
16828 | } |
16829 | |
16830 | private: |
16831 | template<OpcodeSize size, bool recordOpcode> |
16832 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
16833 | { |
16834 | if (size == OpcodeSize::Wide) |
16835 | gen->alignWideOpcode(); |
16836 | if (Fits<unsigned, size>::check(opcodeID) |
16837 | && Fits<VirtualRegister, size>::check(lhs) |
16838 | && Fits<VirtualRegister, size>::check(rhs) |
16839 | && Fits<BoundLabel, size>::check(targetLabel) |
16840 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
16841 | if (recordOpcode) |
16842 | gen->recordOpcode(opcodeID); |
16843 | if (size == OpcodeSize::Wide) |
16844 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
16845 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
16846 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
16847 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
16848 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
16849 | return true; |
16850 | } |
16851 | return false; |
16852 | } |
16853 | |
16854 | public: |
16855 | template<typename Block> |
16856 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
16857 | { |
16858 | dumper->printLocationAndOp(__location, &"*jstricteq" [!__isWide]); |
16859 | dumper->dumpOperand(m_lhs, true); |
16860 | dumper->dumpOperand(m_rhs, false); |
16861 | dumper->dumpOperand(m_targetLabel, false); |
16862 | } |
16863 | |
16864 | OpJstricteq(const uint8_t* stream) |
16865 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
16866 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
16867 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
16868 | { |
16869 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16870 | } |
16871 | |
16872 | OpJstricteq(const uint32_t* stream) |
16873 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
16874 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
16875 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
16876 | { |
16877 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
16878 | } |
16879 | |
16880 | static OpJstricteq decode(const uint8_t* stream) |
16881 | { |
16882 | if (*stream != op_wide) |
16883 | return { stream }; |
16884 | |
16885 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
16886 | return { wideStream }; |
16887 | } |
16888 | |
16889 | template<typename Functor> |
16890 | void setLhs(VirtualRegister value, Functor func) |
16891 | { |
16892 | if (isWide()) |
16893 | setLhs<OpcodeSize::Wide>(value, func); |
16894 | else |
16895 | setLhs<OpcodeSize::Narrow>(value, func); |
16896 | } |
16897 | |
16898 | template <OpcodeSize size, typename Functor> |
16899 | void setLhs(VirtualRegister value, Functor func) |
16900 | { |
16901 | if (!Fits<VirtualRegister, size>::check(value)) |
16902 | value = func(); |
16903 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
16904 | *stream = Fits<VirtualRegister, size>::convert(value); |
16905 | } |
16906 | |
16907 | template<typename Functor> |
16908 | void setRhs(VirtualRegister value, Functor func) |
16909 | { |
16910 | if (isWide()) |
16911 | setRhs<OpcodeSize::Wide>(value, func); |
16912 | else |
16913 | setRhs<OpcodeSize::Narrow>(value, func); |
16914 | } |
16915 | |
16916 | template <OpcodeSize size, typename Functor> |
16917 | void setRhs(VirtualRegister value, Functor func) |
16918 | { |
16919 | if (!Fits<VirtualRegister, size>::check(value)) |
16920 | value = func(); |
16921 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
16922 | *stream = Fits<VirtualRegister, size>::convert(value); |
16923 | } |
16924 | |
16925 | template<typename Functor> |
16926 | void setTargetLabel(BoundLabel value, Functor func) |
16927 | { |
16928 | if (isWide()) |
16929 | setTargetLabel<OpcodeSize::Wide>(value, func); |
16930 | else |
16931 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
16932 | } |
16933 | |
16934 | template <OpcodeSize size, typename Functor> |
16935 | void setTargetLabel(BoundLabel value, Functor func) |
16936 | { |
16937 | if (!Fits<BoundLabel, size>::check(value)) |
16938 | value = func(); |
16939 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
16940 | *stream = Fits<BoundLabel, size>::convert(value); |
16941 | } |
16942 | |
16943 | VirtualRegister m_lhs; |
16944 | VirtualRegister m_rhs; |
16945 | BoundLabel m_targetLabel; |
16946 | }; |
16947 | |
16948 | struct OpJneq : public Instruction { |
16949 | static constexpr OpcodeID opcodeID = op_jneq; |
16950 | |
16951 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
16952 | { |
16953 | |
16954 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
16955 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
16956 | } |
16957 | |
16958 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
16959 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
16960 | { |
16961 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
16962 | if (shouldAssert == Assert) |
16963 | ASSERT(didEmit); |
16964 | return didEmit; |
16965 | } |
16966 | |
16967 | private: |
16968 | template<OpcodeSize size, bool recordOpcode> |
16969 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
16970 | { |
16971 | if (size == OpcodeSize::Wide) |
16972 | gen->alignWideOpcode(); |
16973 | if (Fits<unsigned, size>::check(opcodeID) |
16974 | && Fits<VirtualRegister, size>::check(lhs) |
16975 | && Fits<VirtualRegister, size>::check(rhs) |
16976 | && Fits<BoundLabel, size>::check(targetLabel) |
16977 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
16978 | if (recordOpcode) |
16979 | gen->recordOpcode(opcodeID); |
16980 | if (size == OpcodeSize::Wide) |
16981 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
16982 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
16983 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
16984 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
16985 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
16986 | return true; |
16987 | } |
16988 | return false; |
16989 | } |
16990 | |
16991 | public: |
16992 | template<typename Block> |
16993 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
16994 | { |
16995 | dumper->printLocationAndOp(__location, &"*jneq" [!__isWide]); |
16996 | dumper->dumpOperand(m_lhs, true); |
16997 | dumper->dumpOperand(m_rhs, false); |
16998 | dumper->dumpOperand(m_targetLabel, false); |
16999 | } |
17000 | |
17001 | OpJneq(const uint8_t* stream) |
17002 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
17003 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
17004 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
17005 | { |
17006 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17007 | } |
17008 | |
17009 | OpJneq(const uint32_t* stream) |
17010 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
17011 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
17012 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
17013 | { |
17014 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17015 | } |
17016 | |
17017 | static OpJneq decode(const uint8_t* stream) |
17018 | { |
17019 | if (*stream != op_wide) |
17020 | return { stream }; |
17021 | |
17022 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
17023 | return { wideStream }; |
17024 | } |
17025 | |
17026 | template<typename Functor> |
17027 | void setLhs(VirtualRegister value, Functor func) |
17028 | { |
17029 | if (isWide()) |
17030 | setLhs<OpcodeSize::Wide>(value, func); |
17031 | else |
17032 | setLhs<OpcodeSize::Narrow>(value, func); |
17033 | } |
17034 | |
17035 | template <OpcodeSize size, typename Functor> |
17036 | void setLhs(VirtualRegister value, Functor func) |
17037 | { |
17038 | if (!Fits<VirtualRegister, size>::check(value)) |
17039 | value = func(); |
17040 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
17041 | *stream = Fits<VirtualRegister, size>::convert(value); |
17042 | } |
17043 | |
17044 | template<typename Functor> |
17045 | void setRhs(VirtualRegister value, Functor func) |
17046 | { |
17047 | if (isWide()) |
17048 | setRhs<OpcodeSize::Wide>(value, func); |
17049 | else |
17050 | setRhs<OpcodeSize::Narrow>(value, func); |
17051 | } |
17052 | |
17053 | template <OpcodeSize size, typename Functor> |
17054 | void setRhs(VirtualRegister value, Functor func) |
17055 | { |
17056 | if (!Fits<VirtualRegister, size>::check(value)) |
17057 | value = func(); |
17058 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
17059 | *stream = Fits<VirtualRegister, size>::convert(value); |
17060 | } |
17061 | |
17062 | template<typename Functor> |
17063 | void setTargetLabel(BoundLabel value, Functor func) |
17064 | { |
17065 | if (isWide()) |
17066 | setTargetLabel<OpcodeSize::Wide>(value, func); |
17067 | else |
17068 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
17069 | } |
17070 | |
17071 | template <OpcodeSize size, typename Functor> |
17072 | void setTargetLabel(BoundLabel value, Functor func) |
17073 | { |
17074 | if (!Fits<BoundLabel, size>::check(value)) |
17075 | value = func(); |
17076 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
17077 | *stream = Fits<BoundLabel, size>::convert(value); |
17078 | } |
17079 | |
17080 | VirtualRegister m_lhs; |
17081 | VirtualRegister m_rhs; |
17082 | BoundLabel m_targetLabel; |
17083 | }; |
17084 | |
17085 | struct OpJnstricteq : public Instruction { |
17086 | static constexpr OpcodeID opcodeID = op_jnstricteq; |
17087 | |
17088 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17089 | { |
17090 | |
17091 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
17092 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
17093 | } |
17094 | |
17095 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
17096 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17097 | { |
17098 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
17099 | if (shouldAssert == Assert) |
17100 | ASSERT(didEmit); |
17101 | return didEmit; |
17102 | } |
17103 | |
17104 | private: |
17105 | template<OpcodeSize size, bool recordOpcode> |
17106 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17107 | { |
17108 | if (size == OpcodeSize::Wide) |
17109 | gen->alignWideOpcode(); |
17110 | if (Fits<unsigned, size>::check(opcodeID) |
17111 | && Fits<VirtualRegister, size>::check(lhs) |
17112 | && Fits<VirtualRegister, size>::check(rhs) |
17113 | && Fits<BoundLabel, size>::check(targetLabel) |
17114 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
17115 | if (recordOpcode) |
17116 | gen->recordOpcode(opcodeID); |
17117 | if (size == OpcodeSize::Wide) |
17118 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
17119 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
17120 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
17121 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
17122 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
17123 | return true; |
17124 | } |
17125 | return false; |
17126 | } |
17127 | |
17128 | public: |
17129 | template<typename Block> |
17130 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
17131 | { |
17132 | dumper->printLocationAndOp(__location, &"*jnstricteq" [!__isWide]); |
17133 | dumper->dumpOperand(m_lhs, true); |
17134 | dumper->dumpOperand(m_rhs, false); |
17135 | dumper->dumpOperand(m_targetLabel, false); |
17136 | } |
17137 | |
17138 | OpJnstricteq(const uint8_t* stream) |
17139 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
17140 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
17141 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
17142 | { |
17143 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17144 | } |
17145 | |
17146 | OpJnstricteq(const uint32_t* stream) |
17147 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
17148 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
17149 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
17150 | { |
17151 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17152 | } |
17153 | |
17154 | static OpJnstricteq decode(const uint8_t* stream) |
17155 | { |
17156 | if (*stream != op_wide) |
17157 | return { stream }; |
17158 | |
17159 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
17160 | return { wideStream }; |
17161 | } |
17162 | |
17163 | template<typename Functor> |
17164 | void setLhs(VirtualRegister value, Functor func) |
17165 | { |
17166 | if (isWide()) |
17167 | setLhs<OpcodeSize::Wide>(value, func); |
17168 | else |
17169 | setLhs<OpcodeSize::Narrow>(value, func); |
17170 | } |
17171 | |
17172 | template <OpcodeSize size, typename Functor> |
17173 | void setLhs(VirtualRegister value, Functor func) |
17174 | { |
17175 | if (!Fits<VirtualRegister, size>::check(value)) |
17176 | value = func(); |
17177 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
17178 | *stream = Fits<VirtualRegister, size>::convert(value); |
17179 | } |
17180 | |
17181 | template<typename Functor> |
17182 | void setRhs(VirtualRegister value, Functor func) |
17183 | { |
17184 | if (isWide()) |
17185 | setRhs<OpcodeSize::Wide>(value, func); |
17186 | else |
17187 | setRhs<OpcodeSize::Narrow>(value, func); |
17188 | } |
17189 | |
17190 | template <OpcodeSize size, typename Functor> |
17191 | void setRhs(VirtualRegister value, Functor func) |
17192 | { |
17193 | if (!Fits<VirtualRegister, size>::check(value)) |
17194 | value = func(); |
17195 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
17196 | *stream = Fits<VirtualRegister, size>::convert(value); |
17197 | } |
17198 | |
17199 | template<typename Functor> |
17200 | void setTargetLabel(BoundLabel value, Functor func) |
17201 | { |
17202 | if (isWide()) |
17203 | setTargetLabel<OpcodeSize::Wide>(value, func); |
17204 | else |
17205 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
17206 | } |
17207 | |
17208 | template <OpcodeSize size, typename Functor> |
17209 | void setTargetLabel(BoundLabel value, Functor func) |
17210 | { |
17211 | if (!Fits<BoundLabel, size>::check(value)) |
17212 | value = func(); |
17213 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
17214 | *stream = Fits<BoundLabel, size>::convert(value); |
17215 | } |
17216 | |
17217 | VirtualRegister m_lhs; |
17218 | VirtualRegister m_rhs; |
17219 | BoundLabel m_targetLabel; |
17220 | }; |
17221 | |
17222 | struct OpJless : public Instruction { |
17223 | static constexpr OpcodeID opcodeID = op_jless; |
17224 | |
17225 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17226 | { |
17227 | |
17228 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
17229 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
17230 | } |
17231 | |
17232 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
17233 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17234 | { |
17235 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
17236 | if (shouldAssert == Assert) |
17237 | ASSERT(didEmit); |
17238 | return didEmit; |
17239 | } |
17240 | |
17241 | private: |
17242 | template<OpcodeSize size, bool recordOpcode> |
17243 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17244 | { |
17245 | if (size == OpcodeSize::Wide) |
17246 | gen->alignWideOpcode(); |
17247 | if (Fits<unsigned, size>::check(opcodeID) |
17248 | && Fits<VirtualRegister, size>::check(lhs) |
17249 | && Fits<VirtualRegister, size>::check(rhs) |
17250 | && Fits<BoundLabel, size>::check(targetLabel) |
17251 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
17252 | if (recordOpcode) |
17253 | gen->recordOpcode(opcodeID); |
17254 | if (size == OpcodeSize::Wide) |
17255 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
17256 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
17257 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
17258 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
17259 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
17260 | return true; |
17261 | } |
17262 | return false; |
17263 | } |
17264 | |
17265 | public: |
17266 | template<typename Block> |
17267 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
17268 | { |
17269 | dumper->printLocationAndOp(__location, &"*jless" [!__isWide]); |
17270 | dumper->dumpOperand(m_lhs, true); |
17271 | dumper->dumpOperand(m_rhs, false); |
17272 | dumper->dumpOperand(m_targetLabel, false); |
17273 | } |
17274 | |
17275 | OpJless(const uint8_t* stream) |
17276 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
17277 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
17278 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
17279 | { |
17280 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17281 | } |
17282 | |
17283 | OpJless(const uint32_t* stream) |
17284 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
17285 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
17286 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
17287 | { |
17288 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17289 | } |
17290 | |
17291 | static OpJless decode(const uint8_t* stream) |
17292 | { |
17293 | if (*stream != op_wide) |
17294 | return { stream }; |
17295 | |
17296 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
17297 | return { wideStream }; |
17298 | } |
17299 | |
17300 | template<typename Functor> |
17301 | void setLhs(VirtualRegister value, Functor func) |
17302 | { |
17303 | if (isWide()) |
17304 | setLhs<OpcodeSize::Wide>(value, func); |
17305 | else |
17306 | setLhs<OpcodeSize::Narrow>(value, func); |
17307 | } |
17308 | |
17309 | template <OpcodeSize size, typename Functor> |
17310 | void setLhs(VirtualRegister value, Functor func) |
17311 | { |
17312 | if (!Fits<VirtualRegister, size>::check(value)) |
17313 | value = func(); |
17314 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
17315 | *stream = Fits<VirtualRegister, size>::convert(value); |
17316 | } |
17317 | |
17318 | template<typename Functor> |
17319 | void setRhs(VirtualRegister value, Functor func) |
17320 | { |
17321 | if (isWide()) |
17322 | setRhs<OpcodeSize::Wide>(value, func); |
17323 | else |
17324 | setRhs<OpcodeSize::Narrow>(value, func); |
17325 | } |
17326 | |
17327 | template <OpcodeSize size, typename Functor> |
17328 | void setRhs(VirtualRegister value, Functor func) |
17329 | { |
17330 | if (!Fits<VirtualRegister, size>::check(value)) |
17331 | value = func(); |
17332 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
17333 | *stream = Fits<VirtualRegister, size>::convert(value); |
17334 | } |
17335 | |
17336 | template<typename Functor> |
17337 | void setTargetLabel(BoundLabel value, Functor func) |
17338 | { |
17339 | if (isWide()) |
17340 | setTargetLabel<OpcodeSize::Wide>(value, func); |
17341 | else |
17342 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
17343 | } |
17344 | |
17345 | template <OpcodeSize size, typename Functor> |
17346 | void setTargetLabel(BoundLabel value, Functor func) |
17347 | { |
17348 | if (!Fits<BoundLabel, size>::check(value)) |
17349 | value = func(); |
17350 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
17351 | *stream = Fits<BoundLabel, size>::convert(value); |
17352 | } |
17353 | |
17354 | VirtualRegister m_lhs; |
17355 | VirtualRegister m_rhs; |
17356 | BoundLabel m_targetLabel; |
17357 | }; |
17358 | |
17359 | struct OpJlesseq : public Instruction { |
17360 | static constexpr OpcodeID opcodeID = op_jlesseq; |
17361 | |
17362 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17363 | { |
17364 | |
17365 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
17366 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
17367 | } |
17368 | |
17369 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
17370 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17371 | { |
17372 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
17373 | if (shouldAssert == Assert) |
17374 | ASSERT(didEmit); |
17375 | return didEmit; |
17376 | } |
17377 | |
17378 | private: |
17379 | template<OpcodeSize size, bool recordOpcode> |
17380 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17381 | { |
17382 | if (size == OpcodeSize::Wide) |
17383 | gen->alignWideOpcode(); |
17384 | if (Fits<unsigned, size>::check(opcodeID) |
17385 | && Fits<VirtualRegister, size>::check(lhs) |
17386 | && Fits<VirtualRegister, size>::check(rhs) |
17387 | && Fits<BoundLabel, size>::check(targetLabel) |
17388 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
17389 | if (recordOpcode) |
17390 | gen->recordOpcode(opcodeID); |
17391 | if (size == OpcodeSize::Wide) |
17392 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
17393 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
17394 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
17395 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
17396 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
17397 | return true; |
17398 | } |
17399 | return false; |
17400 | } |
17401 | |
17402 | public: |
17403 | template<typename Block> |
17404 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
17405 | { |
17406 | dumper->printLocationAndOp(__location, &"*jlesseq" [!__isWide]); |
17407 | dumper->dumpOperand(m_lhs, true); |
17408 | dumper->dumpOperand(m_rhs, false); |
17409 | dumper->dumpOperand(m_targetLabel, false); |
17410 | } |
17411 | |
17412 | OpJlesseq(const uint8_t* stream) |
17413 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
17414 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
17415 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
17416 | { |
17417 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17418 | } |
17419 | |
17420 | OpJlesseq(const uint32_t* stream) |
17421 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
17422 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
17423 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
17424 | { |
17425 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17426 | } |
17427 | |
17428 | static OpJlesseq decode(const uint8_t* stream) |
17429 | { |
17430 | if (*stream != op_wide) |
17431 | return { stream }; |
17432 | |
17433 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
17434 | return { wideStream }; |
17435 | } |
17436 | |
17437 | template<typename Functor> |
17438 | void setLhs(VirtualRegister value, Functor func) |
17439 | { |
17440 | if (isWide()) |
17441 | setLhs<OpcodeSize::Wide>(value, func); |
17442 | else |
17443 | setLhs<OpcodeSize::Narrow>(value, func); |
17444 | } |
17445 | |
17446 | template <OpcodeSize size, typename Functor> |
17447 | void setLhs(VirtualRegister value, Functor func) |
17448 | { |
17449 | if (!Fits<VirtualRegister, size>::check(value)) |
17450 | value = func(); |
17451 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
17452 | *stream = Fits<VirtualRegister, size>::convert(value); |
17453 | } |
17454 | |
17455 | template<typename Functor> |
17456 | void setRhs(VirtualRegister value, Functor func) |
17457 | { |
17458 | if (isWide()) |
17459 | setRhs<OpcodeSize::Wide>(value, func); |
17460 | else |
17461 | setRhs<OpcodeSize::Narrow>(value, func); |
17462 | } |
17463 | |
17464 | template <OpcodeSize size, typename Functor> |
17465 | void setRhs(VirtualRegister value, Functor func) |
17466 | { |
17467 | if (!Fits<VirtualRegister, size>::check(value)) |
17468 | value = func(); |
17469 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
17470 | *stream = Fits<VirtualRegister, size>::convert(value); |
17471 | } |
17472 | |
17473 | template<typename Functor> |
17474 | void setTargetLabel(BoundLabel value, Functor func) |
17475 | { |
17476 | if (isWide()) |
17477 | setTargetLabel<OpcodeSize::Wide>(value, func); |
17478 | else |
17479 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
17480 | } |
17481 | |
17482 | template <OpcodeSize size, typename Functor> |
17483 | void setTargetLabel(BoundLabel value, Functor func) |
17484 | { |
17485 | if (!Fits<BoundLabel, size>::check(value)) |
17486 | value = func(); |
17487 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
17488 | *stream = Fits<BoundLabel, size>::convert(value); |
17489 | } |
17490 | |
17491 | VirtualRegister m_lhs; |
17492 | VirtualRegister m_rhs; |
17493 | BoundLabel m_targetLabel; |
17494 | }; |
17495 | |
17496 | struct OpJgreater : public Instruction { |
17497 | static constexpr OpcodeID opcodeID = op_jgreater; |
17498 | |
17499 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17500 | { |
17501 | |
17502 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
17503 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
17504 | } |
17505 | |
17506 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
17507 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17508 | { |
17509 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
17510 | if (shouldAssert == Assert) |
17511 | ASSERT(didEmit); |
17512 | return didEmit; |
17513 | } |
17514 | |
17515 | private: |
17516 | template<OpcodeSize size, bool recordOpcode> |
17517 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17518 | { |
17519 | if (size == OpcodeSize::Wide) |
17520 | gen->alignWideOpcode(); |
17521 | if (Fits<unsigned, size>::check(opcodeID) |
17522 | && Fits<VirtualRegister, size>::check(lhs) |
17523 | && Fits<VirtualRegister, size>::check(rhs) |
17524 | && Fits<BoundLabel, size>::check(targetLabel) |
17525 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
17526 | if (recordOpcode) |
17527 | gen->recordOpcode(opcodeID); |
17528 | if (size == OpcodeSize::Wide) |
17529 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
17530 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
17531 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
17532 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
17533 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
17534 | return true; |
17535 | } |
17536 | return false; |
17537 | } |
17538 | |
17539 | public: |
17540 | template<typename Block> |
17541 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
17542 | { |
17543 | dumper->printLocationAndOp(__location, &"*jgreater" [!__isWide]); |
17544 | dumper->dumpOperand(m_lhs, true); |
17545 | dumper->dumpOperand(m_rhs, false); |
17546 | dumper->dumpOperand(m_targetLabel, false); |
17547 | } |
17548 | |
17549 | OpJgreater(const uint8_t* stream) |
17550 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
17551 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
17552 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
17553 | { |
17554 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17555 | } |
17556 | |
17557 | OpJgreater(const uint32_t* stream) |
17558 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
17559 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
17560 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
17561 | { |
17562 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17563 | } |
17564 | |
17565 | static OpJgreater decode(const uint8_t* stream) |
17566 | { |
17567 | if (*stream != op_wide) |
17568 | return { stream }; |
17569 | |
17570 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
17571 | return { wideStream }; |
17572 | } |
17573 | |
17574 | template<typename Functor> |
17575 | void setLhs(VirtualRegister value, Functor func) |
17576 | { |
17577 | if (isWide()) |
17578 | setLhs<OpcodeSize::Wide>(value, func); |
17579 | else |
17580 | setLhs<OpcodeSize::Narrow>(value, func); |
17581 | } |
17582 | |
17583 | template <OpcodeSize size, typename Functor> |
17584 | void setLhs(VirtualRegister value, Functor func) |
17585 | { |
17586 | if (!Fits<VirtualRegister, size>::check(value)) |
17587 | value = func(); |
17588 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
17589 | *stream = Fits<VirtualRegister, size>::convert(value); |
17590 | } |
17591 | |
17592 | template<typename Functor> |
17593 | void setRhs(VirtualRegister value, Functor func) |
17594 | { |
17595 | if (isWide()) |
17596 | setRhs<OpcodeSize::Wide>(value, func); |
17597 | else |
17598 | setRhs<OpcodeSize::Narrow>(value, func); |
17599 | } |
17600 | |
17601 | template <OpcodeSize size, typename Functor> |
17602 | void setRhs(VirtualRegister value, Functor func) |
17603 | { |
17604 | if (!Fits<VirtualRegister, size>::check(value)) |
17605 | value = func(); |
17606 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
17607 | *stream = Fits<VirtualRegister, size>::convert(value); |
17608 | } |
17609 | |
17610 | template<typename Functor> |
17611 | void setTargetLabel(BoundLabel value, Functor func) |
17612 | { |
17613 | if (isWide()) |
17614 | setTargetLabel<OpcodeSize::Wide>(value, func); |
17615 | else |
17616 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
17617 | } |
17618 | |
17619 | template <OpcodeSize size, typename Functor> |
17620 | void setTargetLabel(BoundLabel value, Functor func) |
17621 | { |
17622 | if (!Fits<BoundLabel, size>::check(value)) |
17623 | value = func(); |
17624 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
17625 | *stream = Fits<BoundLabel, size>::convert(value); |
17626 | } |
17627 | |
17628 | VirtualRegister m_lhs; |
17629 | VirtualRegister m_rhs; |
17630 | BoundLabel m_targetLabel; |
17631 | }; |
17632 | |
17633 | struct OpJgreatereq : public Instruction { |
17634 | static constexpr OpcodeID opcodeID = op_jgreatereq; |
17635 | |
17636 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17637 | { |
17638 | |
17639 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
17640 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
17641 | } |
17642 | |
17643 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
17644 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17645 | { |
17646 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
17647 | if (shouldAssert == Assert) |
17648 | ASSERT(didEmit); |
17649 | return didEmit; |
17650 | } |
17651 | |
17652 | private: |
17653 | template<OpcodeSize size, bool recordOpcode> |
17654 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17655 | { |
17656 | if (size == OpcodeSize::Wide) |
17657 | gen->alignWideOpcode(); |
17658 | if (Fits<unsigned, size>::check(opcodeID) |
17659 | && Fits<VirtualRegister, size>::check(lhs) |
17660 | && Fits<VirtualRegister, size>::check(rhs) |
17661 | && Fits<BoundLabel, size>::check(targetLabel) |
17662 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
17663 | if (recordOpcode) |
17664 | gen->recordOpcode(opcodeID); |
17665 | if (size == OpcodeSize::Wide) |
17666 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
17667 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
17668 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
17669 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
17670 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
17671 | return true; |
17672 | } |
17673 | return false; |
17674 | } |
17675 | |
17676 | public: |
17677 | template<typename Block> |
17678 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
17679 | { |
17680 | dumper->printLocationAndOp(__location, &"*jgreatereq" [!__isWide]); |
17681 | dumper->dumpOperand(m_lhs, true); |
17682 | dumper->dumpOperand(m_rhs, false); |
17683 | dumper->dumpOperand(m_targetLabel, false); |
17684 | } |
17685 | |
17686 | OpJgreatereq(const uint8_t* stream) |
17687 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
17688 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
17689 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
17690 | { |
17691 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17692 | } |
17693 | |
17694 | OpJgreatereq(const uint32_t* stream) |
17695 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
17696 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
17697 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
17698 | { |
17699 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17700 | } |
17701 | |
17702 | static OpJgreatereq decode(const uint8_t* stream) |
17703 | { |
17704 | if (*stream != op_wide) |
17705 | return { stream }; |
17706 | |
17707 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
17708 | return { wideStream }; |
17709 | } |
17710 | |
17711 | template<typename Functor> |
17712 | void setLhs(VirtualRegister value, Functor func) |
17713 | { |
17714 | if (isWide()) |
17715 | setLhs<OpcodeSize::Wide>(value, func); |
17716 | else |
17717 | setLhs<OpcodeSize::Narrow>(value, func); |
17718 | } |
17719 | |
17720 | template <OpcodeSize size, typename Functor> |
17721 | void setLhs(VirtualRegister value, Functor func) |
17722 | { |
17723 | if (!Fits<VirtualRegister, size>::check(value)) |
17724 | value = func(); |
17725 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
17726 | *stream = Fits<VirtualRegister, size>::convert(value); |
17727 | } |
17728 | |
17729 | template<typename Functor> |
17730 | void setRhs(VirtualRegister value, Functor func) |
17731 | { |
17732 | if (isWide()) |
17733 | setRhs<OpcodeSize::Wide>(value, func); |
17734 | else |
17735 | setRhs<OpcodeSize::Narrow>(value, func); |
17736 | } |
17737 | |
17738 | template <OpcodeSize size, typename Functor> |
17739 | void setRhs(VirtualRegister value, Functor func) |
17740 | { |
17741 | if (!Fits<VirtualRegister, size>::check(value)) |
17742 | value = func(); |
17743 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
17744 | *stream = Fits<VirtualRegister, size>::convert(value); |
17745 | } |
17746 | |
17747 | template<typename Functor> |
17748 | void setTargetLabel(BoundLabel value, Functor func) |
17749 | { |
17750 | if (isWide()) |
17751 | setTargetLabel<OpcodeSize::Wide>(value, func); |
17752 | else |
17753 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
17754 | } |
17755 | |
17756 | template <OpcodeSize size, typename Functor> |
17757 | void setTargetLabel(BoundLabel value, Functor func) |
17758 | { |
17759 | if (!Fits<BoundLabel, size>::check(value)) |
17760 | value = func(); |
17761 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
17762 | *stream = Fits<BoundLabel, size>::convert(value); |
17763 | } |
17764 | |
17765 | VirtualRegister m_lhs; |
17766 | VirtualRegister m_rhs; |
17767 | BoundLabel m_targetLabel; |
17768 | }; |
17769 | |
17770 | struct OpJnless : public Instruction { |
17771 | static constexpr OpcodeID opcodeID = op_jnless; |
17772 | |
17773 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17774 | { |
17775 | |
17776 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
17777 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
17778 | } |
17779 | |
17780 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
17781 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17782 | { |
17783 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
17784 | if (shouldAssert == Assert) |
17785 | ASSERT(didEmit); |
17786 | return didEmit; |
17787 | } |
17788 | |
17789 | private: |
17790 | template<OpcodeSize size, bool recordOpcode> |
17791 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17792 | { |
17793 | if (size == OpcodeSize::Wide) |
17794 | gen->alignWideOpcode(); |
17795 | if (Fits<unsigned, size>::check(opcodeID) |
17796 | && Fits<VirtualRegister, size>::check(lhs) |
17797 | && Fits<VirtualRegister, size>::check(rhs) |
17798 | && Fits<BoundLabel, size>::check(targetLabel) |
17799 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
17800 | if (recordOpcode) |
17801 | gen->recordOpcode(opcodeID); |
17802 | if (size == OpcodeSize::Wide) |
17803 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
17804 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
17805 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
17806 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
17807 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
17808 | return true; |
17809 | } |
17810 | return false; |
17811 | } |
17812 | |
17813 | public: |
17814 | template<typename Block> |
17815 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
17816 | { |
17817 | dumper->printLocationAndOp(__location, &"*jnless" [!__isWide]); |
17818 | dumper->dumpOperand(m_lhs, true); |
17819 | dumper->dumpOperand(m_rhs, false); |
17820 | dumper->dumpOperand(m_targetLabel, false); |
17821 | } |
17822 | |
17823 | OpJnless(const uint8_t* stream) |
17824 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
17825 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
17826 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
17827 | { |
17828 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17829 | } |
17830 | |
17831 | OpJnless(const uint32_t* stream) |
17832 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
17833 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
17834 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
17835 | { |
17836 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17837 | } |
17838 | |
17839 | static OpJnless decode(const uint8_t* stream) |
17840 | { |
17841 | if (*stream != op_wide) |
17842 | return { stream }; |
17843 | |
17844 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
17845 | return { wideStream }; |
17846 | } |
17847 | |
17848 | template<typename Functor> |
17849 | void setLhs(VirtualRegister value, Functor func) |
17850 | { |
17851 | if (isWide()) |
17852 | setLhs<OpcodeSize::Wide>(value, func); |
17853 | else |
17854 | setLhs<OpcodeSize::Narrow>(value, func); |
17855 | } |
17856 | |
17857 | template <OpcodeSize size, typename Functor> |
17858 | void setLhs(VirtualRegister value, Functor func) |
17859 | { |
17860 | if (!Fits<VirtualRegister, size>::check(value)) |
17861 | value = func(); |
17862 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
17863 | *stream = Fits<VirtualRegister, size>::convert(value); |
17864 | } |
17865 | |
17866 | template<typename Functor> |
17867 | void setRhs(VirtualRegister value, Functor func) |
17868 | { |
17869 | if (isWide()) |
17870 | setRhs<OpcodeSize::Wide>(value, func); |
17871 | else |
17872 | setRhs<OpcodeSize::Narrow>(value, func); |
17873 | } |
17874 | |
17875 | template <OpcodeSize size, typename Functor> |
17876 | void setRhs(VirtualRegister value, Functor func) |
17877 | { |
17878 | if (!Fits<VirtualRegister, size>::check(value)) |
17879 | value = func(); |
17880 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
17881 | *stream = Fits<VirtualRegister, size>::convert(value); |
17882 | } |
17883 | |
17884 | template<typename Functor> |
17885 | void setTargetLabel(BoundLabel value, Functor func) |
17886 | { |
17887 | if (isWide()) |
17888 | setTargetLabel<OpcodeSize::Wide>(value, func); |
17889 | else |
17890 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
17891 | } |
17892 | |
17893 | template <OpcodeSize size, typename Functor> |
17894 | void setTargetLabel(BoundLabel value, Functor func) |
17895 | { |
17896 | if (!Fits<BoundLabel, size>::check(value)) |
17897 | value = func(); |
17898 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
17899 | *stream = Fits<BoundLabel, size>::convert(value); |
17900 | } |
17901 | |
17902 | VirtualRegister m_lhs; |
17903 | VirtualRegister m_rhs; |
17904 | BoundLabel m_targetLabel; |
17905 | }; |
17906 | |
17907 | struct OpJnlesseq : public Instruction { |
17908 | static constexpr OpcodeID opcodeID = op_jnlesseq; |
17909 | |
17910 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17911 | { |
17912 | |
17913 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
17914 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
17915 | } |
17916 | |
17917 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
17918 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17919 | { |
17920 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
17921 | if (shouldAssert == Assert) |
17922 | ASSERT(didEmit); |
17923 | return didEmit; |
17924 | } |
17925 | |
17926 | private: |
17927 | template<OpcodeSize size, bool recordOpcode> |
17928 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
17929 | { |
17930 | if (size == OpcodeSize::Wide) |
17931 | gen->alignWideOpcode(); |
17932 | if (Fits<unsigned, size>::check(opcodeID) |
17933 | && Fits<VirtualRegister, size>::check(lhs) |
17934 | && Fits<VirtualRegister, size>::check(rhs) |
17935 | && Fits<BoundLabel, size>::check(targetLabel) |
17936 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
17937 | if (recordOpcode) |
17938 | gen->recordOpcode(opcodeID); |
17939 | if (size == OpcodeSize::Wide) |
17940 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
17941 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
17942 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
17943 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
17944 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
17945 | return true; |
17946 | } |
17947 | return false; |
17948 | } |
17949 | |
17950 | public: |
17951 | template<typename Block> |
17952 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
17953 | { |
17954 | dumper->printLocationAndOp(__location, &"*jnlesseq" [!__isWide]); |
17955 | dumper->dumpOperand(m_lhs, true); |
17956 | dumper->dumpOperand(m_rhs, false); |
17957 | dumper->dumpOperand(m_targetLabel, false); |
17958 | } |
17959 | |
17960 | OpJnlesseq(const uint8_t* stream) |
17961 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
17962 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
17963 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
17964 | { |
17965 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17966 | } |
17967 | |
17968 | OpJnlesseq(const uint32_t* stream) |
17969 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
17970 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
17971 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
17972 | { |
17973 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
17974 | } |
17975 | |
17976 | static OpJnlesseq decode(const uint8_t* stream) |
17977 | { |
17978 | if (*stream != op_wide) |
17979 | return { stream }; |
17980 | |
17981 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
17982 | return { wideStream }; |
17983 | } |
17984 | |
17985 | template<typename Functor> |
17986 | void setLhs(VirtualRegister value, Functor func) |
17987 | { |
17988 | if (isWide()) |
17989 | setLhs<OpcodeSize::Wide>(value, func); |
17990 | else |
17991 | setLhs<OpcodeSize::Narrow>(value, func); |
17992 | } |
17993 | |
17994 | template <OpcodeSize size, typename Functor> |
17995 | void setLhs(VirtualRegister value, Functor func) |
17996 | { |
17997 | if (!Fits<VirtualRegister, size>::check(value)) |
17998 | value = func(); |
17999 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
18000 | *stream = Fits<VirtualRegister, size>::convert(value); |
18001 | } |
18002 | |
18003 | template<typename Functor> |
18004 | void setRhs(VirtualRegister value, Functor func) |
18005 | { |
18006 | if (isWide()) |
18007 | setRhs<OpcodeSize::Wide>(value, func); |
18008 | else |
18009 | setRhs<OpcodeSize::Narrow>(value, func); |
18010 | } |
18011 | |
18012 | template <OpcodeSize size, typename Functor> |
18013 | void setRhs(VirtualRegister value, Functor func) |
18014 | { |
18015 | if (!Fits<VirtualRegister, size>::check(value)) |
18016 | value = func(); |
18017 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
18018 | *stream = Fits<VirtualRegister, size>::convert(value); |
18019 | } |
18020 | |
18021 | template<typename Functor> |
18022 | void setTargetLabel(BoundLabel value, Functor func) |
18023 | { |
18024 | if (isWide()) |
18025 | setTargetLabel<OpcodeSize::Wide>(value, func); |
18026 | else |
18027 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
18028 | } |
18029 | |
18030 | template <OpcodeSize size, typename Functor> |
18031 | void setTargetLabel(BoundLabel value, Functor func) |
18032 | { |
18033 | if (!Fits<BoundLabel, size>::check(value)) |
18034 | value = func(); |
18035 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
18036 | *stream = Fits<BoundLabel, size>::convert(value); |
18037 | } |
18038 | |
18039 | VirtualRegister m_lhs; |
18040 | VirtualRegister m_rhs; |
18041 | BoundLabel m_targetLabel; |
18042 | }; |
18043 | |
18044 | struct OpJngreater : public Instruction { |
18045 | static constexpr OpcodeID opcodeID = op_jngreater; |
18046 | |
18047 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
18048 | { |
18049 | |
18050 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
18051 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
18052 | } |
18053 | |
18054 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
18055 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
18056 | { |
18057 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
18058 | if (shouldAssert == Assert) |
18059 | ASSERT(didEmit); |
18060 | return didEmit; |
18061 | } |
18062 | |
18063 | private: |
18064 | template<OpcodeSize size, bool recordOpcode> |
18065 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
18066 | { |
18067 | if (size == OpcodeSize::Wide) |
18068 | gen->alignWideOpcode(); |
18069 | if (Fits<unsigned, size>::check(opcodeID) |
18070 | && Fits<VirtualRegister, size>::check(lhs) |
18071 | && Fits<VirtualRegister, size>::check(rhs) |
18072 | && Fits<BoundLabel, size>::check(targetLabel) |
18073 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
18074 | if (recordOpcode) |
18075 | gen->recordOpcode(opcodeID); |
18076 | if (size == OpcodeSize::Wide) |
18077 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
18078 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
18079 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
18080 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
18081 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
18082 | return true; |
18083 | } |
18084 | return false; |
18085 | } |
18086 | |
18087 | public: |
18088 | template<typename Block> |
18089 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
18090 | { |
18091 | dumper->printLocationAndOp(__location, &"*jngreater" [!__isWide]); |
18092 | dumper->dumpOperand(m_lhs, true); |
18093 | dumper->dumpOperand(m_rhs, false); |
18094 | dumper->dumpOperand(m_targetLabel, false); |
18095 | } |
18096 | |
18097 | OpJngreater(const uint8_t* stream) |
18098 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
18099 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
18100 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
18101 | { |
18102 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18103 | } |
18104 | |
18105 | OpJngreater(const uint32_t* stream) |
18106 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
18107 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
18108 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
18109 | { |
18110 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18111 | } |
18112 | |
18113 | static OpJngreater decode(const uint8_t* stream) |
18114 | { |
18115 | if (*stream != op_wide) |
18116 | return { stream }; |
18117 | |
18118 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
18119 | return { wideStream }; |
18120 | } |
18121 | |
18122 | template<typename Functor> |
18123 | void setLhs(VirtualRegister value, Functor func) |
18124 | { |
18125 | if (isWide()) |
18126 | setLhs<OpcodeSize::Wide>(value, func); |
18127 | else |
18128 | setLhs<OpcodeSize::Narrow>(value, func); |
18129 | } |
18130 | |
18131 | template <OpcodeSize size, typename Functor> |
18132 | void setLhs(VirtualRegister value, Functor func) |
18133 | { |
18134 | if (!Fits<VirtualRegister, size>::check(value)) |
18135 | value = func(); |
18136 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
18137 | *stream = Fits<VirtualRegister, size>::convert(value); |
18138 | } |
18139 | |
18140 | template<typename Functor> |
18141 | void setRhs(VirtualRegister value, Functor func) |
18142 | { |
18143 | if (isWide()) |
18144 | setRhs<OpcodeSize::Wide>(value, func); |
18145 | else |
18146 | setRhs<OpcodeSize::Narrow>(value, func); |
18147 | } |
18148 | |
18149 | template <OpcodeSize size, typename Functor> |
18150 | void setRhs(VirtualRegister value, Functor func) |
18151 | { |
18152 | if (!Fits<VirtualRegister, size>::check(value)) |
18153 | value = func(); |
18154 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
18155 | *stream = Fits<VirtualRegister, size>::convert(value); |
18156 | } |
18157 | |
18158 | template<typename Functor> |
18159 | void setTargetLabel(BoundLabel value, Functor func) |
18160 | { |
18161 | if (isWide()) |
18162 | setTargetLabel<OpcodeSize::Wide>(value, func); |
18163 | else |
18164 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
18165 | } |
18166 | |
18167 | template <OpcodeSize size, typename Functor> |
18168 | void setTargetLabel(BoundLabel value, Functor func) |
18169 | { |
18170 | if (!Fits<BoundLabel, size>::check(value)) |
18171 | value = func(); |
18172 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
18173 | *stream = Fits<BoundLabel, size>::convert(value); |
18174 | } |
18175 | |
18176 | VirtualRegister m_lhs; |
18177 | VirtualRegister m_rhs; |
18178 | BoundLabel m_targetLabel; |
18179 | }; |
18180 | |
18181 | struct OpJngreatereq : public Instruction { |
18182 | static constexpr OpcodeID opcodeID = op_jngreatereq; |
18183 | |
18184 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
18185 | { |
18186 | |
18187 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
18188 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
18189 | } |
18190 | |
18191 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
18192 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
18193 | { |
18194 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
18195 | if (shouldAssert == Assert) |
18196 | ASSERT(didEmit); |
18197 | return didEmit; |
18198 | } |
18199 | |
18200 | private: |
18201 | template<OpcodeSize size, bool recordOpcode> |
18202 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
18203 | { |
18204 | if (size == OpcodeSize::Wide) |
18205 | gen->alignWideOpcode(); |
18206 | if (Fits<unsigned, size>::check(opcodeID) |
18207 | && Fits<VirtualRegister, size>::check(lhs) |
18208 | && Fits<VirtualRegister, size>::check(rhs) |
18209 | && Fits<BoundLabel, size>::check(targetLabel) |
18210 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
18211 | if (recordOpcode) |
18212 | gen->recordOpcode(opcodeID); |
18213 | if (size == OpcodeSize::Wide) |
18214 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
18215 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
18216 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
18217 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
18218 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
18219 | return true; |
18220 | } |
18221 | return false; |
18222 | } |
18223 | |
18224 | public: |
18225 | template<typename Block> |
18226 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
18227 | { |
18228 | dumper->printLocationAndOp(__location, &"*jngreatereq" [!__isWide]); |
18229 | dumper->dumpOperand(m_lhs, true); |
18230 | dumper->dumpOperand(m_rhs, false); |
18231 | dumper->dumpOperand(m_targetLabel, false); |
18232 | } |
18233 | |
18234 | OpJngreatereq(const uint8_t* stream) |
18235 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
18236 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
18237 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
18238 | { |
18239 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18240 | } |
18241 | |
18242 | OpJngreatereq(const uint32_t* stream) |
18243 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
18244 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
18245 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
18246 | { |
18247 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18248 | } |
18249 | |
18250 | static OpJngreatereq decode(const uint8_t* stream) |
18251 | { |
18252 | if (*stream != op_wide) |
18253 | return { stream }; |
18254 | |
18255 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
18256 | return { wideStream }; |
18257 | } |
18258 | |
18259 | template<typename Functor> |
18260 | void setLhs(VirtualRegister value, Functor func) |
18261 | { |
18262 | if (isWide()) |
18263 | setLhs<OpcodeSize::Wide>(value, func); |
18264 | else |
18265 | setLhs<OpcodeSize::Narrow>(value, func); |
18266 | } |
18267 | |
18268 | template <OpcodeSize size, typename Functor> |
18269 | void setLhs(VirtualRegister value, Functor func) |
18270 | { |
18271 | if (!Fits<VirtualRegister, size>::check(value)) |
18272 | value = func(); |
18273 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
18274 | *stream = Fits<VirtualRegister, size>::convert(value); |
18275 | } |
18276 | |
18277 | template<typename Functor> |
18278 | void setRhs(VirtualRegister value, Functor func) |
18279 | { |
18280 | if (isWide()) |
18281 | setRhs<OpcodeSize::Wide>(value, func); |
18282 | else |
18283 | setRhs<OpcodeSize::Narrow>(value, func); |
18284 | } |
18285 | |
18286 | template <OpcodeSize size, typename Functor> |
18287 | void setRhs(VirtualRegister value, Functor func) |
18288 | { |
18289 | if (!Fits<VirtualRegister, size>::check(value)) |
18290 | value = func(); |
18291 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
18292 | *stream = Fits<VirtualRegister, size>::convert(value); |
18293 | } |
18294 | |
18295 | template<typename Functor> |
18296 | void setTargetLabel(BoundLabel value, Functor func) |
18297 | { |
18298 | if (isWide()) |
18299 | setTargetLabel<OpcodeSize::Wide>(value, func); |
18300 | else |
18301 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
18302 | } |
18303 | |
18304 | template <OpcodeSize size, typename Functor> |
18305 | void setTargetLabel(BoundLabel value, Functor func) |
18306 | { |
18307 | if (!Fits<BoundLabel, size>::check(value)) |
18308 | value = func(); |
18309 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
18310 | *stream = Fits<BoundLabel, size>::convert(value); |
18311 | } |
18312 | |
18313 | VirtualRegister m_lhs; |
18314 | VirtualRegister m_rhs; |
18315 | BoundLabel m_targetLabel; |
18316 | }; |
18317 | |
18318 | struct OpJbelow : public Instruction { |
18319 | static constexpr OpcodeID opcodeID = op_jbelow; |
18320 | |
18321 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
18322 | { |
18323 | |
18324 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
18325 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
18326 | } |
18327 | |
18328 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
18329 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
18330 | { |
18331 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
18332 | if (shouldAssert == Assert) |
18333 | ASSERT(didEmit); |
18334 | return didEmit; |
18335 | } |
18336 | |
18337 | private: |
18338 | template<OpcodeSize size, bool recordOpcode> |
18339 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
18340 | { |
18341 | if (size == OpcodeSize::Wide) |
18342 | gen->alignWideOpcode(); |
18343 | if (Fits<unsigned, size>::check(opcodeID) |
18344 | && Fits<VirtualRegister, size>::check(lhs) |
18345 | && Fits<VirtualRegister, size>::check(rhs) |
18346 | && Fits<BoundLabel, size>::check(targetLabel) |
18347 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
18348 | if (recordOpcode) |
18349 | gen->recordOpcode(opcodeID); |
18350 | if (size == OpcodeSize::Wide) |
18351 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
18352 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
18353 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
18354 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
18355 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
18356 | return true; |
18357 | } |
18358 | return false; |
18359 | } |
18360 | |
18361 | public: |
18362 | template<typename Block> |
18363 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
18364 | { |
18365 | dumper->printLocationAndOp(__location, &"*jbelow" [!__isWide]); |
18366 | dumper->dumpOperand(m_lhs, true); |
18367 | dumper->dumpOperand(m_rhs, false); |
18368 | dumper->dumpOperand(m_targetLabel, false); |
18369 | } |
18370 | |
18371 | OpJbelow(const uint8_t* stream) |
18372 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
18373 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
18374 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
18375 | { |
18376 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18377 | } |
18378 | |
18379 | OpJbelow(const uint32_t* stream) |
18380 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
18381 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
18382 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
18383 | { |
18384 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18385 | } |
18386 | |
18387 | static OpJbelow decode(const uint8_t* stream) |
18388 | { |
18389 | if (*stream != op_wide) |
18390 | return { stream }; |
18391 | |
18392 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
18393 | return { wideStream }; |
18394 | } |
18395 | |
18396 | template<typename Functor> |
18397 | void setLhs(VirtualRegister value, Functor func) |
18398 | { |
18399 | if (isWide()) |
18400 | setLhs<OpcodeSize::Wide>(value, func); |
18401 | else |
18402 | setLhs<OpcodeSize::Narrow>(value, func); |
18403 | } |
18404 | |
18405 | template <OpcodeSize size, typename Functor> |
18406 | void setLhs(VirtualRegister value, Functor func) |
18407 | { |
18408 | if (!Fits<VirtualRegister, size>::check(value)) |
18409 | value = func(); |
18410 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
18411 | *stream = Fits<VirtualRegister, size>::convert(value); |
18412 | } |
18413 | |
18414 | template<typename Functor> |
18415 | void setRhs(VirtualRegister value, Functor func) |
18416 | { |
18417 | if (isWide()) |
18418 | setRhs<OpcodeSize::Wide>(value, func); |
18419 | else |
18420 | setRhs<OpcodeSize::Narrow>(value, func); |
18421 | } |
18422 | |
18423 | template <OpcodeSize size, typename Functor> |
18424 | void setRhs(VirtualRegister value, Functor func) |
18425 | { |
18426 | if (!Fits<VirtualRegister, size>::check(value)) |
18427 | value = func(); |
18428 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
18429 | *stream = Fits<VirtualRegister, size>::convert(value); |
18430 | } |
18431 | |
18432 | template<typename Functor> |
18433 | void setTargetLabel(BoundLabel value, Functor func) |
18434 | { |
18435 | if (isWide()) |
18436 | setTargetLabel<OpcodeSize::Wide>(value, func); |
18437 | else |
18438 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
18439 | } |
18440 | |
18441 | template <OpcodeSize size, typename Functor> |
18442 | void setTargetLabel(BoundLabel value, Functor func) |
18443 | { |
18444 | if (!Fits<BoundLabel, size>::check(value)) |
18445 | value = func(); |
18446 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
18447 | *stream = Fits<BoundLabel, size>::convert(value); |
18448 | } |
18449 | |
18450 | VirtualRegister m_lhs; |
18451 | VirtualRegister m_rhs; |
18452 | BoundLabel m_targetLabel; |
18453 | }; |
18454 | |
18455 | struct OpJbeloweq : public Instruction { |
18456 | static constexpr OpcodeID opcodeID = op_jbeloweq; |
18457 | |
18458 | static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
18459 | { |
18460 | |
18461 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel) |
18462 | || emit<OpcodeSize::Wide, Assert, true>(gen, lhs, rhs, targetLabel); |
18463 | } |
18464 | |
18465 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
18466 | static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
18467 | { |
18468 | bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel); |
18469 | if (shouldAssert == Assert) |
18470 | ASSERT(didEmit); |
18471 | return didEmit; |
18472 | } |
18473 | |
18474 | private: |
18475 | template<OpcodeSize size, bool recordOpcode> |
18476 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel) |
18477 | { |
18478 | if (size == OpcodeSize::Wide) |
18479 | gen->alignWideOpcode(); |
18480 | if (Fits<unsigned, size>::check(opcodeID) |
18481 | && Fits<VirtualRegister, size>::check(lhs) |
18482 | && Fits<VirtualRegister, size>::check(rhs) |
18483 | && Fits<BoundLabel, size>::check(targetLabel) |
18484 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
18485 | if (recordOpcode) |
18486 | gen->recordOpcode(opcodeID); |
18487 | if (size == OpcodeSize::Wide) |
18488 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
18489 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
18490 | gen->write(Fits<VirtualRegister, size>::convert(lhs)); |
18491 | gen->write(Fits<VirtualRegister, size>::convert(rhs)); |
18492 | gen->write(Fits<BoundLabel, size>::convert(targetLabel)); |
18493 | return true; |
18494 | } |
18495 | return false; |
18496 | } |
18497 | |
18498 | public: |
18499 | template<typename Block> |
18500 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
18501 | { |
18502 | dumper->printLocationAndOp(__location, &"*jbeloweq" [!__isWide]); |
18503 | dumper->dumpOperand(m_lhs, true); |
18504 | dumper->dumpOperand(m_rhs, false); |
18505 | dumper->dumpOperand(m_targetLabel, false); |
18506 | } |
18507 | |
18508 | OpJbeloweq(const uint8_t* stream) |
18509 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
18510 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
18511 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3])) |
18512 | { |
18513 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18514 | } |
18515 | |
18516 | OpJbeloweq(const uint32_t* stream) |
18517 | : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
18518 | , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
18519 | , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[3])) |
18520 | { |
18521 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18522 | } |
18523 | |
18524 | static OpJbeloweq decode(const uint8_t* stream) |
18525 | { |
18526 | if (*stream != op_wide) |
18527 | return { stream }; |
18528 | |
18529 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
18530 | return { wideStream }; |
18531 | } |
18532 | |
18533 | template<typename Functor> |
18534 | void setLhs(VirtualRegister value, Functor func) |
18535 | { |
18536 | if (isWide()) |
18537 | setLhs<OpcodeSize::Wide>(value, func); |
18538 | else |
18539 | setLhs<OpcodeSize::Narrow>(value, func); |
18540 | } |
18541 | |
18542 | template <OpcodeSize size, typename Functor> |
18543 | void setLhs(VirtualRegister value, Functor func) |
18544 | { |
18545 | if (!Fits<VirtualRegister, size>::check(value)) |
18546 | value = func(); |
18547 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
18548 | *stream = Fits<VirtualRegister, size>::convert(value); |
18549 | } |
18550 | |
18551 | template<typename Functor> |
18552 | void setRhs(VirtualRegister value, Functor func) |
18553 | { |
18554 | if (isWide()) |
18555 | setRhs<OpcodeSize::Wide>(value, func); |
18556 | else |
18557 | setRhs<OpcodeSize::Narrow>(value, func); |
18558 | } |
18559 | |
18560 | template <OpcodeSize size, typename Functor> |
18561 | void setRhs(VirtualRegister value, Functor func) |
18562 | { |
18563 | if (!Fits<VirtualRegister, size>::check(value)) |
18564 | value = func(); |
18565 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
18566 | *stream = Fits<VirtualRegister, size>::convert(value); |
18567 | } |
18568 | |
18569 | template<typename Functor> |
18570 | void setTargetLabel(BoundLabel value, Functor func) |
18571 | { |
18572 | if (isWide()) |
18573 | setTargetLabel<OpcodeSize::Wide>(value, func); |
18574 | else |
18575 | setTargetLabel<OpcodeSize::Narrow>(value, func); |
18576 | } |
18577 | |
18578 | template <OpcodeSize size, typename Functor> |
18579 | void setTargetLabel(BoundLabel value, Functor func) |
18580 | { |
18581 | if (!Fits<BoundLabel, size>::check(value)) |
18582 | value = func(); |
18583 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
18584 | *stream = Fits<BoundLabel, size>::convert(value); |
18585 | } |
18586 | |
18587 | VirtualRegister m_lhs; |
18588 | VirtualRegister m_rhs; |
18589 | BoundLabel m_targetLabel; |
18590 | }; |
18591 | |
18592 | struct OpLoopHint : public Instruction { |
18593 | static constexpr OpcodeID opcodeID = op_loop_hint; |
18594 | |
18595 | static void emit(BytecodeGenerator* gen) |
18596 | { |
18597 | |
18598 | emit<OpcodeSize::Narrow, NoAssert, true>(gen) |
18599 | || emit<OpcodeSize::Wide, Assert, true>(gen); |
18600 | } |
18601 | |
18602 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
18603 | static bool emit(BytecodeGenerator* gen) |
18604 | { |
18605 | bool didEmit = emitImpl<size, recordOpcode>(gen); |
18606 | if (shouldAssert == Assert) |
18607 | ASSERT(didEmit); |
18608 | return didEmit; |
18609 | } |
18610 | |
18611 | private: |
18612 | template<OpcodeSize size, bool recordOpcode> |
18613 | static bool emitImpl(BytecodeGenerator* gen) |
18614 | { |
18615 | if (size == OpcodeSize::Wide) |
18616 | gen->alignWideOpcode(); |
18617 | if (Fits<unsigned, size>::check(opcodeID) |
18618 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
18619 | if (recordOpcode) |
18620 | gen->recordOpcode(opcodeID); |
18621 | if (size == OpcodeSize::Wide) |
18622 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
18623 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
18624 | return true; |
18625 | } |
18626 | return false; |
18627 | } |
18628 | |
18629 | public: |
18630 | template<typename Block> |
18631 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
18632 | { |
18633 | dumper->printLocationAndOp(__location, &"*loop_hint" [!__isWide]); |
18634 | |
18635 | } |
18636 | |
18637 | OpLoopHint(const uint8_t* stream) |
18638 | |
18639 | { |
18640 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18641 | } |
18642 | |
18643 | OpLoopHint(const uint32_t* stream) |
18644 | |
18645 | { |
18646 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18647 | } |
18648 | |
18649 | static OpLoopHint decode(const uint8_t* stream) |
18650 | { |
18651 | if (*stream != op_wide) |
18652 | return { stream }; |
18653 | |
18654 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
18655 | return { wideStream }; |
18656 | } |
18657 | |
18658 | |
18659 | |
18660 | }; |
18661 | |
18662 | struct OpSwitchImm : public Instruction { |
18663 | static constexpr OpcodeID opcodeID = op_switch_imm; |
18664 | |
18665 | static void emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee) |
18666 | { |
18667 | |
18668 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee) |
18669 | || emit<OpcodeSize::Wide, Assert, true>(gen, tableIndex, defaultOffset, scrutinee); |
18670 | } |
18671 | |
18672 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
18673 | static bool emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee) |
18674 | { |
18675 | bool didEmit = emitImpl<size, recordOpcode>(gen, tableIndex, defaultOffset, scrutinee); |
18676 | if (shouldAssert == Assert) |
18677 | ASSERT(didEmit); |
18678 | return didEmit; |
18679 | } |
18680 | |
18681 | private: |
18682 | template<OpcodeSize size, bool recordOpcode> |
18683 | static bool emitImpl(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee) |
18684 | { |
18685 | if (size == OpcodeSize::Wide) |
18686 | gen->alignWideOpcode(); |
18687 | if (Fits<unsigned, size>::check(opcodeID) |
18688 | && Fits<unsigned, size>::check(tableIndex) |
18689 | && Fits<BoundLabel, size>::check(defaultOffset) |
18690 | && Fits<VirtualRegister, size>::check(scrutinee) |
18691 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
18692 | if (recordOpcode) |
18693 | gen->recordOpcode(opcodeID); |
18694 | if (size == OpcodeSize::Wide) |
18695 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
18696 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
18697 | gen->write(Fits<unsigned, size>::convert(tableIndex)); |
18698 | gen->write(Fits<BoundLabel, size>::convert(defaultOffset)); |
18699 | gen->write(Fits<VirtualRegister, size>::convert(scrutinee)); |
18700 | return true; |
18701 | } |
18702 | return false; |
18703 | } |
18704 | |
18705 | public: |
18706 | template<typename Block> |
18707 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
18708 | { |
18709 | dumper->printLocationAndOp(__location, &"*switch_imm" [!__isWide]); |
18710 | dumper->dumpOperand(m_tableIndex, true); |
18711 | dumper->dumpOperand(m_defaultOffset, false); |
18712 | dumper->dumpOperand(m_scrutinee, false); |
18713 | } |
18714 | |
18715 | OpSwitchImm(const uint8_t* stream) |
18716 | : m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1])) |
18717 | , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2])) |
18718 | , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
18719 | { |
18720 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18721 | } |
18722 | |
18723 | OpSwitchImm(const uint32_t* stream) |
18724 | : m_tableIndex(Fits<unsigned, OpcodeSize::Wide>::convert(stream[1])) |
18725 | , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[2])) |
18726 | , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
18727 | { |
18728 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18729 | } |
18730 | |
18731 | static OpSwitchImm decode(const uint8_t* stream) |
18732 | { |
18733 | if (*stream != op_wide) |
18734 | return { stream }; |
18735 | |
18736 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
18737 | return { wideStream }; |
18738 | } |
18739 | |
18740 | template<typename Functor> |
18741 | void setTableIndex(unsigned value, Functor func) |
18742 | { |
18743 | if (isWide()) |
18744 | setTableIndex<OpcodeSize::Wide>(value, func); |
18745 | else |
18746 | setTableIndex<OpcodeSize::Narrow>(value, func); |
18747 | } |
18748 | |
18749 | template <OpcodeSize size, typename Functor> |
18750 | void setTableIndex(unsigned value, Functor func) |
18751 | { |
18752 | if (!Fits<unsigned, size>::check(value)) |
18753 | value = func(); |
18754 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
18755 | *stream = Fits<unsigned, size>::convert(value); |
18756 | } |
18757 | |
18758 | template<typename Functor> |
18759 | void setDefaultOffset(BoundLabel value, Functor func) |
18760 | { |
18761 | if (isWide()) |
18762 | setDefaultOffset<OpcodeSize::Wide>(value, func); |
18763 | else |
18764 | setDefaultOffset<OpcodeSize::Narrow>(value, func); |
18765 | } |
18766 | |
18767 | template <OpcodeSize size, typename Functor> |
18768 | void setDefaultOffset(BoundLabel value, Functor func) |
18769 | { |
18770 | if (!Fits<BoundLabel, size>::check(value)) |
18771 | value = func(); |
18772 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
18773 | *stream = Fits<BoundLabel, size>::convert(value); |
18774 | } |
18775 | |
18776 | template<typename Functor> |
18777 | void setScrutinee(VirtualRegister value, Functor func) |
18778 | { |
18779 | if (isWide()) |
18780 | setScrutinee<OpcodeSize::Wide>(value, func); |
18781 | else |
18782 | setScrutinee<OpcodeSize::Narrow>(value, func); |
18783 | } |
18784 | |
18785 | template <OpcodeSize size, typename Functor> |
18786 | void setScrutinee(VirtualRegister value, Functor func) |
18787 | { |
18788 | if (!Fits<VirtualRegister, size>::check(value)) |
18789 | value = func(); |
18790 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
18791 | *stream = Fits<VirtualRegister, size>::convert(value); |
18792 | } |
18793 | |
18794 | unsigned m_tableIndex; |
18795 | BoundLabel m_defaultOffset; |
18796 | VirtualRegister m_scrutinee; |
18797 | }; |
18798 | |
18799 | struct OpSwitchChar : public Instruction { |
18800 | static constexpr OpcodeID opcodeID = op_switch_char; |
18801 | |
18802 | static void emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee) |
18803 | { |
18804 | |
18805 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee) |
18806 | || emit<OpcodeSize::Wide, Assert, true>(gen, tableIndex, defaultOffset, scrutinee); |
18807 | } |
18808 | |
18809 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
18810 | static bool emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee) |
18811 | { |
18812 | bool didEmit = emitImpl<size, recordOpcode>(gen, tableIndex, defaultOffset, scrutinee); |
18813 | if (shouldAssert == Assert) |
18814 | ASSERT(didEmit); |
18815 | return didEmit; |
18816 | } |
18817 | |
18818 | private: |
18819 | template<OpcodeSize size, bool recordOpcode> |
18820 | static bool emitImpl(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee) |
18821 | { |
18822 | if (size == OpcodeSize::Wide) |
18823 | gen->alignWideOpcode(); |
18824 | if (Fits<unsigned, size>::check(opcodeID) |
18825 | && Fits<unsigned, size>::check(tableIndex) |
18826 | && Fits<BoundLabel, size>::check(defaultOffset) |
18827 | && Fits<VirtualRegister, size>::check(scrutinee) |
18828 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
18829 | if (recordOpcode) |
18830 | gen->recordOpcode(opcodeID); |
18831 | if (size == OpcodeSize::Wide) |
18832 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
18833 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
18834 | gen->write(Fits<unsigned, size>::convert(tableIndex)); |
18835 | gen->write(Fits<BoundLabel, size>::convert(defaultOffset)); |
18836 | gen->write(Fits<VirtualRegister, size>::convert(scrutinee)); |
18837 | return true; |
18838 | } |
18839 | return false; |
18840 | } |
18841 | |
18842 | public: |
18843 | template<typename Block> |
18844 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
18845 | { |
18846 | dumper->printLocationAndOp(__location, &"*switch_char" [!__isWide]); |
18847 | dumper->dumpOperand(m_tableIndex, true); |
18848 | dumper->dumpOperand(m_defaultOffset, false); |
18849 | dumper->dumpOperand(m_scrutinee, false); |
18850 | } |
18851 | |
18852 | OpSwitchChar(const uint8_t* stream) |
18853 | : m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1])) |
18854 | , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2])) |
18855 | , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
18856 | { |
18857 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18858 | } |
18859 | |
18860 | OpSwitchChar(const uint32_t* stream) |
18861 | : m_tableIndex(Fits<unsigned, OpcodeSize::Wide>::convert(stream[1])) |
18862 | , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[2])) |
18863 | , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
18864 | { |
18865 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18866 | } |
18867 | |
18868 | static OpSwitchChar decode(const uint8_t* stream) |
18869 | { |
18870 | if (*stream != op_wide) |
18871 | return { stream }; |
18872 | |
18873 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
18874 | return { wideStream }; |
18875 | } |
18876 | |
18877 | template<typename Functor> |
18878 | void setTableIndex(unsigned value, Functor func) |
18879 | { |
18880 | if (isWide()) |
18881 | setTableIndex<OpcodeSize::Wide>(value, func); |
18882 | else |
18883 | setTableIndex<OpcodeSize::Narrow>(value, func); |
18884 | } |
18885 | |
18886 | template <OpcodeSize size, typename Functor> |
18887 | void setTableIndex(unsigned value, Functor func) |
18888 | { |
18889 | if (!Fits<unsigned, size>::check(value)) |
18890 | value = func(); |
18891 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
18892 | *stream = Fits<unsigned, size>::convert(value); |
18893 | } |
18894 | |
18895 | template<typename Functor> |
18896 | void setDefaultOffset(BoundLabel value, Functor func) |
18897 | { |
18898 | if (isWide()) |
18899 | setDefaultOffset<OpcodeSize::Wide>(value, func); |
18900 | else |
18901 | setDefaultOffset<OpcodeSize::Narrow>(value, func); |
18902 | } |
18903 | |
18904 | template <OpcodeSize size, typename Functor> |
18905 | void setDefaultOffset(BoundLabel value, Functor func) |
18906 | { |
18907 | if (!Fits<BoundLabel, size>::check(value)) |
18908 | value = func(); |
18909 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
18910 | *stream = Fits<BoundLabel, size>::convert(value); |
18911 | } |
18912 | |
18913 | template<typename Functor> |
18914 | void setScrutinee(VirtualRegister value, Functor func) |
18915 | { |
18916 | if (isWide()) |
18917 | setScrutinee<OpcodeSize::Wide>(value, func); |
18918 | else |
18919 | setScrutinee<OpcodeSize::Narrow>(value, func); |
18920 | } |
18921 | |
18922 | template <OpcodeSize size, typename Functor> |
18923 | void setScrutinee(VirtualRegister value, Functor func) |
18924 | { |
18925 | if (!Fits<VirtualRegister, size>::check(value)) |
18926 | value = func(); |
18927 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
18928 | *stream = Fits<VirtualRegister, size>::convert(value); |
18929 | } |
18930 | |
18931 | unsigned m_tableIndex; |
18932 | BoundLabel m_defaultOffset; |
18933 | VirtualRegister m_scrutinee; |
18934 | }; |
18935 | |
18936 | struct OpSwitchString : public Instruction { |
18937 | static constexpr OpcodeID opcodeID = op_switch_string; |
18938 | |
18939 | static void emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee) |
18940 | { |
18941 | |
18942 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee) |
18943 | || emit<OpcodeSize::Wide, Assert, true>(gen, tableIndex, defaultOffset, scrutinee); |
18944 | } |
18945 | |
18946 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
18947 | static bool emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee) |
18948 | { |
18949 | bool didEmit = emitImpl<size, recordOpcode>(gen, tableIndex, defaultOffset, scrutinee); |
18950 | if (shouldAssert == Assert) |
18951 | ASSERT(didEmit); |
18952 | return didEmit; |
18953 | } |
18954 | |
18955 | private: |
18956 | template<OpcodeSize size, bool recordOpcode> |
18957 | static bool emitImpl(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee) |
18958 | { |
18959 | if (size == OpcodeSize::Wide) |
18960 | gen->alignWideOpcode(); |
18961 | if (Fits<unsigned, size>::check(opcodeID) |
18962 | && Fits<unsigned, size>::check(tableIndex) |
18963 | && Fits<BoundLabel, size>::check(defaultOffset) |
18964 | && Fits<VirtualRegister, size>::check(scrutinee) |
18965 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
18966 | if (recordOpcode) |
18967 | gen->recordOpcode(opcodeID); |
18968 | if (size == OpcodeSize::Wide) |
18969 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
18970 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
18971 | gen->write(Fits<unsigned, size>::convert(tableIndex)); |
18972 | gen->write(Fits<BoundLabel, size>::convert(defaultOffset)); |
18973 | gen->write(Fits<VirtualRegister, size>::convert(scrutinee)); |
18974 | return true; |
18975 | } |
18976 | return false; |
18977 | } |
18978 | |
18979 | public: |
18980 | template<typename Block> |
18981 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
18982 | { |
18983 | dumper->printLocationAndOp(__location, &"*switch_string" [!__isWide]); |
18984 | dumper->dumpOperand(m_tableIndex, true); |
18985 | dumper->dumpOperand(m_defaultOffset, false); |
18986 | dumper->dumpOperand(m_scrutinee, false); |
18987 | } |
18988 | |
18989 | OpSwitchString(const uint8_t* stream) |
18990 | : m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1])) |
18991 | , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2])) |
18992 | , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
18993 | { |
18994 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
18995 | } |
18996 | |
18997 | OpSwitchString(const uint32_t* stream) |
18998 | : m_tableIndex(Fits<unsigned, OpcodeSize::Wide>::convert(stream[1])) |
18999 | , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide>::convert(stream[2])) |
19000 | , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
19001 | { |
19002 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19003 | } |
19004 | |
19005 | static OpSwitchString decode(const uint8_t* stream) |
19006 | { |
19007 | if (*stream != op_wide) |
19008 | return { stream }; |
19009 | |
19010 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
19011 | return { wideStream }; |
19012 | } |
19013 | |
19014 | template<typename Functor> |
19015 | void setTableIndex(unsigned value, Functor func) |
19016 | { |
19017 | if (isWide()) |
19018 | setTableIndex<OpcodeSize::Wide>(value, func); |
19019 | else |
19020 | setTableIndex<OpcodeSize::Narrow>(value, func); |
19021 | } |
19022 | |
19023 | template <OpcodeSize size, typename Functor> |
19024 | void setTableIndex(unsigned value, Functor func) |
19025 | { |
19026 | if (!Fits<unsigned, size>::check(value)) |
19027 | value = func(); |
19028 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
19029 | *stream = Fits<unsigned, size>::convert(value); |
19030 | } |
19031 | |
19032 | template<typename Functor> |
19033 | void setDefaultOffset(BoundLabel value, Functor func) |
19034 | { |
19035 | if (isWide()) |
19036 | setDefaultOffset<OpcodeSize::Wide>(value, func); |
19037 | else |
19038 | setDefaultOffset<OpcodeSize::Narrow>(value, func); |
19039 | } |
19040 | |
19041 | template <OpcodeSize size, typename Functor> |
19042 | void setDefaultOffset(BoundLabel value, Functor func) |
19043 | { |
19044 | if (!Fits<BoundLabel, size>::check(value)) |
19045 | value = func(); |
19046 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
19047 | *stream = Fits<BoundLabel, size>::convert(value); |
19048 | } |
19049 | |
19050 | template<typename Functor> |
19051 | void setScrutinee(VirtualRegister value, Functor func) |
19052 | { |
19053 | if (isWide()) |
19054 | setScrutinee<OpcodeSize::Wide>(value, func); |
19055 | else |
19056 | setScrutinee<OpcodeSize::Narrow>(value, func); |
19057 | } |
19058 | |
19059 | template <OpcodeSize size, typename Functor> |
19060 | void setScrutinee(VirtualRegister value, Functor func) |
19061 | { |
19062 | if (!Fits<VirtualRegister, size>::check(value)) |
19063 | value = func(); |
19064 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
19065 | *stream = Fits<VirtualRegister, size>::convert(value); |
19066 | } |
19067 | |
19068 | unsigned m_tableIndex; |
19069 | BoundLabel m_defaultOffset; |
19070 | VirtualRegister m_scrutinee; |
19071 | }; |
19072 | |
19073 | struct OpNewFunc : public Instruction { |
19074 | static constexpr OpcodeID opcodeID = op_new_func; |
19075 | |
19076 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19077 | { |
19078 | |
19079 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl) |
19080 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope, functionDecl); |
19081 | } |
19082 | |
19083 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
19084 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19085 | { |
19086 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl); |
19087 | if (shouldAssert == Assert) |
19088 | ASSERT(didEmit); |
19089 | return didEmit; |
19090 | } |
19091 | |
19092 | private: |
19093 | template<OpcodeSize size, bool recordOpcode> |
19094 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19095 | { |
19096 | if (size == OpcodeSize::Wide) |
19097 | gen->alignWideOpcode(); |
19098 | if (Fits<unsigned, size>::check(opcodeID) |
19099 | && Fits<VirtualRegister, size>::check(dst) |
19100 | && Fits<VirtualRegister, size>::check(scope) |
19101 | && Fits<unsigned, size>::check(functionDecl) |
19102 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
19103 | if (recordOpcode) |
19104 | gen->recordOpcode(opcodeID); |
19105 | if (size == OpcodeSize::Wide) |
19106 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
19107 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
19108 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
19109 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
19110 | gen->write(Fits<unsigned, size>::convert(functionDecl)); |
19111 | return true; |
19112 | } |
19113 | return false; |
19114 | } |
19115 | |
19116 | public: |
19117 | template<typename Block> |
19118 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
19119 | { |
19120 | dumper->printLocationAndOp(__location, &"*new_func" [!__isWide]); |
19121 | dumper->dumpOperand(m_dst, true); |
19122 | dumper->dumpOperand(m_scope, false); |
19123 | dumper->dumpOperand(m_functionDecl, false); |
19124 | } |
19125 | |
19126 | OpNewFunc(const uint8_t* stream) |
19127 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
19128 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
19129 | , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
19130 | { |
19131 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19132 | } |
19133 | |
19134 | OpNewFunc(const uint32_t* stream) |
19135 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
19136 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
19137 | , m_functionDecl(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
19138 | { |
19139 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19140 | } |
19141 | |
19142 | static OpNewFunc decode(const uint8_t* stream) |
19143 | { |
19144 | if (*stream != op_wide) |
19145 | return { stream }; |
19146 | |
19147 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
19148 | return { wideStream }; |
19149 | } |
19150 | |
19151 | template<typename Functor> |
19152 | void setDst(VirtualRegister value, Functor func) |
19153 | { |
19154 | if (isWide()) |
19155 | setDst<OpcodeSize::Wide>(value, func); |
19156 | else |
19157 | setDst<OpcodeSize::Narrow>(value, func); |
19158 | } |
19159 | |
19160 | template <OpcodeSize size, typename Functor> |
19161 | void setDst(VirtualRegister value, Functor func) |
19162 | { |
19163 | if (!Fits<VirtualRegister, size>::check(value)) |
19164 | value = func(); |
19165 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
19166 | *stream = Fits<VirtualRegister, size>::convert(value); |
19167 | } |
19168 | |
19169 | template<typename Functor> |
19170 | void setScope(VirtualRegister value, Functor func) |
19171 | { |
19172 | if (isWide()) |
19173 | setScope<OpcodeSize::Wide>(value, func); |
19174 | else |
19175 | setScope<OpcodeSize::Narrow>(value, func); |
19176 | } |
19177 | |
19178 | template <OpcodeSize size, typename Functor> |
19179 | void setScope(VirtualRegister value, Functor func) |
19180 | { |
19181 | if (!Fits<VirtualRegister, size>::check(value)) |
19182 | value = func(); |
19183 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
19184 | *stream = Fits<VirtualRegister, size>::convert(value); |
19185 | } |
19186 | |
19187 | template<typename Functor> |
19188 | void setFunctionDecl(unsigned value, Functor func) |
19189 | { |
19190 | if (isWide()) |
19191 | setFunctionDecl<OpcodeSize::Wide>(value, func); |
19192 | else |
19193 | setFunctionDecl<OpcodeSize::Narrow>(value, func); |
19194 | } |
19195 | |
19196 | template <OpcodeSize size, typename Functor> |
19197 | void setFunctionDecl(unsigned value, Functor func) |
19198 | { |
19199 | if (!Fits<unsigned, size>::check(value)) |
19200 | value = func(); |
19201 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
19202 | *stream = Fits<unsigned, size>::convert(value); |
19203 | } |
19204 | |
19205 | VirtualRegister m_dst; |
19206 | VirtualRegister m_scope; |
19207 | unsigned m_functionDecl; |
19208 | }; |
19209 | |
19210 | struct OpNewFuncExp : public Instruction { |
19211 | static constexpr OpcodeID opcodeID = op_new_func_exp; |
19212 | |
19213 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19214 | { |
19215 | |
19216 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl) |
19217 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope, functionDecl); |
19218 | } |
19219 | |
19220 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
19221 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19222 | { |
19223 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl); |
19224 | if (shouldAssert == Assert) |
19225 | ASSERT(didEmit); |
19226 | return didEmit; |
19227 | } |
19228 | |
19229 | private: |
19230 | template<OpcodeSize size, bool recordOpcode> |
19231 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19232 | { |
19233 | if (size == OpcodeSize::Wide) |
19234 | gen->alignWideOpcode(); |
19235 | if (Fits<unsigned, size>::check(opcodeID) |
19236 | && Fits<VirtualRegister, size>::check(dst) |
19237 | && Fits<VirtualRegister, size>::check(scope) |
19238 | && Fits<unsigned, size>::check(functionDecl) |
19239 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
19240 | if (recordOpcode) |
19241 | gen->recordOpcode(opcodeID); |
19242 | if (size == OpcodeSize::Wide) |
19243 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
19244 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
19245 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
19246 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
19247 | gen->write(Fits<unsigned, size>::convert(functionDecl)); |
19248 | return true; |
19249 | } |
19250 | return false; |
19251 | } |
19252 | |
19253 | public: |
19254 | template<typename Block> |
19255 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
19256 | { |
19257 | dumper->printLocationAndOp(__location, &"*new_func_exp" [!__isWide]); |
19258 | dumper->dumpOperand(m_dst, true); |
19259 | dumper->dumpOperand(m_scope, false); |
19260 | dumper->dumpOperand(m_functionDecl, false); |
19261 | } |
19262 | |
19263 | OpNewFuncExp(const uint8_t* stream) |
19264 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
19265 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
19266 | , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
19267 | { |
19268 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19269 | } |
19270 | |
19271 | OpNewFuncExp(const uint32_t* stream) |
19272 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
19273 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
19274 | , m_functionDecl(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
19275 | { |
19276 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19277 | } |
19278 | |
19279 | static OpNewFuncExp decode(const uint8_t* stream) |
19280 | { |
19281 | if (*stream != op_wide) |
19282 | return { stream }; |
19283 | |
19284 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
19285 | return { wideStream }; |
19286 | } |
19287 | |
19288 | template<typename Functor> |
19289 | void setDst(VirtualRegister value, Functor func) |
19290 | { |
19291 | if (isWide()) |
19292 | setDst<OpcodeSize::Wide>(value, func); |
19293 | else |
19294 | setDst<OpcodeSize::Narrow>(value, func); |
19295 | } |
19296 | |
19297 | template <OpcodeSize size, typename Functor> |
19298 | void setDst(VirtualRegister value, Functor func) |
19299 | { |
19300 | if (!Fits<VirtualRegister, size>::check(value)) |
19301 | value = func(); |
19302 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
19303 | *stream = Fits<VirtualRegister, size>::convert(value); |
19304 | } |
19305 | |
19306 | template<typename Functor> |
19307 | void setScope(VirtualRegister value, Functor func) |
19308 | { |
19309 | if (isWide()) |
19310 | setScope<OpcodeSize::Wide>(value, func); |
19311 | else |
19312 | setScope<OpcodeSize::Narrow>(value, func); |
19313 | } |
19314 | |
19315 | template <OpcodeSize size, typename Functor> |
19316 | void setScope(VirtualRegister value, Functor func) |
19317 | { |
19318 | if (!Fits<VirtualRegister, size>::check(value)) |
19319 | value = func(); |
19320 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
19321 | *stream = Fits<VirtualRegister, size>::convert(value); |
19322 | } |
19323 | |
19324 | template<typename Functor> |
19325 | void setFunctionDecl(unsigned value, Functor func) |
19326 | { |
19327 | if (isWide()) |
19328 | setFunctionDecl<OpcodeSize::Wide>(value, func); |
19329 | else |
19330 | setFunctionDecl<OpcodeSize::Narrow>(value, func); |
19331 | } |
19332 | |
19333 | template <OpcodeSize size, typename Functor> |
19334 | void setFunctionDecl(unsigned value, Functor func) |
19335 | { |
19336 | if (!Fits<unsigned, size>::check(value)) |
19337 | value = func(); |
19338 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
19339 | *stream = Fits<unsigned, size>::convert(value); |
19340 | } |
19341 | |
19342 | VirtualRegister m_dst; |
19343 | VirtualRegister m_scope; |
19344 | unsigned m_functionDecl; |
19345 | }; |
19346 | |
19347 | struct OpNewGeneratorFunc : public Instruction { |
19348 | static constexpr OpcodeID opcodeID = op_new_generator_func; |
19349 | |
19350 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19351 | { |
19352 | |
19353 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl) |
19354 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope, functionDecl); |
19355 | } |
19356 | |
19357 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
19358 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19359 | { |
19360 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl); |
19361 | if (shouldAssert == Assert) |
19362 | ASSERT(didEmit); |
19363 | return didEmit; |
19364 | } |
19365 | |
19366 | private: |
19367 | template<OpcodeSize size, bool recordOpcode> |
19368 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19369 | { |
19370 | if (size == OpcodeSize::Wide) |
19371 | gen->alignWideOpcode(); |
19372 | if (Fits<unsigned, size>::check(opcodeID) |
19373 | && Fits<VirtualRegister, size>::check(dst) |
19374 | && Fits<VirtualRegister, size>::check(scope) |
19375 | && Fits<unsigned, size>::check(functionDecl) |
19376 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
19377 | if (recordOpcode) |
19378 | gen->recordOpcode(opcodeID); |
19379 | if (size == OpcodeSize::Wide) |
19380 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
19381 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
19382 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
19383 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
19384 | gen->write(Fits<unsigned, size>::convert(functionDecl)); |
19385 | return true; |
19386 | } |
19387 | return false; |
19388 | } |
19389 | |
19390 | public: |
19391 | template<typename Block> |
19392 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
19393 | { |
19394 | dumper->printLocationAndOp(__location, &"*new_generator_func" [!__isWide]); |
19395 | dumper->dumpOperand(m_dst, true); |
19396 | dumper->dumpOperand(m_scope, false); |
19397 | dumper->dumpOperand(m_functionDecl, false); |
19398 | } |
19399 | |
19400 | OpNewGeneratorFunc(const uint8_t* stream) |
19401 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
19402 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
19403 | , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
19404 | { |
19405 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19406 | } |
19407 | |
19408 | OpNewGeneratorFunc(const uint32_t* stream) |
19409 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
19410 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
19411 | , m_functionDecl(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
19412 | { |
19413 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19414 | } |
19415 | |
19416 | static OpNewGeneratorFunc decode(const uint8_t* stream) |
19417 | { |
19418 | if (*stream != op_wide) |
19419 | return { stream }; |
19420 | |
19421 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
19422 | return { wideStream }; |
19423 | } |
19424 | |
19425 | template<typename Functor> |
19426 | void setDst(VirtualRegister value, Functor func) |
19427 | { |
19428 | if (isWide()) |
19429 | setDst<OpcodeSize::Wide>(value, func); |
19430 | else |
19431 | setDst<OpcodeSize::Narrow>(value, func); |
19432 | } |
19433 | |
19434 | template <OpcodeSize size, typename Functor> |
19435 | void setDst(VirtualRegister value, Functor func) |
19436 | { |
19437 | if (!Fits<VirtualRegister, size>::check(value)) |
19438 | value = func(); |
19439 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
19440 | *stream = Fits<VirtualRegister, size>::convert(value); |
19441 | } |
19442 | |
19443 | template<typename Functor> |
19444 | void setScope(VirtualRegister value, Functor func) |
19445 | { |
19446 | if (isWide()) |
19447 | setScope<OpcodeSize::Wide>(value, func); |
19448 | else |
19449 | setScope<OpcodeSize::Narrow>(value, func); |
19450 | } |
19451 | |
19452 | template <OpcodeSize size, typename Functor> |
19453 | void setScope(VirtualRegister value, Functor func) |
19454 | { |
19455 | if (!Fits<VirtualRegister, size>::check(value)) |
19456 | value = func(); |
19457 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
19458 | *stream = Fits<VirtualRegister, size>::convert(value); |
19459 | } |
19460 | |
19461 | template<typename Functor> |
19462 | void setFunctionDecl(unsigned value, Functor func) |
19463 | { |
19464 | if (isWide()) |
19465 | setFunctionDecl<OpcodeSize::Wide>(value, func); |
19466 | else |
19467 | setFunctionDecl<OpcodeSize::Narrow>(value, func); |
19468 | } |
19469 | |
19470 | template <OpcodeSize size, typename Functor> |
19471 | void setFunctionDecl(unsigned value, Functor func) |
19472 | { |
19473 | if (!Fits<unsigned, size>::check(value)) |
19474 | value = func(); |
19475 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
19476 | *stream = Fits<unsigned, size>::convert(value); |
19477 | } |
19478 | |
19479 | VirtualRegister m_dst; |
19480 | VirtualRegister m_scope; |
19481 | unsigned m_functionDecl; |
19482 | }; |
19483 | |
19484 | struct OpNewGeneratorFuncExp : public Instruction { |
19485 | static constexpr OpcodeID opcodeID = op_new_generator_func_exp; |
19486 | |
19487 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19488 | { |
19489 | |
19490 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl) |
19491 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope, functionDecl); |
19492 | } |
19493 | |
19494 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
19495 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19496 | { |
19497 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl); |
19498 | if (shouldAssert == Assert) |
19499 | ASSERT(didEmit); |
19500 | return didEmit; |
19501 | } |
19502 | |
19503 | private: |
19504 | template<OpcodeSize size, bool recordOpcode> |
19505 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19506 | { |
19507 | if (size == OpcodeSize::Wide) |
19508 | gen->alignWideOpcode(); |
19509 | if (Fits<unsigned, size>::check(opcodeID) |
19510 | && Fits<VirtualRegister, size>::check(dst) |
19511 | && Fits<VirtualRegister, size>::check(scope) |
19512 | && Fits<unsigned, size>::check(functionDecl) |
19513 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
19514 | if (recordOpcode) |
19515 | gen->recordOpcode(opcodeID); |
19516 | if (size == OpcodeSize::Wide) |
19517 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
19518 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
19519 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
19520 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
19521 | gen->write(Fits<unsigned, size>::convert(functionDecl)); |
19522 | return true; |
19523 | } |
19524 | return false; |
19525 | } |
19526 | |
19527 | public: |
19528 | template<typename Block> |
19529 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
19530 | { |
19531 | dumper->printLocationAndOp(__location, &"*new_generator_func_exp" [!__isWide]); |
19532 | dumper->dumpOperand(m_dst, true); |
19533 | dumper->dumpOperand(m_scope, false); |
19534 | dumper->dumpOperand(m_functionDecl, false); |
19535 | } |
19536 | |
19537 | OpNewGeneratorFuncExp(const uint8_t* stream) |
19538 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
19539 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
19540 | , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
19541 | { |
19542 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19543 | } |
19544 | |
19545 | OpNewGeneratorFuncExp(const uint32_t* stream) |
19546 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
19547 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
19548 | , m_functionDecl(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
19549 | { |
19550 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19551 | } |
19552 | |
19553 | static OpNewGeneratorFuncExp decode(const uint8_t* stream) |
19554 | { |
19555 | if (*stream != op_wide) |
19556 | return { stream }; |
19557 | |
19558 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
19559 | return { wideStream }; |
19560 | } |
19561 | |
19562 | template<typename Functor> |
19563 | void setDst(VirtualRegister value, Functor func) |
19564 | { |
19565 | if (isWide()) |
19566 | setDst<OpcodeSize::Wide>(value, func); |
19567 | else |
19568 | setDst<OpcodeSize::Narrow>(value, func); |
19569 | } |
19570 | |
19571 | template <OpcodeSize size, typename Functor> |
19572 | void setDst(VirtualRegister value, Functor func) |
19573 | { |
19574 | if (!Fits<VirtualRegister, size>::check(value)) |
19575 | value = func(); |
19576 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
19577 | *stream = Fits<VirtualRegister, size>::convert(value); |
19578 | } |
19579 | |
19580 | template<typename Functor> |
19581 | void setScope(VirtualRegister value, Functor func) |
19582 | { |
19583 | if (isWide()) |
19584 | setScope<OpcodeSize::Wide>(value, func); |
19585 | else |
19586 | setScope<OpcodeSize::Narrow>(value, func); |
19587 | } |
19588 | |
19589 | template <OpcodeSize size, typename Functor> |
19590 | void setScope(VirtualRegister value, Functor func) |
19591 | { |
19592 | if (!Fits<VirtualRegister, size>::check(value)) |
19593 | value = func(); |
19594 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
19595 | *stream = Fits<VirtualRegister, size>::convert(value); |
19596 | } |
19597 | |
19598 | template<typename Functor> |
19599 | void setFunctionDecl(unsigned value, Functor func) |
19600 | { |
19601 | if (isWide()) |
19602 | setFunctionDecl<OpcodeSize::Wide>(value, func); |
19603 | else |
19604 | setFunctionDecl<OpcodeSize::Narrow>(value, func); |
19605 | } |
19606 | |
19607 | template <OpcodeSize size, typename Functor> |
19608 | void setFunctionDecl(unsigned value, Functor func) |
19609 | { |
19610 | if (!Fits<unsigned, size>::check(value)) |
19611 | value = func(); |
19612 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
19613 | *stream = Fits<unsigned, size>::convert(value); |
19614 | } |
19615 | |
19616 | VirtualRegister m_dst; |
19617 | VirtualRegister m_scope; |
19618 | unsigned m_functionDecl; |
19619 | }; |
19620 | |
19621 | struct OpNewAsyncFunc : public Instruction { |
19622 | static constexpr OpcodeID opcodeID = op_new_async_func; |
19623 | |
19624 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19625 | { |
19626 | |
19627 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl) |
19628 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope, functionDecl); |
19629 | } |
19630 | |
19631 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
19632 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19633 | { |
19634 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl); |
19635 | if (shouldAssert == Assert) |
19636 | ASSERT(didEmit); |
19637 | return didEmit; |
19638 | } |
19639 | |
19640 | private: |
19641 | template<OpcodeSize size, bool recordOpcode> |
19642 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19643 | { |
19644 | if (size == OpcodeSize::Wide) |
19645 | gen->alignWideOpcode(); |
19646 | if (Fits<unsigned, size>::check(opcodeID) |
19647 | && Fits<VirtualRegister, size>::check(dst) |
19648 | && Fits<VirtualRegister, size>::check(scope) |
19649 | && Fits<unsigned, size>::check(functionDecl) |
19650 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
19651 | if (recordOpcode) |
19652 | gen->recordOpcode(opcodeID); |
19653 | if (size == OpcodeSize::Wide) |
19654 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
19655 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
19656 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
19657 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
19658 | gen->write(Fits<unsigned, size>::convert(functionDecl)); |
19659 | return true; |
19660 | } |
19661 | return false; |
19662 | } |
19663 | |
19664 | public: |
19665 | template<typename Block> |
19666 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
19667 | { |
19668 | dumper->printLocationAndOp(__location, &"*new_async_func" [!__isWide]); |
19669 | dumper->dumpOperand(m_dst, true); |
19670 | dumper->dumpOperand(m_scope, false); |
19671 | dumper->dumpOperand(m_functionDecl, false); |
19672 | } |
19673 | |
19674 | OpNewAsyncFunc(const uint8_t* stream) |
19675 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
19676 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
19677 | , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
19678 | { |
19679 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19680 | } |
19681 | |
19682 | OpNewAsyncFunc(const uint32_t* stream) |
19683 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
19684 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
19685 | , m_functionDecl(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
19686 | { |
19687 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19688 | } |
19689 | |
19690 | static OpNewAsyncFunc decode(const uint8_t* stream) |
19691 | { |
19692 | if (*stream != op_wide) |
19693 | return { stream }; |
19694 | |
19695 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
19696 | return { wideStream }; |
19697 | } |
19698 | |
19699 | template<typename Functor> |
19700 | void setDst(VirtualRegister value, Functor func) |
19701 | { |
19702 | if (isWide()) |
19703 | setDst<OpcodeSize::Wide>(value, func); |
19704 | else |
19705 | setDst<OpcodeSize::Narrow>(value, func); |
19706 | } |
19707 | |
19708 | template <OpcodeSize size, typename Functor> |
19709 | void setDst(VirtualRegister value, Functor func) |
19710 | { |
19711 | if (!Fits<VirtualRegister, size>::check(value)) |
19712 | value = func(); |
19713 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
19714 | *stream = Fits<VirtualRegister, size>::convert(value); |
19715 | } |
19716 | |
19717 | template<typename Functor> |
19718 | void setScope(VirtualRegister value, Functor func) |
19719 | { |
19720 | if (isWide()) |
19721 | setScope<OpcodeSize::Wide>(value, func); |
19722 | else |
19723 | setScope<OpcodeSize::Narrow>(value, func); |
19724 | } |
19725 | |
19726 | template <OpcodeSize size, typename Functor> |
19727 | void setScope(VirtualRegister value, Functor func) |
19728 | { |
19729 | if (!Fits<VirtualRegister, size>::check(value)) |
19730 | value = func(); |
19731 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
19732 | *stream = Fits<VirtualRegister, size>::convert(value); |
19733 | } |
19734 | |
19735 | template<typename Functor> |
19736 | void setFunctionDecl(unsigned value, Functor func) |
19737 | { |
19738 | if (isWide()) |
19739 | setFunctionDecl<OpcodeSize::Wide>(value, func); |
19740 | else |
19741 | setFunctionDecl<OpcodeSize::Narrow>(value, func); |
19742 | } |
19743 | |
19744 | template <OpcodeSize size, typename Functor> |
19745 | void setFunctionDecl(unsigned value, Functor func) |
19746 | { |
19747 | if (!Fits<unsigned, size>::check(value)) |
19748 | value = func(); |
19749 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
19750 | *stream = Fits<unsigned, size>::convert(value); |
19751 | } |
19752 | |
19753 | VirtualRegister m_dst; |
19754 | VirtualRegister m_scope; |
19755 | unsigned m_functionDecl; |
19756 | }; |
19757 | |
19758 | struct OpNewAsyncFuncExp : public Instruction { |
19759 | static constexpr OpcodeID opcodeID = op_new_async_func_exp; |
19760 | |
19761 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19762 | { |
19763 | |
19764 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl) |
19765 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope, functionDecl); |
19766 | } |
19767 | |
19768 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
19769 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19770 | { |
19771 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl); |
19772 | if (shouldAssert == Assert) |
19773 | ASSERT(didEmit); |
19774 | return didEmit; |
19775 | } |
19776 | |
19777 | private: |
19778 | template<OpcodeSize size, bool recordOpcode> |
19779 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19780 | { |
19781 | if (size == OpcodeSize::Wide) |
19782 | gen->alignWideOpcode(); |
19783 | if (Fits<unsigned, size>::check(opcodeID) |
19784 | && Fits<VirtualRegister, size>::check(dst) |
19785 | && Fits<VirtualRegister, size>::check(scope) |
19786 | && Fits<unsigned, size>::check(functionDecl) |
19787 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
19788 | if (recordOpcode) |
19789 | gen->recordOpcode(opcodeID); |
19790 | if (size == OpcodeSize::Wide) |
19791 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
19792 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
19793 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
19794 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
19795 | gen->write(Fits<unsigned, size>::convert(functionDecl)); |
19796 | return true; |
19797 | } |
19798 | return false; |
19799 | } |
19800 | |
19801 | public: |
19802 | template<typename Block> |
19803 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
19804 | { |
19805 | dumper->printLocationAndOp(__location, &"*new_async_func_exp" [!__isWide]); |
19806 | dumper->dumpOperand(m_dst, true); |
19807 | dumper->dumpOperand(m_scope, false); |
19808 | dumper->dumpOperand(m_functionDecl, false); |
19809 | } |
19810 | |
19811 | OpNewAsyncFuncExp(const uint8_t* stream) |
19812 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
19813 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
19814 | , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
19815 | { |
19816 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19817 | } |
19818 | |
19819 | OpNewAsyncFuncExp(const uint32_t* stream) |
19820 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
19821 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
19822 | , m_functionDecl(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
19823 | { |
19824 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19825 | } |
19826 | |
19827 | static OpNewAsyncFuncExp decode(const uint8_t* stream) |
19828 | { |
19829 | if (*stream != op_wide) |
19830 | return { stream }; |
19831 | |
19832 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
19833 | return { wideStream }; |
19834 | } |
19835 | |
19836 | template<typename Functor> |
19837 | void setDst(VirtualRegister value, Functor func) |
19838 | { |
19839 | if (isWide()) |
19840 | setDst<OpcodeSize::Wide>(value, func); |
19841 | else |
19842 | setDst<OpcodeSize::Narrow>(value, func); |
19843 | } |
19844 | |
19845 | template <OpcodeSize size, typename Functor> |
19846 | void setDst(VirtualRegister value, Functor func) |
19847 | { |
19848 | if (!Fits<VirtualRegister, size>::check(value)) |
19849 | value = func(); |
19850 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
19851 | *stream = Fits<VirtualRegister, size>::convert(value); |
19852 | } |
19853 | |
19854 | template<typename Functor> |
19855 | void setScope(VirtualRegister value, Functor func) |
19856 | { |
19857 | if (isWide()) |
19858 | setScope<OpcodeSize::Wide>(value, func); |
19859 | else |
19860 | setScope<OpcodeSize::Narrow>(value, func); |
19861 | } |
19862 | |
19863 | template <OpcodeSize size, typename Functor> |
19864 | void setScope(VirtualRegister value, Functor func) |
19865 | { |
19866 | if (!Fits<VirtualRegister, size>::check(value)) |
19867 | value = func(); |
19868 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
19869 | *stream = Fits<VirtualRegister, size>::convert(value); |
19870 | } |
19871 | |
19872 | template<typename Functor> |
19873 | void setFunctionDecl(unsigned value, Functor func) |
19874 | { |
19875 | if (isWide()) |
19876 | setFunctionDecl<OpcodeSize::Wide>(value, func); |
19877 | else |
19878 | setFunctionDecl<OpcodeSize::Narrow>(value, func); |
19879 | } |
19880 | |
19881 | template <OpcodeSize size, typename Functor> |
19882 | void setFunctionDecl(unsigned value, Functor func) |
19883 | { |
19884 | if (!Fits<unsigned, size>::check(value)) |
19885 | value = func(); |
19886 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
19887 | *stream = Fits<unsigned, size>::convert(value); |
19888 | } |
19889 | |
19890 | VirtualRegister m_dst; |
19891 | VirtualRegister m_scope; |
19892 | unsigned m_functionDecl; |
19893 | }; |
19894 | |
19895 | struct OpNewAsyncGeneratorFunc : public Instruction { |
19896 | static constexpr OpcodeID opcodeID = op_new_async_generator_func; |
19897 | |
19898 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19899 | { |
19900 | |
19901 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl) |
19902 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope, functionDecl); |
19903 | } |
19904 | |
19905 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
19906 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19907 | { |
19908 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl); |
19909 | if (shouldAssert == Assert) |
19910 | ASSERT(didEmit); |
19911 | return didEmit; |
19912 | } |
19913 | |
19914 | private: |
19915 | template<OpcodeSize size, bool recordOpcode> |
19916 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
19917 | { |
19918 | if (size == OpcodeSize::Wide) |
19919 | gen->alignWideOpcode(); |
19920 | if (Fits<unsigned, size>::check(opcodeID) |
19921 | && Fits<VirtualRegister, size>::check(dst) |
19922 | && Fits<VirtualRegister, size>::check(scope) |
19923 | && Fits<unsigned, size>::check(functionDecl) |
19924 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
19925 | if (recordOpcode) |
19926 | gen->recordOpcode(opcodeID); |
19927 | if (size == OpcodeSize::Wide) |
19928 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
19929 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
19930 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
19931 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
19932 | gen->write(Fits<unsigned, size>::convert(functionDecl)); |
19933 | return true; |
19934 | } |
19935 | return false; |
19936 | } |
19937 | |
19938 | public: |
19939 | template<typename Block> |
19940 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
19941 | { |
19942 | dumper->printLocationAndOp(__location, &"*new_async_generator_func" [!__isWide]); |
19943 | dumper->dumpOperand(m_dst, true); |
19944 | dumper->dumpOperand(m_scope, false); |
19945 | dumper->dumpOperand(m_functionDecl, false); |
19946 | } |
19947 | |
19948 | OpNewAsyncGeneratorFunc(const uint8_t* stream) |
19949 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
19950 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
19951 | , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
19952 | { |
19953 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19954 | } |
19955 | |
19956 | OpNewAsyncGeneratorFunc(const uint32_t* stream) |
19957 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
19958 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
19959 | , m_functionDecl(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
19960 | { |
19961 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
19962 | } |
19963 | |
19964 | static OpNewAsyncGeneratorFunc decode(const uint8_t* stream) |
19965 | { |
19966 | if (*stream != op_wide) |
19967 | return { stream }; |
19968 | |
19969 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
19970 | return { wideStream }; |
19971 | } |
19972 | |
19973 | template<typename Functor> |
19974 | void setDst(VirtualRegister value, Functor func) |
19975 | { |
19976 | if (isWide()) |
19977 | setDst<OpcodeSize::Wide>(value, func); |
19978 | else |
19979 | setDst<OpcodeSize::Narrow>(value, func); |
19980 | } |
19981 | |
19982 | template <OpcodeSize size, typename Functor> |
19983 | void setDst(VirtualRegister value, Functor func) |
19984 | { |
19985 | if (!Fits<VirtualRegister, size>::check(value)) |
19986 | value = func(); |
19987 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
19988 | *stream = Fits<VirtualRegister, size>::convert(value); |
19989 | } |
19990 | |
19991 | template<typename Functor> |
19992 | void setScope(VirtualRegister value, Functor func) |
19993 | { |
19994 | if (isWide()) |
19995 | setScope<OpcodeSize::Wide>(value, func); |
19996 | else |
19997 | setScope<OpcodeSize::Narrow>(value, func); |
19998 | } |
19999 | |
20000 | template <OpcodeSize size, typename Functor> |
20001 | void setScope(VirtualRegister value, Functor func) |
20002 | { |
20003 | if (!Fits<VirtualRegister, size>::check(value)) |
20004 | value = func(); |
20005 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
20006 | *stream = Fits<VirtualRegister, size>::convert(value); |
20007 | } |
20008 | |
20009 | template<typename Functor> |
20010 | void setFunctionDecl(unsigned value, Functor func) |
20011 | { |
20012 | if (isWide()) |
20013 | setFunctionDecl<OpcodeSize::Wide>(value, func); |
20014 | else |
20015 | setFunctionDecl<OpcodeSize::Narrow>(value, func); |
20016 | } |
20017 | |
20018 | template <OpcodeSize size, typename Functor> |
20019 | void setFunctionDecl(unsigned value, Functor func) |
20020 | { |
20021 | if (!Fits<unsigned, size>::check(value)) |
20022 | value = func(); |
20023 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
20024 | *stream = Fits<unsigned, size>::convert(value); |
20025 | } |
20026 | |
20027 | VirtualRegister m_dst; |
20028 | VirtualRegister m_scope; |
20029 | unsigned m_functionDecl; |
20030 | }; |
20031 | |
20032 | struct OpNewAsyncGeneratorFuncExp : public Instruction { |
20033 | static constexpr OpcodeID opcodeID = op_new_async_generator_func_exp; |
20034 | |
20035 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
20036 | { |
20037 | |
20038 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl) |
20039 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope, functionDecl); |
20040 | } |
20041 | |
20042 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
20043 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
20044 | { |
20045 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl); |
20046 | if (shouldAssert == Assert) |
20047 | ASSERT(didEmit); |
20048 | return didEmit; |
20049 | } |
20050 | |
20051 | private: |
20052 | template<OpcodeSize size, bool recordOpcode> |
20053 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl) |
20054 | { |
20055 | if (size == OpcodeSize::Wide) |
20056 | gen->alignWideOpcode(); |
20057 | if (Fits<unsigned, size>::check(opcodeID) |
20058 | && Fits<VirtualRegister, size>::check(dst) |
20059 | && Fits<VirtualRegister, size>::check(scope) |
20060 | && Fits<unsigned, size>::check(functionDecl) |
20061 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
20062 | if (recordOpcode) |
20063 | gen->recordOpcode(opcodeID); |
20064 | if (size == OpcodeSize::Wide) |
20065 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
20066 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
20067 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
20068 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
20069 | gen->write(Fits<unsigned, size>::convert(functionDecl)); |
20070 | return true; |
20071 | } |
20072 | return false; |
20073 | } |
20074 | |
20075 | public: |
20076 | template<typename Block> |
20077 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
20078 | { |
20079 | dumper->printLocationAndOp(__location, &"*new_async_generator_func_exp" [!__isWide]); |
20080 | dumper->dumpOperand(m_dst, true); |
20081 | dumper->dumpOperand(m_scope, false); |
20082 | dumper->dumpOperand(m_functionDecl, false); |
20083 | } |
20084 | |
20085 | OpNewAsyncGeneratorFuncExp(const uint8_t* stream) |
20086 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
20087 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
20088 | , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
20089 | { |
20090 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20091 | } |
20092 | |
20093 | OpNewAsyncGeneratorFuncExp(const uint32_t* stream) |
20094 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
20095 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
20096 | , m_functionDecl(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
20097 | { |
20098 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20099 | } |
20100 | |
20101 | static OpNewAsyncGeneratorFuncExp decode(const uint8_t* stream) |
20102 | { |
20103 | if (*stream != op_wide) |
20104 | return { stream }; |
20105 | |
20106 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
20107 | return { wideStream }; |
20108 | } |
20109 | |
20110 | template<typename Functor> |
20111 | void setDst(VirtualRegister value, Functor func) |
20112 | { |
20113 | if (isWide()) |
20114 | setDst<OpcodeSize::Wide>(value, func); |
20115 | else |
20116 | setDst<OpcodeSize::Narrow>(value, func); |
20117 | } |
20118 | |
20119 | template <OpcodeSize size, typename Functor> |
20120 | void setDst(VirtualRegister value, Functor func) |
20121 | { |
20122 | if (!Fits<VirtualRegister, size>::check(value)) |
20123 | value = func(); |
20124 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
20125 | *stream = Fits<VirtualRegister, size>::convert(value); |
20126 | } |
20127 | |
20128 | template<typename Functor> |
20129 | void setScope(VirtualRegister value, Functor func) |
20130 | { |
20131 | if (isWide()) |
20132 | setScope<OpcodeSize::Wide>(value, func); |
20133 | else |
20134 | setScope<OpcodeSize::Narrow>(value, func); |
20135 | } |
20136 | |
20137 | template <OpcodeSize size, typename Functor> |
20138 | void setScope(VirtualRegister value, Functor func) |
20139 | { |
20140 | if (!Fits<VirtualRegister, size>::check(value)) |
20141 | value = func(); |
20142 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
20143 | *stream = Fits<VirtualRegister, size>::convert(value); |
20144 | } |
20145 | |
20146 | template<typename Functor> |
20147 | void setFunctionDecl(unsigned value, Functor func) |
20148 | { |
20149 | if (isWide()) |
20150 | setFunctionDecl<OpcodeSize::Wide>(value, func); |
20151 | else |
20152 | setFunctionDecl<OpcodeSize::Narrow>(value, func); |
20153 | } |
20154 | |
20155 | template <OpcodeSize size, typename Functor> |
20156 | void setFunctionDecl(unsigned value, Functor func) |
20157 | { |
20158 | if (!Fits<unsigned, size>::check(value)) |
20159 | value = func(); |
20160 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
20161 | *stream = Fits<unsigned, size>::convert(value); |
20162 | } |
20163 | |
20164 | VirtualRegister m_dst; |
20165 | VirtualRegister m_scope; |
20166 | unsigned m_functionDecl; |
20167 | }; |
20168 | |
20169 | struct OpSetFunctionName : public Instruction { |
20170 | static constexpr OpcodeID opcodeID = op_set_function_name; |
20171 | |
20172 | static void emit(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name) |
20173 | { |
20174 | |
20175 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, function, name) |
20176 | || emit<OpcodeSize::Wide, Assert, true>(gen, function, name); |
20177 | } |
20178 | |
20179 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
20180 | static bool emit(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name) |
20181 | { |
20182 | bool didEmit = emitImpl<size, recordOpcode>(gen, function, name); |
20183 | if (shouldAssert == Assert) |
20184 | ASSERT(didEmit); |
20185 | return didEmit; |
20186 | } |
20187 | |
20188 | private: |
20189 | template<OpcodeSize size, bool recordOpcode> |
20190 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name) |
20191 | { |
20192 | if (size == OpcodeSize::Wide) |
20193 | gen->alignWideOpcode(); |
20194 | if (Fits<unsigned, size>::check(opcodeID) |
20195 | && Fits<VirtualRegister, size>::check(function) |
20196 | && Fits<VirtualRegister, size>::check(name) |
20197 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
20198 | if (recordOpcode) |
20199 | gen->recordOpcode(opcodeID); |
20200 | if (size == OpcodeSize::Wide) |
20201 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
20202 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
20203 | gen->write(Fits<VirtualRegister, size>::convert(function)); |
20204 | gen->write(Fits<VirtualRegister, size>::convert(name)); |
20205 | return true; |
20206 | } |
20207 | return false; |
20208 | } |
20209 | |
20210 | public: |
20211 | template<typename Block> |
20212 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
20213 | { |
20214 | dumper->printLocationAndOp(__location, &"*set_function_name" [!__isWide]); |
20215 | dumper->dumpOperand(m_function, true); |
20216 | dumper->dumpOperand(m_name, false); |
20217 | } |
20218 | |
20219 | OpSetFunctionName(const uint8_t* stream) |
20220 | : m_function(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
20221 | , m_name(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
20222 | { |
20223 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20224 | } |
20225 | |
20226 | OpSetFunctionName(const uint32_t* stream) |
20227 | : m_function(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
20228 | , m_name(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
20229 | { |
20230 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20231 | } |
20232 | |
20233 | static OpSetFunctionName decode(const uint8_t* stream) |
20234 | { |
20235 | if (*stream != op_wide) |
20236 | return { stream }; |
20237 | |
20238 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
20239 | return { wideStream }; |
20240 | } |
20241 | |
20242 | template<typename Functor> |
20243 | void setFunction(VirtualRegister value, Functor func) |
20244 | { |
20245 | if (isWide()) |
20246 | setFunction<OpcodeSize::Wide>(value, func); |
20247 | else |
20248 | setFunction<OpcodeSize::Narrow>(value, func); |
20249 | } |
20250 | |
20251 | template <OpcodeSize size, typename Functor> |
20252 | void setFunction(VirtualRegister value, Functor func) |
20253 | { |
20254 | if (!Fits<VirtualRegister, size>::check(value)) |
20255 | value = func(); |
20256 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
20257 | *stream = Fits<VirtualRegister, size>::convert(value); |
20258 | } |
20259 | |
20260 | template<typename Functor> |
20261 | void setName(VirtualRegister value, Functor func) |
20262 | { |
20263 | if (isWide()) |
20264 | setName<OpcodeSize::Wide>(value, func); |
20265 | else |
20266 | setName<OpcodeSize::Narrow>(value, func); |
20267 | } |
20268 | |
20269 | template <OpcodeSize size, typename Functor> |
20270 | void setName(VirtualRegister value, Functor func) |
20271 | { |
20272 | if (!Fits<VirtualRegister, size>::check(value)) |
20273 | value = func(); |
20274 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
20275 | *stream = Fits<VirtualRegister, size>::convert(value); |
20276 | } |
20277 | |
20278 | VirtualRegister m_function; |
20279 | VirtualRegister m_name; |
20280 | }; |
20281 | |
20282 | struct OpRet : public Instruction { |
20283 | static constexpr OpcodeID opcodeID = op_ret; |
20284 | |
20285 | static void emit(BytecodeGenerator* gen, VirtualRegister value) |
20286 | { |
20287 | |
20288 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, value) |
20289 | || emit<OpcodeSize::Wide, Assert, true>(gen, value); |
20290 | } |
20291 | |
20292 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
20293 | static bool emit(BytecodeGenerator* gen, VirtualRegister value) |
20294 | { |
20295 | bool didEmit = emitImpl<size, recordOpcode>(gen, value); |
20296 | if (shouldAssert == Assert) |
20297 | ASSERT(didEmit); |
20298 | return didEmit; |
20299 | } |
20300 | |
20301 | private: |
20302 | template<OpcodeSize size, bool recordOpcode> |
20303 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value) |
20304 | { |
20305 | if (size == OpcodeSize::Wide) |
20306 | gen->alignWideOpcode(); |
20307 | if (Fits<unsigned, size>::check(opcodeID) |
20308 | && Fits<VirtualRegister, size>::check(value) |
20309 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
20310 | if (recordOpcode) |
20311 | gen->recordOpcode(opcodeID); |
20312 | if (size == OpcodeSize::Wide) |
20313 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
20314 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
20315 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
20316 | return true; |
20317 | } |
20318 | return false; |
20319 | } |
20320 | |
20321 | public: |
20322 | template<typename Block> |
20323 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
20324 | { |
20325 | dumper->printLocationAndOp(__location, &"*ret" [!__isWide]); |
20326 | dumper->dumpOperand(m_value, true); |
20327 | } |
20328 | |
20329 | OpRet(const uint8_t* stream) |
20330 | : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
20331 | { |
20332 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20333 | } |
20334 | |
20335 | OpRet(const uint32_t* stream) |
20336 | : m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
20337 | { |
20338 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20339 | } |
20340 | |
20341 | static OpRet decode(const uint8_t* stream) |
20342 | { |
20343 | if (*stream != op_wide) |
20344 | return { stream }; |
20345 | |
20346 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
20347 | return { wideStream }; |
20348 | } |
20349 | |
20350 | template<typename Functor> |
20351 | void setValue(VirtualRegister value, Functor func) |
20352 | { |
20353 | if (isWide()) |
20354 | setValue<OpcodeSize::Wide>(value, func); |
20355 | else |
20356 | setValue<OpcodeSize::Narrow>(value, func); |
20357 | } |
20358 | |
20359 | template <OpcodeSize size, typename Functor> |
20360 | void setValue(VirtualRegister value, Functor func) |
20361 | { |
20362 | if (!Fits<VirtualRegister, size>::check(value)) |
20363 | value = func(); |
20364 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
20365 | *stream = Fits<VirtualRegister, size>::convert(value); |
20366 | } |
20367 | |
20368 | VirtualRegister m_value; |
20369 | }; |
20370 | |
20371 | struct OpStrcat : public Instruction { |
20372 | static constexpr OpcodeID opcodeID = op_strcat; |
20373 | |
20374 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src, int count) |
20375 | { |
20376 | |
20377 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, src, count) |
20378 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, src, count); |
20379 | } |
20380 | |
20381 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
20382 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src, int count) |
20383 | { |
20384 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, src, count); |
20385 | if (shouldAssert == Assert) |
20386 | ASSERT(didEmit); |
20387 | return didEmit; |
20388 | } |
20389 | |
20390 | private: |
20391 | template<OpcodeSize size, bool recordOpcode> |
20392 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src, int count) |
20393 | { |
20394 | if (size == OpcodeSize::Wide) |
20395 | gen->alignWideOpcode(); |
20396 | if (Fits<unsigned, size>::check(opcodeID) |
20397 | && Fits<VirtualRegister, size>::check(dst) |
20398 | && Fits<VirtualRegister, size>::check(src) |
20399 | && Fits<int, size>::check(count) |
20400 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
20401 | if (recordOpcode) |
20402 | gen->recordOpcode(opcodeID); |
20403 | if (size == OpcodeSize::Wide) |
20404 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
20405 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
20406 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
20407 | gen->write(Fits<VirtualRegister, size>::convert(src)); |
20408 | gen->write(Fits<int, size>::convert(count)); |
20409 | return true; |
20410 | } |
20411 | return false; |
20412 | } |
20413 | |
20414 | public: |
20415 | template<typename Block> |
20416 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
20417 | { |
20418 | dumper->printLocationAndOp(__location, &"*strcat" [!__isWide]); |
20419 | dumper->dumpOperand(m_dst, true); |
20420 | dumper->dumpOperand(m_src, false); |
20421 | dumper->dumpOperand(m_count, false); |
20422 | } |
20423 | |
20424 | OpStrcat(const uint8_t* stream) |
20425 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
20426 | , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
20427 | , m_count(Fits<int, OpcodeSize::Narrow>::convert(stream[3])) |
20428 | { |
20429 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20430 | } |
20431 | |
20432 | OpStrcat(const uint32_t* stream) |
20433 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
20434 | , m_src(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
20435 | , m_count(Fits<int, OpcodeSize::Wide>::convert(stream[3])) |
20436 | { |
20437 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20438 | } |
20439 | |
20440 | static OpStrcat decode(const uint8_t* stream) |
20441 | { |
20442 | if (*stream != op_wide) |
20443 | return { stream }; |
20444 | |
20445 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
20446 | return { wideStream }; |
20447 | } |
20448 | |
20449 | template<typename Functor> |
20450 | void setDst(VirtualRegister value, Functor func) |
20451 | { |
20452 | if (isWide()) |
20453 | setDst<OpcodeSize::Wide>(value, func); |
20454 | else |
20455 | setDst<OpcodeSize::Narrow>(value, func); |
20456 | } |
20457 | |
20458 | template <OpcodeSize size, typename Functor> |
20459 | void setDst(VirtualRegister value, Functor func) |
20460 | { |
20461 | if (!Fits<VirtualRegister, size>::check(value)) |
20462 | value = func(); |
20463 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
20464 | *stream = Fits<VirtualRegister, size>::convert(value); |
20465 | } |
20466 | |
20467 | template<typename Functor> |
20468 | void setSrc(VirtualRegister value, Functor func) |
20469 | { |
20470 | if (isWide()) |
20471 | setSrc<OpcodeSize::Wide>(value, func); |
20472 | else |
20473 | setSrc<OpcodeSize::Narrow>(value, func); |
20474 | } |
20475 | |
20476 | template <OpcodeSize size, typename Functor> |
20477 | void setSrc(VirtualRegister value, Functor func) |
20478 | { |
20479 | if (!Fits<VirtualRegister, size>::check(value)) |
20480 | value = func(); |
20481 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
20482 | *stream = Fits<VirtualRegister, size>::convert(value); |
20483 | } |
20484 | |
20485 | template<typename Functor> |
20486 | void setCount(int value, Functor func) |
20487 | { |
20488 | if (isWide()) |
20489 | setCount<OpcodeSize::Wide>(value, func); |
20490 | else |
20491 | setCount<OpcodeSize::Narrow>(value, func); |
20492 | } |
20493 | |
20494 | template <OpcodeSize size, typename Functor> |
20495 | void setCount(int value, Functor func) |
20496 | { |
20497 | if (!Fits<int, size>::check(value)) |
20498 | value = func(); |
20499 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
20500 | *stream = Fits<int, size>::convert(value); |
20501 | } |
20502 | |
20503 | VirtualRegister m_dst; |
20504 | VirtualRegister m_src; |
20505 | int m_count; |
20506 | }; |
20507 | |
20508 | struct OpToPrimitive : public Instruction { |
20509 | static constexpr OpcodeID opcodeID = op_to_primitive; |
20510 | |
20511 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src) |
20512 | { |
20513 | |
20514 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, src) |
20515 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, src); |
20516 | } |
20517 | |
20518 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
20519 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src) |
20520 | { |
20521 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, src); |
20522 | if (shouldAssert == Assert) |
20523 | ASSERT(didEmit); |
20524 | return didEmit; |
20525 | } |
20526 | |
20527 | private: |
20528 | template<OpcodeSize size, bool recordOpcode> |
20529 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src) |
20530 | { |
20531 | if (size == OpcodeSize::Wide) |
20532 | gen->alignWideOpcode(); |
20533 | if (Fits<unsigned, size>::check(opcodeID) |
20534 | && Fits<VirtualRegister, size>::check(dst) |
20535 | && Fits<VirtualRegister, size>::check(src) |
20536 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
20537 | if (recordOpcode) |
20538 | gen->recordOpcode(opcodeID); |
20539 | if (size == OpcodeSize::Wide) |
20540 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
20541 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
20542 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
20543 | gen->write(Fits<VirtualRegister, size>::convert(src)); |
20544 | return true; |
20545 | } |
20546 | return false; |
20547 | } |
20548 | |
20549 | public: |
20550 | template<typename Block> |
20551 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
20552 | { |
20553 | dumper->printLocationAndOp(__location, &"*to_primitive" [!__isWide]); |
20554 | dumper->dumpOperand(m_dst, true); |
20555 | dumper->dumpOperand(m_src, false); |
20556 | } |
20557 | |
20558 | OpToPrimitive(const uint8_t* stream) |
20559 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
20560 | , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
20561 | { |
20562 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20563 | } |
20564 | |
20565 | OpToPrimitive(const uint32_t* stream) |
20566 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
20567 | , m_src(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
20568 | { |
20569 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20570 | } |
20571 | |
20572 | static OpToPrimitive decode(const uint8_t* stream) |
20573 | { |
20574 | if (*stream != op_wide) |
20575 | return { stream }; |
20576 | |
20577 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
20578 | return { wideStream }; |
20579 | } |
20580 | |
20581 | template<typename Functor> |
20582 | void setDst(VirtualRegister value, Functor func) |
20583 | { |
20584 | if (isWide()) |
20585 | setDst<OpcodeSize::Wide>(value, func); |
20586 | else |
20587 | setDst<OpcodeSize::Narrow>(value, func); |
20588 | } |
20589 | |
20590 | template <OpcodeSize size, typename Functor> |
20591 | void setDst(VirtualRegister value, Functor func) |
20592 | { |
20593 | if (!Fits<VirtualRegister, size>::check(value)) |
20594 | value = func(); |
20595 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
20596 | *stream = Fits<VirtualRegister, size>::convert(value); |
20597 | } |
20598 | |
20599 | template<typename Functor> |
20600 | void setSrc(VirtualRegister value, Functor func) |
20601 | { |
20602 | if (isWide()) |
20603 | setSrc<OpcodeSize::Wide>(value, func); |
20604 | else |
20605 | setSrc<OpcodeSize::Narrow>(value, func); |
20606 | } |
20607 | |
20608 | template <OpcodeSize size, typename Functor> |
20609 | void setSrc(VirtualRegister value, Functor func) |
20610 | { |
20611 | if (!Fits<VirtualRegister, size>::check(value)) |
20612 | value = func(); |
20613 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
20614 | *stream = Fits<VirtualRegister, size>::convert(value); |
20615 | } |
20616 | |
20617 | VirtualRegister m_dst; |
20618 | VirtualRegister m_src; |
20619 | }; |
20620 | |
20621 | struct OpPutToArguments : public Instruction { |
20622 | static constexpr OpcodeID opcodeID = op_put_to_arguments; |
20623 | |
20624 | static void emit(BytecodeGenerator* gen, VirtualRegister arguments, unsigned index, VirtualRegister value) |
20625 | { |
20626 | |
20627 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, arguments, index, value) |
20628 | || emit<OpcodeSize::Wide, Assert, true>(gen, arguments, index, value); |
20629 | } |
20630 | |
20631 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
20632 | static bool emit(BytecodeGenerator* gen, VirtualRegister arguments, unsigned index, VirtualRegister value) |
20633 | { |
20634 | bool didEmit = emitImpl<size, recordOpcode>(gen, arguments, index, value); |
20635 | if (shouldAssert == Assert) |
20636 | ASSERT(didEmit); |
20637 | return didEmit; |
20638 | } |
20639 | |
20640 | private: |
20641 | template<OpcodeSize size, bool recordOpcode> |
20642 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister arguments, unsigned index, VirtualRegister value) |
20643 | { |
20644 | if (size == OpcodeSize::Wide) |
20645 | gen->alignWideOpcode(); |
20646 | if (Fits<unsigned, size>::check(opcodeID) |
20647 | && Fits<VirtualRegister, size>::check(arguments) |
20648 | && Fits<unsigned, size>::check(index) |
20649 | && Fits<VirtualRegister, size>::check(value) |
20650 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
20651 | if (recordOpcode) |
20652 | gen->recordOpcode(opcodeID); |
20653 | if (size == OpcodeSize::Wide) |
20654 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
20655 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
20656 | gen->write(Fits<VirtualRegister, size>::convert(arguments)); |
20657 | gen->write(Fits<unsigned, size>::convert(index)); |
20658 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
20659 | return true; |
20660 | } |
20661 | return false; |
20662 | } |
20663 | |
20664 | public: |
20665 | template<typename Block> |
20666 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
20667 | { |
20668 | dumper->printLocationAndOp(__location, &"*put_to_arguments" [!__isWide]); |
20669 | dumper->dumpOperand(m_arguments, true); |
20670 | dumper->dumpOperand(m_index, false); |
20671 | dumper->dumpOperand(m_value, false); |
20672 | } |
20673 | |
20674 | OpPutToArguments(const uint8_t* stream) |
20675 | : m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
20676 | , m_index(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2])) |
20677 | , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
20678 | { |
20679 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20680 | } |
20681 | |
20682 | OpPutToArguments(const uint32_t* stream) |
20683 | : m_arguments(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
20684 | , m_index(Fits<unsigned, OpcodeSize::Wide>::convert(stream[2])) |
20685 | , m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
20686 | { |
20687 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20688 | } |
20689 | |
20690 | static OpPutToArguments decode(const uint8_t* stream) |
20691 | { |
20692 | if (*stream != op_wide) |
20693 | return { stream }; |
20694 | |
20695 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
20696 | return { wideStream }; |
20697 | } |
20698 | |
20699 | template<typename Functor> |
20700 | void setArguments(VirtualRegister value, Functor func) |
20701 | { |
20702 | if (isWide()) |
20703 | setArguments<OpcodeSize::Wide>(value, func); |
20704 | else |
20705 | setArguments<OpcodeSize::Narrow>(value, func); |
20706 | } |
20707 | |
20708 | template <OpcodeSize size, typename Functor> |
20709 | void setArguments(VirtualRegister value, Functor func) |
20710 | { |
20711 | if (!Fits<VirtualRegister, size>::check(value)) |
20712 | value = func(); |
20713 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
20714 | *stream = Fits<VirtualRegister, size>::convert(value); |
20715 | } |
20716 | |
20717 | template<typename Functor> |
20718 | void setIndex(unsigned value, Functor func) |
20719 | { |
20720 | if (isWide()) |
20721 | setIndex<OpcodeSize::Wide>(value, func); |
20722 | else |
20723 | setIndex<OpcodeSize::Narrow>(value, func); |
20724 | } |
20725 | |
20726 | template <OpcodeSize size, typename Functor> |
20727 | void setIndex(unsigned value, Functor func) |
20728 | { |
20729 | if (!Fits<unsigned, size>::check(value)) |
20730 | value = func(); |
20731 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
20732 | *stream = Fits<unsigned, size>::convert(value); |
20733 | } |
20734 | |
20735 | template<typename Functor> |
20736 | void setValue(VirtualRegister value, Functor func) |
20737 | { |
20738 | if (isWide()) |
20739 | setValue<OpcodeSize::Wide>(value, func); |
20740 | else |
20741 | setValue<OpcodeSize::Narrow>(value, func); |
20742 | } |
20743 | |
20744 | template <OpcodeSize size, typename Functor> |
20745 | void setValue(VirtualRegister value, Functor func) |
20746 | { |
20747 | if (!Fits<VirtualRegister, size>::check(value)) |
20748 | value = func(); |
20749 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
20750 | *stream = Fits<VirtualRegister, size>::convert(value); |
20751 | } |
20752 | |
20753 | VirtualRegister m_arguments; |
20754 | unsigned m_index; |
20755 | VirtualRegister m_value; |
20756 | }; |
20757 | |
20758 | struct OpPushWithScope : public Instruction { |
20759 | static constexpr OpcodeID opcodeID = op_push_with_scope; |
20760 | |
20761 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister currentScope, VirtualRegister newScope) |
20762 | { |
20763 | |
20764 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, currentScope, newScope) |
20765 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, currentScope, newScope); |
20766 | } |
20767 | |
20768 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
20769 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister currentScope, VirtualRegister newScope) |
20770 | { |
20771 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, currentScope, newScope); |
20772 | if (shouldAssert == Assert) |
20773 | ASSERT(didEmit); |
20774 | return didEmit; |
20775 | } |
20776 | |
20777 | private: |
20778 | template<OpcodeSize size, bool recordOpcode> |
20779 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister currentScope, VirtualRegister newScope) |
20780 | { |
20781 | if (size == OpcodeSize::Wide) |
20782 | gen->alignWideOpcode(); |
20783 | if (Fits<unsigned, size>::check(opcodeID) |
20784 | && Fits<VirtualRegister, size>::check(dst) |
20785 | && Fits<VirtualRegister, size>::check(currentScope) |
20786 | && Fits<VirtualRegister, size>::check(newScope) |
20787 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
20788 | if (recordOpcode) |
20789 | gen->recordOpcode(opcodeID); |
20790 | if (size == OpcodeSize::Wide) |
20791 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
20792 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
20793 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
20794 | gen->write(Fits<VirtualRegister, size>::convert(currentScope)); |
20795 | gen->write(Fits<VirtualRegister, size>::convert(newScope)); |
20796 | return true; |
20797 | } |
20798 | return false; |
20799 | } |
20800 | |
20801 | public: |
20802 | template<typename Block> |
20803 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
20804 | { |
20805 | dumper->printLocationAndOp(__location, &"*push_with_scope" [!__isWide]); |
20806 | dumper->dumpOperand(m_dst, true); |
20807 | dumper->dumpOperand(m_currentScope, false); |
20808 | dumper->dumpOperand(m_newScope, false); |
20809 | } |
20810 | |
20811 | OpPushWithScope(const uint8_t* stream) |
20812 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
20813 | , m_currentScope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
20814 | , m_newScope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
20815 | { |
20816 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20817 | } |
20818 | |
20819 | OpPushWithScope(const uint32_t* stream) |
20820 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
20821 | , m_currentScope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
20822 | , m_newScope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
20823 | { |
20824 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20825 | } |
20826 | |
20827 | static OpPushWithScope decode(const uint8_t* stream) |
20828 | { |
20829 | if (*stream != op_wide) |
20830 | return { stream }; |
20831 | |
20832 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
20833 | return { wideStream }; |
20834 | } |
20835 | |
20836 | template<typename Functor> |
20837 | void setDst(VirtualRegister value, Functor func) |
20838 | { |
20839 | if (isWide()) |
20840 | setDst<OpcodeSize::Wide>(value, func); |
20841 | else |
20842 | setDst<OpcodeSize::Narrow>(value, func); |
20843 | } |
20844 | |
20845 | template <OpcodeSize size, typename Functor> |
20846 | void setDst(VirtualRegister value, Functor func) |
20847 | { |
20848 | if (!Fits<VirtualRegister, size>::check(value)) |
20849 | value = func(); |
20850 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
20851 | *stream = Fits<VirtualRegister, size>::convert(value); |
20852 | } |
20853 | |
20854 | template<typename Functor> |
20855 | void setCurrentScope(VirtualRegister value, Functor func) |
20856 | { |
20857 | if (isWide()) |
20858 | setCurrentScope<OpcodeSize::Wide>(value, func); |
20859 | else |
20860 | setCurrentScope<OpcodeSize::Narrow>(value, func); |
20861 | } |
20862 | |
20863 | template <OpcodeSize size, typename Functor> |
20864 | void setCurrentScope(VirtualRegister value, Functor func) |
20865 | { |
20866 | if (!Fits<VirtualRegister, size>::check(value)) |
20867 | value = func(); |
20868 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
20869 | *stream = Fits<VirtualRegister, size>::convert(value); |
20870 | } |
20871 | |
20872 | template<typename Functor> |
20873 | void setNewScope(VirtualRegister value, Functor func) |
20874 | { |
20875 | if (isWide()) |
20876 | setNewScope<OpcodeSize::Wide>(value, func); |
20877 | else |
20878 | setNewScope<OpcodeSize::Narrow>(value, func); |
20879 | } |
20880 | |
20881 | template <OpcodeSize size, typename Functor> |
20882 | void setNewScope(VirtualRegister value, Functor func) |
20883 | { |
20884 | if (!Fits<VirtualRegister, size>::check(value)) |
20885 | value = func(); |
20886 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
20887 | *stream = Fits<VirtualRegister, size>::convert(value); |
20888 | } |
20889 | |
20890 | VirtualRegister m_dst; |
20891 | VirtualRegister m_currentScope; |
20892 | VirtualRegister m_newScope; |
20893 | }; |
20894 | |
20895 | struct OpCreateLexicalEnvironment : public Instruction { |
20896 | static constexpr OpcodeID opcodeID = op_create_lexical_environment; |
20897 | |
20898 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue) |
20899 | { |
20900 | |
20901 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, symbolTable, initialValue) |
20902 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope, symbolTable, initialValue); |
20903 | } |
20904 | |
20905 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
20906 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue) |
20907 | { |
20908 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, symbolTable, initialValue); |
20909 | if (shouldAssert == Assert) |
20910 | ASSERT(didEmit); |
20911 | return didEmit; |
20912 | } |
20913 | |
20914 | private: |
20915 | template<OpcodeSize size, bool recordOpcode> |
20916 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue) |
20917 | { |
20918 | if (size == OpcodeSize::Wide) |
20919 | gen->alignWideOpcode(); |
20920 | if (Fits<unsigned, size>::check(opcodeID) |
20921 | && Fits<VirtualRegister, size>::check(dst) |
20922 | && Fits<VirtualRegister, size>::check(scope) |
20923 | && Fits<VirtualRegister, size>::check(symbolTable) |
20924 | && Fits<VirtualRegister, size>::check(initialValue) |
20925 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
20926 | if (recordOpcode) |
20927 | gen->recordOpcode(opcodeID); |
20928 | if (size == OpcodeSize::Wide) |
20929 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
20930 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
20931 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
20932 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
20933 | gen->write(Fits<VirtualRegister, size>::convert(symbolTable)); |
20934 | gen->write(Fits<VirtualRegister, size>::convert(initialValue)); |
20935 | return true; |
20936 | } |
20937 | return false; |
20938 | } |
20939 | |
20940 | public: |
20941 | template<typename Block> |
20942 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
20943 | { |
20944 | dumper->printLocationAndOp(__location, &"*create_lexical_environment" [!__isWide]); |
20945 | dumper->dumpOperand(m_dst, true); |
20946 | dumper->dumpOperand(m_scope, false); |
20947 | dumper->dumpOperand(m_symbolTable, false); |
20948 | dumper->dumpOperand(m_initialValue, false); |
20949 | } |
20950 | |
20951 | OpCreateLexicalEnvironment(const uint8_t* stream) |
20952 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
20953 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
20954 | , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
20955 | , m_initialValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
20956 | { |
20957 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20958 | } |
20959 | |
20960 | OpCreateLexicalEnvironment(const uint32_t* stream) |
20961 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
20962 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
20963 | , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
20964 | , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
20965 | { |
20966 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
20967 | } |
20968 | |
20969 | static OpCreateLexicalEnvironment decode(const uint8_t* stream) |
20970 | { |
20971 | if (*stream != op_wide) |
20972 | return { stream }; |
20973 | |
20974 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
20975 | return { wideStream }; |
20976 | } |
20977 | |
20978 | template<typename Functor> |
20979 | void setDst(VirtualRegister value, Functor func) |
20980 | { |
20981 | if (isWide()) |
20982 | setDst<OpcodeSize::Wide>(value, func); |
20983 | else |
20984 | setDst<OpcodeSize::Narrow>(value, func); |
20985 | } |
20986 | |
20987 | template <OpcodeSize size, typename Functor> |
20988 | void setDst(VirtualRegister value, Functor func) |
20989 | { |
20990 | if (!Fits<VirtualRegister, size>::check(value)) |
20991 | value = func(); |
20992 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
20993 | *stream = Fits<VirtualRegister, size>::convert(value); |
20994 | } |
20995 | |
20996 | template<typename Functor> |
20997 | void setScope(VirtualRegister value, Functor func) |
20998 | { |
20999 | if (isWide()) |
21000 | setScope<OpcodeSize::Wide>(value, func); |
21001 | else |
21002 | setScope<OpcodeSize::Narrow>(value, func); |
21003 | } |
21004 | |
21005 | template <OpcodeSize size, typename Functor> |
21006 | void setScope(VirtualRegister value, Functor func) |
21007 | { |
21008 | if (!Fits<VirtualRegister, size>::check(value)) |
21009 | value = func(); |
21010 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
21011 | *stream = Fits<VirtualRegister, size>::convert(value); |
21012 | } |
21013 | |
21014 | template<typename Functor> |
21015 | void setSymbolTable(VirtualRegister value, Functor func) |
21016 | { |
21017 | if (isWide()) |
21018 | setSymbolTable<OpcodeSize::Wide>(value, func); |
21019 | else |
21020 | setSymbolTable<OpcodeSize::Narrow>(value, func); |
21021 | } |
21022 | |
21023 | template <OpcodeSize size, typename Functor> |
21024 | void setSymbolTable(VirtualRegister value, Functor func) |
21025 | { |
21026 | if (!Fits<VirtualRegister, size>::check(value)) |
21027 | value = func(); |
21028 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
21029 | *stream = Fits<VirtualRegister, size>::convert(value); |
21030 | } |
21031 | |
21032 | template<typename Functor> |
21033 | void setInitialValue(VirtualRegister value, Functor func) |
21034 | { |
21035 | if (isWide()) |
21036 | setInitialValue<OpcodeSize::Wide>(value, func); |
21037 | else |
21038 | setInitialValue<OpcodeSize::Narrow>(value, func); |
21039 | } |
21040 | |
21041 | template <OpcodeSize size, typename Functor> |
21042 | void setInitialValue(VirtualRegister value, Functor func) |
21043 | { |
21044 | if (!Fits<VirtualRegister, size>::check(value)) |
21045 | value = func(); |
21046 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
21047 | *stream = Fits<VirtualRegister, size>::convert(value); |
21048 | } |
21049 | |
21050 | VirtualRegister m_dst; |
21051 | VirtualRegister m_scope; |
21052 | VirtualRegister m_symbolTable; |
21053 | VirtualRegister m_initialValue; |
21054 | }; |
21055 | |
21056 | struct OpCreateGeneratorFrameEnvironment : public Instruction { |
21057 | static constexpr OpcodeID opcodeID = op_create_generator_frame_environment; |
21058 | |
21059 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue) |
21060 | { |
21061 | |
21062 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, symbolTable, initialValue) |
21063 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope, symbolTable, initialValue); |
21064 | } |
21065 | |
21066 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
21067 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue) |
21068 | { |
21069 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, symbolTable, initialValue); |
21070 | if (shouldAssert == Assert) |
21071 | ASSERT(didEmit); |
21072 | return didEmit; |
21073 | } |
21074 | |
21075 | private: |
21076 | template<OpcodeSize size, bool recordOpcode> |
21077 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue) |
21078 | { |
21079 | if (size == OpcodeSize::Wide) |
21080 | gen->alignWideOpcode(); |
21081 | if (Fits<unsigned, size>::check(opcodeID) |
21082 | && Fits<VirtualRegister, size>::check(dst) |
21083 | && Fits<VirtualRegister, size>::check(scope) |
21084 | && Fits<VirtualRegister, size>::check(symbolTable) |
21085 | && Fits<VirtualRegister, size>::check(initialValue) |
21086 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
21087 | if (recordOpcode) |
21088 | gen->recordOpcode(opcodeID); |
21089 | if (size == OpcodeSize::Wide) |
21090 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
21091 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
21092 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
21093 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
21094 | gen->write(Fits<VirtualRegister, size>::convert(symbolTable)); |
21095 | gen->write(Fits<VirtualRegister, size>::convert(initialValue)); |
21096 | return true; |
21097 | } |
21098 | return false; |
21099 | } |
21100 | |
21101 | public: |
21102 | template<typename Block> |
21103 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
21104 | { |
21105 | dumper->printLocationAndOp(__location, &"*create_generator_frame_environment" [!__isWide]); |
21106 | dumper->dumpOperand(m_dst, true); |
21107 | dumper->dumpOperand(m_scope, false); |
21108 | dumper->dumpOperand(m_symbolTable, false); |
21109 | dumper->dumpOperand(m_initialValue, false); |
21110 | } |
21111 | |
21112 | OpCreateGeneratorFrameEnvironment(const uint8_t* stream) |
21113 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
21114 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
21115 | , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
21116 | , m_initialValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
21117 | { |
21118 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21119 | } |
21120 | |
21121 | OpCreateGeneratorFrameEnvironment(const uint32_t* stream) |
21122 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
21123 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
21124 | , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
21125 | , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
21126 | { |
21127 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21128 | } |
21129 | |
21130 | static OpCreateGeneratorFrameEnvironment decode(const uint8_t* stream) |
21131 | { |
21132 | if (*stream != op_wide) |
21133 | return { stream }; |
21134 | |
21135 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
21136 | return { wideStream }; |
21137 | } |
21138 | |
21139 | template<typename Functor> |
21140 | void setDst(VirtualRegister value, Functor func) |
21141 | { |
21142 | if (isWide()) |
21143 | setDst<OpcodeSize::Wide>(value, func); |
21144 | else |
21145 | setDst<OpcodeSize::Narrow>(value, func); |
21146 | } |
21147 | |
21148 | template <OpcodeSize size, typename Functor> |
21149 | void setDst(VirtualRegister value, Functor func) |
21150 | { |
21151 | if (!Fits<VirtualRegister, size>::check(value)) |
21152 | value = func(); |
21153 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
21154 | *stream = Fits<VirtualRegister, size>::convert(value); |
21155 | } |
21156 | |
21157 | template<typename Functor> |
21158 | void setScope(VirtualRegister value, Functor func) |
21159 | { |
21160 | if (isWide()) |
21161 | setScope<OpcodeSize::Wide>(value, func); |
21162 | else |
21163 | setScope<OpcodeSize::Narrow>(value, func); |
21164 | } |
21165 | |
21166 | template <OpcodeSize size, typename Functor> |
21167 | void setScope(VirtualRegister value, Functor func) |
21168 | { |
21169 | if (!Fits<VirtualRegister, size>::check(value)) |
21170 | value = func(); |
21171 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
21172 | *stream = Fits<VirtualRegister, size>::convert(value); |
21173 | } |
21174 | |
21175 | template<typename Functor> |
21176 | void setSymbolTable(VirtualRegister value, Functor func) |
21177 | { |
21178 | if (isWide()) |
21179 | setSymbolTable<OpcodeSize::Wide>(value, func); |
21180 | else |
21181 | setSymbolTable<OpcodeSize::Narrow>(value, func); |
21182 | } |
21183 | |
21184 | template <OpcodeSize size, typename Functor> |
21185 | void setSymbolTable(VirtualRegister value, Functor func) |
21186 | { |
21187 | if (!Fits<VirtualRegister, size>::check(value)) |
21188 | value = func(); |
21189 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
21190 | *stream = Fits<VirtualRegister, size>::convert(value); |
21191 | } |
21192 | |
21193 | template<typename Functor> |
21194 | void setInitialValue(VirtualRegister value, Functor func) |
21195 | { |
21196 | if (isWide()) |
21197 | setInitialValue<OpcodeSize::Wide>(value, func); |
21198 | else |
21199 | setInitialValue<OpcodeSize::Narrow>(value, func); |
21200 | } |
21201 | |
21202 | template <OpcodeSize size, typename Functor> |
21203 | void setInitialValue(VirtualRegister value, Functor func) |
21204 | { |
21205 | if (!Fits<VirtualRegister, size>::check(value)) |
21206 | value = func(); |
21207 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
21208 | *stream = Fits<VirtualRegister, size>::convert(value); |
21209 | } |
21210 | |
21211 | VirtualRegister m_dst; |
21212 | VirtualRegister m_scope; |
21213 | VirtualRegister m_symbolTable; |
21214 | VirtualRegister m_initialValue; |
21215 | }; |
21216 | |
21217 | struct OpGetParentScope : public Instruction { |
21218 | static constexpr OpcodeID opcodeID = op_get_parent_scope; |
21219 | |
21220 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope) |
21221 | { |
21222 | |
21223 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope) |
21224 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope); |
21225 | } |
21226 | |
21227 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
21228 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope) |
21229 | { |
21230 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope); |
21231 | if (shouldAssert == Assert) |
21232 | ASSERT(didEmit); |
21233 | return didEmit; |
21234 | } |
21235 | |
21236 | private: |
21237 | template<OpcodeSize size, bool recordOpcode> |
21238 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope) |
21239 | { |
21240 | if (size == OpcodeSize::Wide) |
21241 | gen->alignWideOpcode(); |
21242 | if (Fits<unsigned, size>::check(opcodeID) |
21243 | && Fits<VirtualRegister, size>::check(dst) |
21244 | && Fits<VirtualRegister, size>::check(scope) |
21245 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
21246 | if (recordOpcode) |
21247 | gen->recordOpcode(opcodeID); |
21248 | if (size == OpcodeSize::Wide) |
21249 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
21250 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
21251 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
21252 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
21253 | return true; |
21254 | } |
21255 | return false; |
21256 | } |
21257 | |
21258 | public: |
21259 | template<typename Block> |
21260 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
21261 | { |
21262 | dumper->printLocationAndOp(__location, &"*get_parent_scope" [!__isWide]); |
21263 | dumper->dumpOperand(m_dst, true); |
21264 | dumper->dumpOperand(m_scope, false); |
21265 | } |
21266 | |
21267 | OpGetParentScope(const uint8_t* stream) |
21268 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
21269 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
21270 | { |
21271 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21272 | } |
21273 | |
21274 | OpGetParentScope(const uint32_t* stream) |
21275 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
21276 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
21277 | { |
21278 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21279 | } |
21280 | |
21281 | static OpGetParentScope decode(const uint8_t* stream) |
21282 | { |
21283 | if (*stream != op_wide) |
21284 | return { stream }; |
21285 | |
21286 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
21287 | return { wideStream }; |
21288 | } |
21289 | |
21290 | template<typename Functor> |
21291 | void setDst(VirtualRegister value, Functor func) |
21292 | { |
21293 | if (isWide()) |
21294 | setDst<OpcodeSize::Wide>(value, func); |
21295 | else |
21296 | setDst<OpcodeSize::Narrow>(value, func); |
21297 | } |
21298 | |
21299 | template <OpcodeSize size, typename Functor> |
21300 | void setDst(VirtualRegister value, Functor func) |
21301 | { |
21302 | if (!Fits<VirtualRegister, size>::check(value)) |
21303 | value = func(); |
21304 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
21305 | *stream = Fits<VirtualRegister, size>::convert(value); |
21306 | } |
21307 | |
21308 | template<typename Functor> |
21309 | void setScope(VirtualRegister value, Functor func) |
21310 | { |
21311 | if (isWide()) |
21312 | setScope<OpcodeSize::Wide>(value, func); |
21313 | else |
21314 | setScope<OpcodeSize::Narrow>(value, func); |
21315 | } |
21316 | |
21317 | template <OpcodeSize size, typename Functor> |
21318 | void setScope(VirtualRegister value, Functor func) |
21319 | { |
21320 | if (!Fits<VirtualRegister, size>::check(value)) |
21321 | value = func(); |
21322 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
21323 | *stream = Fits<VirtualRegister, size>::convert(value); |
21324 | } |
21325 | |
21326 | VirtualRegister m_dst; |
21327 | VirtualRegister m_scope; |
21328 | }; |
21329 | |
21330 | struct OpThrow : public Instruction { |
21331 | static constexpr OpcodeID opcodeID = op_throw; |
21332 | |
21333 | static void emit(BytecodeGenerator* gen, VirtualRegister value) |
21334 | { |
21335 | |
21336 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, value) |
21337 | || emit<OpcodeSize::Wide, Assert, true>(gen, value); |
21338 | } |
21339 | |
21340 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
21341 | static bool emit(BytecodeGenerator* gen, VirtualRegister value) |
21342 | { |
21343 | bool didEmit = emitImpl<size, recordOpcode>(gen, value); |
21344 | if (shouldAssert == Assert) |
21345 | ASSERT(didEmit); |
21346 | return didEmit; |
21347 | } |
21348 | |
21349 | private: |
21350 | template<OpcodeSize size, bool recordOpcode> |
21351 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value) |
21352 | { |
21353 | if (size == OpcodeSize::Wide) |
21354 | gen->alignWideOpcode(); |
21355 | if (Fits<unsigned, size>::check(opcodeID) |
21356 | && Fits<VirtualRegister, size>::check(value) |
21357 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
21358 | if (recordOpcode) |
21359 | gen->recordOpcode(opcodeID); |
21360 | if (size == OpcodeSize::Wide) |
21361 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
21362 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
21363 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
21364 | return true; |
21365 | } |
21366 | return false; |
21367 | } |
21368 | |
21369 | public: |
21370 | template<typename Block> |
21371 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
21372 | { |
21373 | dumper->printLocationAndOp(__location, &"*throw" [!__isWide]); |
21374 | dumper->dumpOperand(m_value, true); |
21375 | } |
21376 | |
21377 | OpThrow(const uint8_t* stream) |
21378 | : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
21379 | { |
21380 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21381 | } |
21382 | |
21383 | OpThrow(const uint32_t* stream) |
21384 | : m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
21385 | { |
21386 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21387 | } |
21388 | |
21389 | static OpThrow decode(const uint8_t* stream) |
21390 | { |
21391 | if (*stream != op_wide) |
21392 | return { stream }; |
21393 | |
21394 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
21395 | return { wideStream }; |
21396 | } |
21397 | |
21398 | template<typename Functor> |
21399 | void setValue(VirtualRegister value, Functor func) |
21400 | { |
21401 | if (isWide()) |
21402 | setValue<OpcodeSize::Wide>(value, func); |
21403 | else |
21404 | setValue<OpcodeSize::Narrow>(value, func); |
21405 | } |
21406 | |
21407 | template <OpcodeSize size, typename Functor> |
21408 | void setValue(VirtualRegister value, Functor func) |
21409 | { |
21410 | if (!Fits<VirtualRegister, size>::check(value)) |
21411 | value = func(); |
21412 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
21413 | *stream = Fits<VirtualRegister, size>::convert(value); |
21414 | } |
21415 | |
21416 | VirtualRegister m_value; |
21417 | }; |
21418 | |
21419 | struct OpThrowStaticError : public Instruction { |
21420 | static constexpr OpcodeID opcodeID = op_throw_static_error; |
21421 | |
21422 | static void emit(BytecodeGenerator* gen, VirtualRegister message, ErrorType errorType) |
21423 | { |
21424 | |
21425 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, message, errorType) |
21426 | || emit<OpcodeSize::Wide, Assert, true>(gen, message, errorType); |
21427 | } |
21428 | |
21429 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
21430 | static bool emit(BytecodeGenerator* gen, VirtualRegister message, ErrorType errorType) |
21431 | { |
21432 | bool didEmit = emitImpl<size, recordOpcode>(gen, message, errorType); |
21433 | if (shouldAssert == Assert) |
21434 | ASSERT(didEmit); |
21435 | return didEmit; |
21436 | } |
21437 | |
21438 | private: |
21439 | template<OpcodeSize size, bool recordOpcode> |
21440 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister message, ErrorType errorType) |
21441 | { |
21442 | if (size == OpcodeSize::Wide) |
21443 | gen->alignWideOpcode(); |
21444 | if (Fits<unsigned, size>::check(opcodeID) |
21445 | && Fits<VirtualRegister, size>::check(message) |
21446 | && Fits<ErrorType, size>::check(errorType) |
21447 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
21448 | if (recordOpcode) |
21449 | gen->recordOpcode(opcodeID); |
21450 | if (size == OpcodeSize::Wide) |
21451 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
21452 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
21453 | gen->write(Fits<VirtualRegister, size>::convert(message)); |
21454 | gen->write(Fits<ErrorType, size>::convert(errorType)); |
21455 | return true; |
21456 | } |
21457 | return false; |
21458 | } |
21459 | |
21460 | public: |
21461 | template<typename Block> |
21462 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
21463 | { |
21464 | dumper->printLocationAndOp(__location, &"*throw_static_error" [!__isWide]); |
21465 | dumper->dumpOperand(m_message, true); |
21466 | dumper->dumpOperand(m_errorType, false); |
21467 | } |
21468 | |
21469 | OpThrowStaticError(const uint8_t* stream) |
21470 | : m_message(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
21471 | , m_errorType(Fits<ErrorType, OpcodeSize::Narrow>::convert(stream[2])) |
21472 | { |
21473 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21474 | } |
21475 | |
21476 | OpThrowStaticError(const uint32_t* stream) |
21477 | : m_message(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
21478 | , m_errorType(Fits<ErrorType, OpcodeSize::Wide>::convert(stream[2])) |
21479 | { |
21480 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21481 | } |
21482 | |
21483 | static OpThrowStaticError decode(const uint8_t* stream) |
21484 | { |
21485 | if (*stream != op_wide) |
21486 | return { stream }; |
21487 | |
21488 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
21489 | return { wideStream }; |
21490 | } |
21491 | |
21492 | template<typename Functor> |
21493 | void setMessage(VirtualRegister value, Functor func) |
21494 | { |
21495 | if (isWide()) |
21496 | setMessage<OpcodeSize::Wide>(value, func); |
21497 | else |
21498 | setMessage<OpcodeSize::Narrow>(value, func); |
21499 | } |
21500 | |
21501 | template <OpcodeSize size, typename Functor> |
21502 | void setMessage(VirtualRegister value, Functor func) |
21503 | { |
21504 | if (!Fits<VirtualRegister, size>::check(value)) |
21505 | value = func(); |
21506 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
21507 | *stream = Fits<VirtualRegister, size>::convert(value); |
21508 | } |
21509 | |
21510 | template<typename Functor> |
21511 | void setErrorType(ErrorType value, Functor func) |
21512 | { |
21513 | if (isWide()) |
21514 | setErrorType<OpcodeSize::Wide>(value, func); |
21515 | else |
21516 | setErrorType<OpcodeSize::Narrow>(value, func); |
21517 | } |
21518 | |
21519 | template <OpcodeSize size, typename Functor> |
21520 | void setErrorType(ErrorType value, Functor func) |
21521 | { |
21522 | if (!Fits<ErrorType, size>::check(value)) |
21523 | value = func(); |
21524 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
21525 | *stream = Fits<ErrorType, size>::convert(value); |
21526 | } |
21527 | |
21528 | VirtualRegister m_message; |
21529 | ErrorType m_errorType; |
21530 | }; |
21531 | |
21532 | struct OpDebug : public Instruction { |
21533 | static constexpr OpcodeID opcodeID = op_debug; |
21534 | |
21535 | static void emit(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint) |
21536 | { |
21537 | |
21538 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, debugHookType, hasBreakpoint) |
21539 | || emit<OpcodeSize::Wide, Assert, true>(gen, debugHookType, hasBreakpoint); |
21540 | } |
21541 | |
21542 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
21543 | static bool emit(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint) |
21544 | { |
21545 | bool didEmit = emitImpl<size, recordOpcode>(gen, debugHookType, hasBreakpoint); |
21546 | if (shouldAssert == Assert) |
21547 | ASSERT(didEmit); |
21548 | return didEmit; |
21549 | } |
21550 | |
21551 | private: |
21552 | template<OpcodeSize size, bool recordOpcode> |
21553 | static bool emitImpl(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint) |
21554 | { |
21555 | if (size == OpcodeSize::Wide) |
21556 | gen->alignWideOpcode(); |
21557 | if (Fits<unsigned, size>::check(opcodeID) |
21558 | && Fits<DebugHookType, size>::check(debugHookType) |
21559 | && Fits<bool, size>::check(hasBreakpoint) |
21560 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
21561 | if (recordOpcode) |
21562 | gen->recordOpcode(opcodeID); |
21563 | if (size == OpcodeSize::Wide) |
21564 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
21565 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
21566 | gen->write(Fits<DebugHookType, size>::convert(debugHookType)); |
21567 | gen->write(Fits<bool, size>::convert(hasBreakpoint)); |
21568 | return true; |
21569 | } |
21570 | return false; |
21571 | } |
21572 | |
21573 | public: |
21574 | template<typename Block> |
21575 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
21576 | { |
21577 | dumper->printLocationAndOp(__location, &"*debug" [!__isWide]); |
21578 | dumper->dumpOperand(m_debugHookType, true); |
21579 | dumper->dumpOperand(m_hasBreakpoint, false); |
21580 | } |
21581 | |
21582 | OpDebug(const uint8_t* stream) |
21583 | : m_debugHookType(Fits<DebugHookType, OpcodeSize::Narrow>::convert(stream[1])) |
21584 | , m_hasBreakpoint(Fits<bool, OpcodeSize::Narrow>::convert(stream[2])) |
21585 | { |
21586 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21587 | } |
21588 | |
21589 | OpDebug(const uint32_t* stream) |
21590 | : m_debugHookType(Fits<DebugHookType, OpcodeSize::Wide>::convert(stream[1])) |
21591 | , m_hasBreakpoint(Fits<bool, OpcodeSize::Wide>::convert(stream[2])) |
21592 | { |
21593 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21594 | } |
21595 | |
21596 | static OpDebug decode(const uint8_t* stream) |
21597 | { |
21598 | if (*stream != op_wide) |
21599 | return { stream }; |
21600 | |
21601 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
21602 | return { wideStream }; |
21603 | } |
21604 | |
21605 | template<typename Functor> |
21606 | void setDebugHookType(DebugHookType value, Functor func) |
21607 | { |
21608 | if (isWide()) |
21609 | setDebugHookType<OpcodeSize::Wide>(value, func); |
21610 | else |
21611 | setDebugHookType<OpcodeSize::Narrow>(value, func); |
21612 | } |
21613 | |
21614 | template <OpcodeSize size, typename Functor> |
21615 | void setDebugHookType(DebugHookType value, Functor func) |
21616 | { |
21617 | if (!Fits<DebugHookType, size>::check(value)) |
21618 | value = func(); |
21619 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
21620 | *stream = Fits<DebugHookType, size>::convert(value); |
21621 | } |
21622 | |
21623 | template<typename Functor> |
21624 | void setHasBreakpoint(bool value, Functor func) |
21625 | { |
21626 | if (isWide()) |
21627 | setHasBreakpoint<OpcodeSize::Wide>(value, func); |
21628 | else |
21629 | setHasBreakpoint<OpcodeSize::Narrow>(value, func); |
21630 | } |
21631 | |
21632 | template <OpcodeSize size, typename Functor> |
21633 | void setHasBreakpoint(bool value, Functor func) |
21634 | { |
21635 | if (!Fits<bool, size>::check(value)) |
21636 | value = func(); |
21637 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
21638 | *stream = Fits<bool, size>::convert(value); |
21639 | } |
21640 | |
21641 | DebugHookType m_debugHookType; |
21642 | bool m_hasBreakpoint; |
21643 | }; |
21644 | |
21645 | struct OpEnd : public Instruction { |
21646 | static constexpr OpcodeID opcodeID = op_end; |
21647 | |
21648 | static void emit(BytecodeGenerator* gen, VirtualRegister value) |
21649 | { |
21650 | |
21651 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, value) |
21652 | || emit<OpcodeSize::Wide, Assert, true>(gen, value); |
21653 | } |
21654 | |
21655 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
21656 | static bool emit(BytecodeGenerator* gen, VirtualRegister value) |
21657 | { |
21658 | bool didEmit = emitImpl<size, recordOpcode>(gen, value); |
21659 | if (shouldAssert == Assert) |
21660 | ASSERT(didEmit); |
21661 | return didEmit; |
21662 | } |
21663 | |
21664 | private: |
21665 | template<OpcodeSize size, bool recordOpcode> |
21666 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value) |
21667 | { |
21668 | if (size == OpcodeSize::Wide) |
21669 | gen->alignWideOpcode(); |
21670 | if (Fits<unsigned, size>::check(opcodeID) |
21671 | && Fits<VirtualRegister, size>::check(value) |
21672 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
21673 | if (recordOpcode) |
21674 | gen->recordOpcode(opcodeID); |
21675 | if (size == OpcodeSize::Wide) |
21676 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
21677 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
21678 | gen->write(Fits<VirtualRegister, size>::convert(value)); |
21679 | return true; |
21680 | } |
21681 | return false; |
21682 | } |
21683 | |
21684 | public: |
21685 | template<typename Block> |
21686 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
21687 | { |
21688 | dumper->printLocationAndOp(__location, &"*end" [!__isWide]); |
21689 | dumper->dumpOperand(m_value, true); |
21690 | } |
21691 | |
21692 | OpEnd(const uint8_t* stream) |
21693 | : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
21694 | { |
21695 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21696 | } |
21697 | |
21698 | OpEnd(const uint32_t* stream) |
21699 | : m_value(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
21700 | { |
21701 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21702 | } |
21703 | |
21704 | static OpEnd decode(const uint8_t* stream) |
21705 | { |
21706 | if (*stream != op_wide) |
21707 | return { stream }; |
21708 | |
21709 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
21710 | return { wideStream }; |
21711 | } |
21712 | |
21713 | template<typename Functor> |
21714 | void setValue(VirtualRegister value, Functor func) |
21715 | { |
21716 | if (isWide()) |
21717 | setValue<OpcodeSize::Wide>(value, func); |
21718 | else |
21719 | setValue<OpcodeSize::Narrow>(value, func); |
21720 | } |
21721 | |
21722 | template <OpcodeSize size, typename Functor> |
21723 | void setValue(VirtualRegister value, Functor func) |
21724 | { |
21725 | if (!Fits<VirtualRegister, size>::check(value)) |
21726 | value = func(); |
21727 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
21728 | *stream = Fits<VirtualRegister, size>::convert(value); |
21729 | } |
21730 | |
21731 | VirtualRegister m_value; |
21732 | }; |
21733 | |
21734 | struct OpGetEnumerableLength : public Instruction { |
21735 | static constexpr OpcodeID opcodeID = op_get_enumerable_length; |
21736 | |
21737 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base) |
21738 | { |
21739 | |
21740 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base) |
21741 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base); |
21742 | } |
21743 | |
21744 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
21745 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base) |
21746 | { |
21747 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base); |
21748 | if (shouldAssert == Assert) |
21749 | ASSERT(didEmit); |
21750 | return didEmit; |
21751 | } |
21752 | |
21753 | private: |
21754 | template<OpcodeSize size, bool recordOpcode> |
21755 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base) |
21756 | { |
21757 | if (size == OpcodeSize::Wide) |
21758 | gen->alignWideOpcode(); |
21759 | if (Fits<unsigned, size>::check(opcodeID) |
21760 | && Fits<VirtualRegister, size>::check(dst) |
21761 | && Fits<VirtualRegister, size>::check(base) |
21762 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
21763 | if (recordOpcode) |
21764 | gen->recordOpcode(opcodeID); |
21765 | if (size == OpcodeSize::Wide) |
21766 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
21767 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
21768 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
21769 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
21770 | return true; |
21771 | } |
21772 | return false; |
21773 | } |
21774 | |
21775 | public: |
21776 | template<typename Block> |
21777 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
21778 | { |
21779 | dumper->printLocationAndOp(__location, &"*get_enumerable_length" [!__isWide]); |
21780 | dumper->dumpOperand(m_dst, true); |
21781 | dumper->dumpOperand(m_base, false); |
21782 | } |
21783 | |
21784 | OpGetEnumerableLength(const uint8_t* stream) |
21785 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
21786 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
21787 | { |
21788 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21789 | } |
21790 | |
21791 | OpGetEnumerableLength(const uint32_t* stream) |
21792 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
21793 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
21794 | { |
21795 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21796 | } |
21797 | |
21798 | static OpGetEnumerableLength decode(const uint8_t* stream) |
21799 | { |
21800 | if (*stream != op_wide) |
21801 | return { stream }; |
21802 | |
21803 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
21804 | return { wideStream }; |
21805 | } |
21806 | |
21807 | template<typename Functor> |
21808 | void setDst(VirtualRegister value, Functor func) |
21809 | { |
21810 | if (isWide()) |
21811 | setDst<OpcodeSize::Wide>(value, func); |
21812 | else |
21813 | setDst<OpcodeSize::Narrow>(value, func); |
21814 | } |
21815 | |
21816 | template <OpcodeSize size, typename Functor> |
21817 | void setDst(VirtualRegister value, Functor func) |
21818 | { |
21819 | if (!Fits<VirtualRegister, size>::check(value)) |
21820 | value = func(); |
21821 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
21822 | *stream = Fits<VirtualRegister, size>::convert(value); |
21823 | } |
21824 | |
21825 | template<typename Functor> |
21826 | void setBase(VirtualRegister value, Functor func) |
21827 | { |
21828 | if (isWide()) |
21829 | setBase<OpcodeSize::Wide>(value, func); |
21830 | else |
21831 | setBase<OpcodeSize::Narrow>(value, func); |
21832 | } |
21833 | |
21834 | template <OpcodeSize size, typename Functor> |
21835 | void setBase(VirtualRegister value, Functor func) |
21836 | { |
21837 | if (!Fits<VirtualRegister, size>::check(value)) |
21838 | value = func(); |
21839 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
21840 | *stream = Fits<VirtualRegister, size>::convert(value); |
21841 | } |
21842 | |
21843 | VirtualRegister m_dst; |
21844 | VirtualRegister m_base; |
21845 | }; |
21846 | |
21847 | struct OpHasStructureProperty : public Instruction { |
21848 | static constexpr OpcodeID opcodeID = op_has_structure_property; |
21849 | |
21850 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator) |
21851 | { |
21852 | |
21853 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, enumerator) |
21854 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, property, enumerator); |
21855 | } |
21856 | |
21857 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
21858 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator) |
21859 | { |
21860 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, enumerator); |
21861 | if (shouldAssert == Assert) |
21862 | ASSERT(didEmit); |
21863 | return didEmit; |
21864 | } |
21865 | |
21866 | private: |
21867 | template<OpcodeSize size, bool recordOpcode> |
21868 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator) |
21869 | { |
21870 | if (size == OpcodeSize::Wide) |
21871 | gen->alignWideOpcode(); |
21872 | if (Fits<unsigned, size>::check(opcodeID) |
21873 | && Fits<VirtualRegister, size>::check(dst) |
21874 | && Fits<VirtualRegister, size>::check(base) |
21875 | && Fits<VirtualRegister, size>::check(property) |
21876 | && Fits<VirtualRegister, size>::check(enumerator) |
21877 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
21878 | if (recordOpcode) |
21879 | gen->recordOpcode(opcodeID); |
21880 | if (size == OpcodeSize::Wide) |
21881 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
21882 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
21883 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
21884 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
21885 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
21886 | gen->write(Fits<VirtualRegister, size>::convert(enumerator)); |
21887 | return true; |
21888 | } |
21889 | return false; |
21890 | } |
21891 | |
21892 | public: |
21893 | template<typename Block> |
21894 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
21895 | { |
21896 | dumper->printLocationAndOp(__location, &"*has_structure_property" [!__isWide]); |
21897 | dumper->dumpOperand(m_dst, true); |
21898 | dumper->dumpOperand(m_base, false); |
21899 | dumper->dumpOperand(m_property, false); |
21900 | dumper->dumpOperand(m_enumerator, false); |
21901 | } |
21902 | |
21903 | OpHasStructureProperty(const uint8_t* stream) |
21904 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
21905 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
21906 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
21907 | , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4])) |
21908 | { |
21909 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21910 | } |
21911 | |
21912 | OpHasStructureProperty(const uint32_t* stream) |
21913 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
21914 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
21915 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
21916 | , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[4])) |
21917 | { |
21918 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
21919 | } |
21920 | |
21921 | static OpHasStructureProperty decode(const uint8_t* stream) |
21922 | { |
21923 | if (*stream != op_wide) |
21924 | return { stream }; |
21925 | |
21926 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
21927 | return { wideStream }; |
21928 | } |
21929 | |
21930 | template<typename Functor> |
21931 | void setDst(VirtualRegister value, Functor func) |
21932 | { |
21933 | if (isWide()) |
21934 | setDst<OpcodeSize::Wide>(value, func); |
21935 | else |
21936 | setDst<OpcodeSize::Narrow>(value, func); |
21937 | } |
21938 | |
21939 | template <OpcodeSize size, typename Functor> |
21940 | void setDst(VirtualRegister value, Functor func) |
21941 | { |
21942 | if (!Fits<VirtualRegister, size>::check(value)) |
21943 | value = func(); |
21944 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
21945 | *stream = Fits<VirtualRegister, size>::convert(value); |
21946 | } |
21947 | |
21948 | template<typename Functor> |
21949 | void setBase(VirtualRegister value, Functor func) |
21950 | { |
21951 | if (isWide()) |
21952 | setBase<OpcodeSize::Wide>(value, func); |
21953 | else |
21954 | setBase<OpcodeSize::Narrow>(value, func); |
21955 | } |
21956 | |
21957 | template <OpcodeSize size, typename Functor> |
21958 | void setBase(VirtualRegister value, Functor func) |
21959 | { |
21960 | if (!Fits<VirtualRegister, size>::check(value)) |
21961 | value = func(); |
21962 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
21963 | *stream = Fits<VirtualRegister, size>::convert(value); |
21964 | } |
21965 | |
21966 | template<typename Functor> |
21967 | void setProperty(VirtualRegister value, Functor func) |
21968 | { |
21969 | if (isWide()) |
21970 | setProperty<OpcodeSize::Wide>(value, func); |
21971 | else |
21972 | setProperty<OpcodeSize::Narrow>(value, func); |
21973 | } |
21974 | |
21975 | template <OpcodeSize size, typename Functor> |
21976 | void setProperty(VirtualRegister value, Functor func) |
21977 | { |
21978 | if (!Fits<VirtualRegister, size>::check(value)) |
21979 | value = func(); |
21980 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
21981 | *stream = Fits<VirtualRegister, size>::convert(value); |
21982 | } |
21983 | |
21984 | template<typename Functor> |
21985 | void setEnumerator(VirtualRegister value, Functor func) |
21986 | { |
21987 | if (isWide()) |
21988 | setEnumerator<OpcodeSize::Wide>(value, func); |
21989 | else |
21990 | setEnumerator<OpcodeSize::Narrow>(value, func); |
21991 | } |
21992 | |
21993 | template <OpcodeSize size, typename Functor> |
21994 | void setEnumerator(VirtualRegister value, Functor func) |
21995 | { |
21996 | if (!Fits<VirtualRegister, size>::check(value)) |
21997 | value = func(); |
21998 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value); |
21999 | *stream = Fits<VirtualRegister, size>::convert(value); |
22000 | } |
22001 | |
22002 | VirtualRegister m_dst; |
22003 | VirtualRegister m_base; |
22004 | VirtualRegister m_property; |
22005 | VirtualRegister m_enumerator; |
22006 | }; |
22007 | |
22008 | struct OpHasGenericProperty : public Instruction { |
22009 | static constexpr OpcodeID opcodeID = op_has_generic_property; |
22010 | |
22011 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property) |
22012 | { |
22013 | |
22014 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property) |
22015 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base, property); |
22016 | } |
22017 | |
22018 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
22019 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property) |
22020 | { |
22021 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property); |
22022 | if (shouldAssert == Assert) |
22023 | ASSERT(didEmit); |
22024 | return didEmit; |
22025 | } |
22026 | |
22027 | private: |
22028 | template<OpcodeSize size, bool recordOpcode> |
22029 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property) |
22030 | { |
22031 | if (size == OpcodeSize::Wide) |
22032 | gen->alignWideOpcode(); |
22033 | if (Fits<unsigned, size>::check(opcodeID) |
22034 | && Fits<VirtualRegister, size>::check(dst) |
22035 | && Fits<VirtualRegister, size>::check(base) |
22036 | && Fits<VirtualRegister, size>::check(property) |
22037 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
22038 | if (recordOpcode) |
22039 | gen->recordOpcode(opcodeID); |
22040 | if (size == OpcodeSize::Wide) |
22041 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
22042 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
22043 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
22044 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
22045 | gen->write(Fits<VirtualRegister, size>::convert(property)); |
22046 | return true; |
22047 | } |
22048 | return false; |
22049 | } |
22050 | |
22051 | public: |
22052 | template<typename Block> |
22053 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
22054 | { |
22055 | dumper->printLocationAndOp(__location, &"*has_generic_property" [!__isWide]); |
22056 | dumper->dumpOperand(m_dst, true); |
22057 | dumper->dumpOperand(m_base, false); |
22058 | dumper->dumpOperand(m_property, false); |
22059 | } |
22060 | |
22061 | OpHasGenericProperty(const uint8_t* stream) |
22062 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
22063 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
22064 | , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
22065 | { |
22066 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22067 | } |
22068 | |
22069 | OpHasGenericProperty(const uint32_t* stream) |
22070 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
22071 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
22072 | , m_property(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
22073 | { |
22074 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22075 | } |
22076 | |
22077 | static OpHasGenericProperty decode(const uint8_t* stream) |
22078 | { |
22079 | if (*stream != op_wide) |
22080 | return { stream }; |
22081 | |
22082 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
22083 | return { wideStream }; |
22084 | } |
22085 | |
22086 | template<typename Functor> |
22087 | void setDst(VirtualRegister value, Functor func) |
22088 | { |
22089 | if (isWide()) |
22090 | setDst<OpcodeSize::Wide>(value, func); |
22091 | else |
22092 | setDst<OpcodeSize::Narrow>(value, func); |
22093 | } |
22094 | |
22095 | template <OpcodeSize size, typename Functor> |
22096 | void setDst(VirtualRegister value, Functor func) |
22097 | { |
22098 | if (!Fits<VirtualRegister, size>::check(value)) |
22099 | value = func(); |
22100 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
22101 | *stream = Fits<VirtualRegister, size>::convert(value); |
22102 | } |
22103 | |
22104 | template<typename Functor> |
22105 | void setBase(VirtualRegister value, Functor func) |
22106 | { |
22107 | if (isWide()) |
22108 | setBase<OpcodeSize::Wide>(value, func); |
22109 | else |
22110 | setBase<OpcodeSize::Narrow>(value, func); |
22111 | } |
22112 | |
22113 | template <OpcodeSize size, typename Functor> |
22114 | void setBase(VirtualRegister value, Functor func) |
22115 | { |
22116 | if (!Fits<VirtualRegister, size>::check(value)) |
22117 | value = func(); |
22118 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
22119 | *stream = Fits<VirtualRegister, size>::convert(value); |
22120 | } |
22121 | |
22122 | template<typename Functor> |
22123 | void setProperty(VirtualRegister value, Functor func) |
22124 | { |
22125 | if (isWide()) |
22126 | setProperty<OpcodeSize::Wide>(value, func); |
22127 | else |
22128 | setProperty<OpcodeSize::Narrow>(value, func); |
22129 | } |
22130 | |
22131 | template <OpcodeSize size, typename Functor> |
22132 | void setProperty(VirtualRegister value, Functor func) |
22133 | { |
22134 | if (!Fits<VirtualRegister, size>::check(value)) |
22135 | value = func(); |
22136 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
22137 | *stream = Fits<VirtualRegister, size>::convert(value); |
22138 | } |
22139 | |
22140 | VirtualRegister m_dst; |
22141 | VirtualRegister m_base; |
22142 | VirtualRegister m_property; |
22143 | }; |
22144 | |
22145 | struct OpGetPropertyEnumerator : public Instruction { |
22146 | static constexpr OpcodeID opcodeID = op_get_property_enumerator; |
22147 | |
22148 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base) |
22149 | { |
22150 | |
22151 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base) |
22152 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, base); |
22153 | } |
22154 | |
22155 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
22156 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base) |
22157 | { |
22158 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base); |
22159 | if (shouldAssert == Assert) |
22160 | ASSERT(didEmit); |
22161 | return didEmit; |
22162 | } |
22163 | |
22164 | private: |
22165 | template<OpcodeSize size, bool recordOpcode> |
22166 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base) |
22167 | { |
22168 | if (size == OpcodeSize::Wide) |
22169 | gen->alignWideOpcode(); |
22170 | if (Fits<unsigned, size>::check(opcodeID) |
22171 | && Fits<VirtualRegister, size>::check(dst) |
22172 | && Fits<VirtualRegister, size>::check(base) |
22173 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
22174 | if (recordOpcode) |
22175 | gen->recordOpcode(opcodeID); |
22176 | if (size == OpcodeSize::Wide) |
22177 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
22178 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
22179 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
22180 | gen->write(Fits<VirtualRegister, size>::convert(base)); |
22181 | return true; |
22182 | } |
22183 | return false; |
22184 | } |
22185 | |
22186 | public: |
22187 | template<typename Block> |
22188 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
22189 | { |
22190 | dumper->printLocationAndOp(__location, &"*get_property_enumerator" [!__isWide]); |
22191 | dumper->dumpOperand(m_dst, true); |
22192 | dumper->dumpOperand(m_base, false); |
22193 | } |
22194 | |
22195 | OpGetPropertyEnumerator(const uint8_t* stream) |
22196 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
22197 | , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
22198 | { |
22199 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22200 | } |
22201 | |
22202 | OpGetPropertyEnumerator(const uint32_t* stream) |
22203 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
22204 | , m_base(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
22205 | { |
22206 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22207 | } |
22208 | |
22209 | static OpGetPropertyEnumerator decode(const uint8_t* stream) |
22210 | { |
22211 | if (*stream != op_wide) |
22212 | return { stream }; |
22213 | |
22214 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
22215 | return { wideStream }; |
22216 | } |
22217 | |
22218 | template<typename Functor> |
22219 | void setDst(VirtualRegister value, Functor func) |
22220 | { |
22221 | if (isWide()) |
22222 | setDst<OpcodeSize::Wide>(value, func); |
22223 | else |
22224 | setDst<OpcodeSize::Narrow>(value, func); |
22225 | } |
22226 | |
22227 | template <OpcodeSize size, typename Functor> |
22228 | void setDst(VirtualRegister value, Functor func) |
22229 | { |
22230 | if (!Fits<VirtualRegister, size>::check(value)) |
22231 | value = func(); |
22232 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
22233 | *stream = Fits<VirtualRegister, size>::convert(value); |
22234 | } |
22235 | |
22236 | template<typename Functor> |
22237 | void setBase(VirtualRegister value, Functor func) |
22238 | { |
22239 | if (isWide()) |
22240 | setBase<OpcodeSize::Wide>(value, func); |
22241 | else |
22242 | setBase<OpcodeSize::Narrow>(value, func); |
22243 | } |
22244 | |
22245 | template <OpcodeSize size, typename Functor> |
22246 | void setBase(VirtualRegister value, Functor func) |
22247 | { |
22248 | if (!Fits<VirtualRegister, size>::check(value)) |
22249 | value = func(); |
22250 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
22251 | *stream = Fits<VirtualRegister, size>::convert(value); |
22252 | } |
22253 | |
22254 | VirtualRegister m_dst; |
22255 | VirtualRegister m_base; |
22256 | }; |
22257 | |
22258 | struct OpEnumeratorStructurePname : public Instruction { |
22259 | static constexpr OpcodeID opcodeID = op_enumerator_structure_pname; |
22260 | |
22261 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index) |
22262 | { |
22263 | |
22264 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, enumerator, index) |
22265 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, enumerator, index); |
22266 | } |
22267 | |
22268 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
22269 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index) |
22270 | { |
22271 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, enumerator, index); |
22272 | if (shouldAssert == Assert) |
22273 | ASSERT(didEmit); |
22274 | return didEmit; |
22275 | } |
22276 | |
22277 | private: |
22278 | template<OpcodeSize size, bool recordOpcode> |
22279 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index) |
22280 | { |
22281 | if (size == OpcodeSize::Wide) |
22282 | gen->alignWideOpcode(); |
22283 | if (Fits<unsigned, size>::check(opcodeID) |
22284 | && Fits<VirtualRegister, size>::check(dst) |
22285 | && Fits<VirtualRegister, size>::check(enumerator) |
22286 | && Fits<VirtualRegister, size>::check(index) |
22287 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
22288 | if (recordOpcode) |
22289 | gen->recordOpcode(opcodeID); |
22290 | if (size == OpcodeSize::Wide) |
22291 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
22292 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
22293 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
22294 | gen->write(Fits<VirtualRegister, size>::convert(enumerator)); |
22295 | gen->write(Fits<VirtualRegister, size>::convert(index)); |
22296 | return true; |
22297 | } |
22298 | return false; |
22299 | } |
22300 | |
22301 | public: |
22302 | template<typename Block> |
22303 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
22304 | { |
22305 | dumper->printLocationAndOp(__location, &"*enumerator_structure_pname" [!__isWide]); |
22306 | dumper->dumpOperand(m_dst, true); |
22307 | dumper->dumpOperand(m_enumerator, false); |
22308 | dumper->dumpOperand(m_index, false); |
22309 | } |
22310 | |
22311 | OpEnumeratorStructurePname(const uint8_t* stream) |
22312 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
22313 | , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
22314 | , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
22315 | { |
22316 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22317 | } |
22318 | |
22319 | OpEnumeratorStructurePname(const uint32_t* stream) |
22320 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
22321 | , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
22322 | , m_index(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
22323 | { |
22324 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22325 | } |
22326 | |
22327 | static OpEnumeratorStructurePname decode(const uint8_t* stream) |
22328 | { |
22329 | if (*stream != op_wide) |
22330 | return { stream }; |
22331 | |
22332 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
22333 | return { wideStream }; |
22334 | } |
22335 | |
22336 | template<typename Functor> |
22337 | void setDst(VirtualRegister value, Functor func) |
22338 | { |
22339 | if (isWide()) |
22340 | setDst<OpcodeSize::Wide>(value, func); |
22341 | else |
22342 | setDst<OpcodeSize::Narrow>(value, func); |
22343 | } |
22344 | |
22345 | template <OpcodeSize size, typename Functor> |
22346 | void setDst(VirtualRegister value, Functor func) |
22347 | { |
22348 | if (!Fits<VirtualRegister, size>::check(value)) |
22349 | value = func(); |
22350 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
22351 | *stream = Fits<VirtualRegister, size>::convert(value); |
22352 | } |
22353 | |
22354 | template<typename Functor> |
22355 | void setEnumerator(VirtualRegister value, Functor func) |
22356 | { |
22357 | if (isWide()) |
22358 | setEnumerator<OpcodeSize::Wide>(value, func); |
22359 | else |
22360 | setEnumerator<OpcodeSize::Narrow>(value, func); |
22361 | } |
22362 | |
22363 | template <OpcodeSize size, typename Functor> |
22364 | void setEnumerator(VirtualRegister value, Functor func) |
22365 | { |
22366 | if (!Fits<VirtualRegister, size>::check(value)) |
22367 | value = func(); |
22368 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
22369 | *stream = Fits<VirtualRegister, size>::convert(value); |
22370 | } |
22371 | |
22372 | template<typename Functor> |
22373 | void setIndex(VirtualRegister value, Functor func) |
22374 | { |
22375 | if (isWide()) |
22376 | setIndex<OpcodeSize::Wide>(value, func); |
22377 | else |
22378 | setIndex<OpcodeSize::Narrow>(value, func); |
22379 | } |
22380 | |
22381 | template <OpcodeSize size, typename Functor> |
22382 | void setIndex(VirtualRegister value, Functor func) |
22383 | { |
22384 | if (!Fits<VirtualRegister, size>::check(value)) |
22385 | value = func(); |
22386 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
22387 | *stream = Fits<VirtualRegister, size>::convert(value); |
22388 | } |
22389 | |
22390 | VirtualRegister m_dst; |
22391 | VirtualRegister m_enumerator; |
22392 | VirtualRegister m_index; |
22393 | }; |
22394 | |
22395 | struct OpEnumeratorGenericPname : public Instruction { |
22396 | static constexpr OpcodeID opcodeID = op_enumerator_generic_pname; |
22397 | |
22398 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index) |
22399 | { |
22400 | |
22401 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, enumerator, index) |
22402 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, enumerator, index); |
22403 | } |
22404 | |
22405 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
22406 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index) |
22407 | { |
22408 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, enumerator, index); |
22409 | if (shouldAssert == Assert) |
22410 | ASSERT(didEmit); |
22411 | return didEmit; |
22412 | } |
22413 | |
22414 | private: |
22415 | template<OpcodeSize size, bool recordOpcode> |
22416 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index) |
22417 | { |
22418 | if (size == OpcodeSize::Wide) |
22419 | gen->alignWideOpcode(); |
22420 | if (Fits<unsigned, size>::check(opcodeID) |
22421 | && Fits<VirtualRegister, size>::check(dst) |
22422 | && Fits<VirtualRegister, size>::check(enumerator) |
22423 | && Fits<VirtualRegister, size>::check(index) |
22424 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
22425 | if (recordOpcode) |
22426 | gen->recordOpcode(opcodeID); |
22427 | if (size == OpcodeSize::Wide) |
22428 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
22429 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
22430 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
22431 | gen->write(Fits<VirtualRegister, size>::convert(enumerator)); |
22432 | gen->write(Fits<VirtualRegister, size>::convert(index)); |
22433 | return true; |
22434 | } |
22435 | return false; |
22436 | } |
22437 | |
22438 | public: |
22439 | template<typename Block> |
22440 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
22441 | { |
22442 | dumper->printLocationAndOp(__location, &"*enumerator_generic_pname" [!__isWide]); |
22443 | dumper->dumpOperand(m_dst, true); |
22444 | dumper->dumpOperand(m_enumerator, false); |
22445 | dumper->dumpOperand(m_index, false); |
22446 | } |
22447 | |
22448 | OpEnumeratorGenericPname(const uint8_t* stream) |
22449 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
22450 | , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
22451 | , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
22452 | { |
22453 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22454 | } |
22455 | |
22456 | OpEnumeratorGenericPname(const uint32_t* stream) |
22457 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
22458 | , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
22459 | , m_index(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
22460 | { |
22461 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22462 | } |
22463 | |
22464 | static OpEnumeratorGenericPname decode(const uint8_t* stream) |
22465 | { |
22466 | if (*stream != op_wide) |
22467 | return { stream }; |
22468 | |
22469 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
22470 | return { wideStream }; |
22471 | } |
22472 | |
22473 | template<typename Functor> |
22474 | void setDst(VirtualRegister value, Functor func) |
22475 | { |
22476 | if (isWide()) |
22477 | setDst<OpcodeSize::Wide>(value, func); |
22478 | else |
22479 | setDst<OpcodeSize::Narrow>(value, func); |
22480 | } |
22481 | |
22482 | template <OpcodeSize size, typename Functor> |
22483 | void setDst(VirtualRegister value, Functor func) |
22484 | { |
22485 | if (!Fits<VirtualRegister, size>::check(value)) |
22486 | value = func(); |
22487 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
22488 | *stream = Fits<VirtualRegister, size>::convert(value); |
22489 | } |
22490 | |
22491 | template<typename Functor> |
22492 | void setEnumerator(VirtualRegister value, Functor func) |
22493 | { |
22494 | if (isWide()) |
22495 | setEnumerator<OpcodeSize::Wide>(value, func); |
22496 | else |
22497 | setEnumerator<OpcodeSize::Narrow>(value, func); |
22498 | } |
22499 | |
22500 | template <OpcodeSize size, typename Functor> |
22501 | void setEnumerator(VirtualRegister value, Functor func) |
22502 | { |
22503 | if (!Fits<VirtualRegister, size>::check(value)) |
22504 | value = func(); |
22505 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
22506 | *stream = Fits<VirtualRegister, size>::convert(value); |
22507 | } |
22508 | |
22509 | template<typename Functor> |
22510 | void setIndex(VirtualRegister value, Functor func) |
22511 | { |
22512 | if (isWide()) |
22513 | setIndex<OpcodeSize::Wide>(value, func); |
22514 | else |
22515 | setIndex<OpcodeSize::Narrow>(value, func); |
22516 | } |
22517 | |
22518 | template <OpcodeSize size, typename Functor> |
22519 | void setIndex(VirtualRegister value, Functor func) |
22520 | { |
22521 | if (!Fits<VirtualRegister, size>::check(value)) |
22522 | value = func(); |
22523 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
22524 | *stream = Fits<VirtualRegister, size>::convert(value); |
22525 | } |
22526 | |
22527 | VirtualRegister m_dst; |
22528 | VirtualRegister m_enumerator; |
22529 | VirtualRegister m_index; |
22530 | }; |
22531 | |
22532 | struct OpToIndexString : public Instruction { |
22533 | static constexpr OpcodeID opcodeID = op_to_index_string; |
22534 | |
22535 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index) |
22536 | { |
22537 | |
22538 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, index) |
22539 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, index); |
22540 | } |
22541 | |
22542 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
22543 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index) |
22544 | { |
22545 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, index); |
22546 | if (shouldAssert == Assert) |
22547 | ASSERT(didEmit); |
22548 | return didEmit; |
22549 | } |
22550 | |
22551 | private: |
22552 | template<OpcodeSize size, bool recordOpcode> |
22553 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index) |
22554 | { |
22555 | if (size == OpcodeSize::Wide) |
22556 | gen->alignWideOpcode(); |
22557 | if (Fits<unsigned, size>::check(opcodeID) |
22558 | && Fits<VirtualRegister, size>::check(dst) |
22559 | && Fits<VirtualRegister, size>::check(index) |
22560 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
22561 | if (recordOpcode) |
22562 | gen->recordOpcode(opcodeID); |
22563 | if (size == OpcodeSize::Wide) |
22564 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
22565 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
22566 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
22567 | gen->write(Fits<VirtualRegister, size>::convert(index)); |
22568 | return true; |
22569 | } |
22570 | return false; |
22571 | } |
22572 | |
22573 | public: |
22574 | template<typename Block> |
22575 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
22576 | { |
22577 | dumper->printLocationAndOp(__location, &"*to_index_string" [!__isWide]); |
22578 | dumper->dumpOperand(m_dst, true); |
22579 | dumper->dumpOperand(m_index, false); |
22580 | } |
22581 | |
22582 | OpToIndexString(const uint8_t* stream) |
22583 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
22584 | , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
22585 | { |
22586 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22587 | } |
22588 | |
22589 | OpToIndexString(const uint32_t* stream) |
22590 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
22591 | , m_index(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
22592 | { |
22593 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22594 | } |
22595 | |
22596 | static OpToIndexString decode(const uint8_t* stream) |
22597 | { |
22598 | if (*stream != op_wide) |
22599 | return { stream }; |
22600 | |
22601 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
22602 | return { wideStream }; |
22603 | } |
22604 | |
22605 | template<typename Functor> |
22606 | void setDst(VirtualRegister value, Functor func) |
22607 | { |
22608 | if (isWide()) |
22609 | setDst<OpcodeSize::Wide>(value, func); |
22610 | else |
22611 | setDst<OpcodeSize::Narrow>(value, func); |
22612 | } |
22613 | |
22614 | template <OpcodeSize size, typename Functor> |
22615 | void setDst(VirtualRegister value, Functor func) |
22616 | { |
22617 | if (!Fits<VirtualRegister, size>::check(value)) |
22618 | value = func(); |
22619 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
22620 | *stream = Fits<VirtualRegister, size>::convert(value); |
22621 | } |
22622 | |
22623 | template<typename Functor> |
22624 | void setIndex(VirtualRegister value, Functor func) |
22625 | { |
22626 | if (isWide()) |
22627 | setIndex<OpcodeSize::Wide>(value, func); |
22628 | else |
22629 | setIndex<OpcodeSize::Narrow>(value, func); |
22630 | } |
22631 | |
22632 | template <OpcodeSize size, typename Functor> |
22633 | void setIndex(VirtualRegister value, Functor func) |
22634 | { |
22635 | if (!Fits<VirtualRegister, size>::check(value)) |
22636 | value = func(); |
22637 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
22638 | *stream = Fits<VirtualRegister, size>::convert(value); |
22639 | } |
22640 | |
22641 | VirtualRegister m_dst; |
22642 | VirtualRegister m_index; |
22643 | }; |
22644 | |
22645 | struct OpUnreachable : public Instruction { |
22646 | static constexpr OpcodeID opcodeID = op_unreachable; |
22647 | |
22648 | static void emit(BytecodeGenerator* gen) |
22649 | { |
22650 | |
22651 | emit<OpcodeSize::Narrow, NoAssert, true>(gen) |
22652 | || emit<OpcodeSize::Wide, Assert, true>(gen); |
22653 | } |
22654 | |
22655 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
22656 | static bool emit(BytecodeGenerator* gen) |
22657 | { |
22658 | bool didEmit = emitImpl<size, recordOpcode>(gen); |
22659 | if (shouldAssert == Assert) |
22660 | ASSERT(didEmit); |
22661 | return didEmit; |
22662 | } |
22663 | |
22664 | private: |
22665 | template<OpcodeSize size, bool recordOpcode> |
22666 | static bool emitImpl(BytecodeGenerator* gen) |
22667 | { |
22668 | if (size == OpcodeSize::Wide) |
22669 | gen->alignWideOpcode(); |
22670 | if (Fits<unsigned, size>::check(opcodeID) |
22671 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
22672 | if (recordOpcode) |
22673 | gen->recordOpcode(opcodeID); |
22674 | if (size == OpcodeSize::Wide) |
22675 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
22676 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
22677 | return true; |
22678 | } |
22679 | return false; |
22680 | } |
22681 | |
22682 | public: |
22683 | template<typename Block> |
22684 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
22685 | { |
22686 | dumper->printLocationAndOp(__location, &"*unreachable" [!__isWide]); |
22687 | |
22688 | } |
22689 | |
22690 | OpUnreachable(const uint8_t* stream) |
22691 | |
22692 | { |
22693 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22694 | } |
22695 | |
22696 | OpUnreachable(const uint32_t* stream) |
22697 | |
22698 | { |
22699 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22700 | } |
22701 | |
22702 | static OpUnreachable decode(const uint8_t* stream) |
22703 | { |
22704 | if (*stream != op_wide) |
22705 | return { stream }; |
22706 | |
22707 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
22708 | return { wideStream }; |
22709 | } |
22710 | |
22711 | |
22712 | |
22713 | }; |
22714 | |
22715 | struct OpCreateRest : public Instruction { |
22716 | static constexpr OpcodeID opcodeID = op_create_rest; |
22717 | |
22718 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arraySize, unsigned numParametersToSkip) |
22719 | { |
22720 | |
22721 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, arraySize, numParametersToSkip) |
22722 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, arraySize, numParametersToSkip); |
22723 | } |
22724 | |
22725 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
22726 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arraySize, unsigned numParametersToSkip) |
22727 | { |
22728 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, arraySize, numParametersToSkip); |
22729 | if (shouldAssert == Assert) |
22730 | ASSERT(didEmit); |
22731 | return didEmit; |
22732 | } |
22733 | |
22734 | private: |
22735 | template<OpcodeSize size, bool recordOpcode> |
22736 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arraySize, unsigned numParametersToSkip) |
22737 | { |
22738 | if (size == OpcodeSize::Wide) |
22739 | gen->alignWideOpcode(); |
22740 | if (Fits<unsigned, size>::check(opcodeID) |
22741 | && Fits<VirtualRegister, size>::check(dst) |
22742 | && Fits<VirtualRegister, size>::check(arraySize) |
22743 | && Fits<unsigned, size>::check(numParametersToSkip) |
22744 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
22745 | if (recordOpcode) |
22746 | gen->recordOpcode(opcodeID); |
22747 | if (size == OpcodeSize::Wide) |
22748 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
22749 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
22750 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
22751 | gen->write(Fits<VirtualRegister, size>::convert(arraySize)); |
22752 | gen->write(Fits<unsigned, size>::convert(numParametersToSkip)); |
22753 | return true; |
22754 | } |
22755 | return false; |
22756 | } |
22757 | |
22758 | public: |
22759 | template<typename Block> |
22760 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
22761 | { |
22762 | dumper->printLocationAndOp(__location, &"*create_rest" [!__isWide]); |
22763 | dumper->dumpOperand(m_dst, true); |
22764 | dumper->dumpOperand(m_arraySize, false); |
22765 | dumper->dumpOperand(m_numParametersToSkip, false); |
22766 | } |
22767 | |
22768 | OpCreateRest(const uint8_t* stream) |
22769 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
22770 | , m_arraySize(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
22771 | , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
22772 | { |
22773 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22774 | } |
22775 | |
22776 | OpCreateRest(const uint32_t* stream) |
22777 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
22778 | , m_arraySize(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
22779 | , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
22780 | { |
22781 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22782 | } |
22783 | |
22784 | static OpCreateRest decode(const uint8_t* stream) |
22785 | { |
22786 | if (*stream != op_wide) |
22787 | return { stream }; |
22788 | |
22789 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
22790 | return { wideStream }; |
22791 | } |
22792 | |
22793 | template<typename Functor> |
22794 | void setDst(VirtualRegister value, Functor func) |
22795 | { |
22796 | if (isWide()) |
22797 | setDst<OpcodeSize::Wide>(value, func); |
22798 | else |
22799 | setDst<OpcodeSize::Narrow>(value, func); |
22800 | } |
22801 | |
22802 | template <OpcodeSize size, typename Functor> |
22803 | void setDst(VirtualRegister value, Functor func) |
22804 | { |
22805 | if (!Fits<VirtualRegister, size>::check(value)) |
22806 | value = func(); |
22807 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
22808 | *stream = Fits<VirtualRegister, size>::convert(value); |
22809 | } |
22810 | |
22811 | template<typename Functor> |
22812 | void setArraySize(VirtualRegister value, Functor func) |
22813 | { |
22814 | if (isWide()) |
22815 | setArraySize<OpcodeSize::Wide>(value, func); |
22816 | else |
22817 | setArraySize<OpcodeSize::Narrow>(value, func); |
22818 | } |
22819 | |
22820 | template <OpcodeSize size, typename Functor> |
22821 | void setArraySize(VirtualRegister value, Functor func) |
22822 | { |
22823 | if (!Fits<VirtualRegister, size>::check(value)) |
22824 | value = func(); |
22825 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
22826 | *stream = Fits<VirtualRegister, size>::convert(value); |
22827 | } |
22828 | |
22829 | template<typename Functor> |
22830 | void setNumParametersToSkip(unsigned value, Functor func) |
22831 | { |
22832 | if (isWide()) |
22833 | setNumParametersToSkip<OpcodeSize::Wide>(value, func); |
22834 | else |
22835 | setNumParametersToSkip<OpcodeSize::Narrow>(value, func); |
22836 | } |
22837 | |
22838 | template <OpcodeSize size, typename Functor> |
22839 | void setNumParametersToSkip(unsigned value, Functor func) |
22840 | { |
22841 | if (!Fits<unsigned, size>::check(value)) |
22842 | value = func(); |
22843 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
22844 | *stream = Fits<unsigned, size>::convert(value); |
22845 | } |
22846 | |
22847 | VirtualRegister m_dst; |
22848 | VirtualRegister m_arraySize; |
22849 | unsigned m_numParametersToSkip; |
22850 | }; |
22851 | |
22852 | struct OpGetRestLength : public Instruction { |
22853 | static constexpr OpcodeID opcodeID = op_get_rest_length; |
22854 | |
22855 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned numParametersToSkip) |
22856 | { |
22857 | |
22858 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, numParametersToSkip) |
22859 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, numParametersToSkip); |
22860 | } |
22861 | |
22862 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
22863 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned numParametersToSkip) |
22864 | { |
22865 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, numParametersToSkip); |
22866 | if (shouldAssert == Assert) |
22867 | ASSERT(didEmit); |
22868 | return didEmit; |
22869 | } |
22870 | |
22871 | private: |
22872 | template<OpcodeSize size, bool recordOpcode> |
22873 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, unsigned numParametersToSkip) |
22874 | { |
22875 | if (size == OpcodeSize::Wide) |
22876 | gen->alignWideOpcode(); |
22877 | if (Fits<unsigned, size>::check(opcodeID) |
22878 | && Fits<VirtualRegister, size>::check(dst) |
22879 | && Fits<unsigned, size>::check(numParametersToSkip) |
22880 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
22881 | if (recordOpcode) |
22882 | gen->recordOpcode(opcodeID); |
22883 | if (size == OpcodeSize::Wide) |
22884 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
22885 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
22886 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
22887 | gen->write(Fits<unsigned, size>::convert(numParametersToSkip)); |
22888 | return true; |
22889 | } |
22890 | return false; |
22891 | } |
22892 | |
22893 | public: |
22894 | template<typename Block> |
22895 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
22896 | { |
22897 | dumper->printLocationAndOp(__location, &"*get_rest_length" [!__isWide]); |
22898 | dumper->dumpOperand(m_dst, true); |
22899 | dumper->dumpOperand(m_numParametersToSkip, false); |
22900 | } |
22901 | |
22902 | OpGetRestLength(const uint8_t* stream) |
22903 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
22904 | , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2])) |
22905 | { |
22906 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22907 | } |
22908 | |
22909 | OpGetRestLength(const uint32_t* stream) |
22910 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
22911 | , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide>::convert(stream[2])) |
22912 | { |
22913 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
22914 | } |
22915 | |
22916 | static OpGetRestLength decode(const uint8_t* stream) |
22917 | { |
22918 | if (*stream != op_wide) |
22919 | return { stream }; |
22920 | |
22921 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
22922 | return { wideStream }; |
22923 | } |
22924 | |
22925 | template<typename Functor> |
22926 | void setDst(VirtualRegister value, Functor func) |
22927 | { |
22928 | if (isWide()) |
22929 | setDst<OpcodeSize::Wide>(value, func); |
22930 | else |
22931 | setDst<OpcodeSize::Narrow>(value, func); |
22932 | } |
22933 | |
22934 | template <OpcodeSize size, typename Functor> |
22935 | void setDst(VirtualRegister value, Functor func) |
22936 | { |
22937 | if (!Fits<VirtualRegister, size>::check(value)) |
22938 | value = func(); |
22939 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
22940 | *stream = Fits<VirtualRegister, size>::convert(value); |
22941 | } |
22942 | |
22943 | template<typename Functor> |
22944 | void setNumParametersToSkip(unsigned value, Functor func) |
22945 | { |
22946 | if (isWide()) |
22947 | setNumParametersToSkip<OpcodeSize::Wide>(value, func); |
22948 | else |
22949 | setNumParametersToSkip<OpcodeSize::Narrow>(value, func); |
22950 | } |
22951 | |
22952 | template <OpcodeSize size, typename Functor> |
22953 | void setNumParametersToSkip(unsigned value, Functor func) |
22954 | { |
22955 | if (!Fits<unsigned, size>::check(value)) |
22956 | value = func(); |
22957 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
22958 | *stream = Fits<unsigned, size>::convert(value); |
22959 | } |
22960 | |
22961 | VirtualRegister m_dst; |
22962 | unsigned m_numParametersToSkip; |
22963 | }; |
22964 | |
22965 | struct OpYield : public Instruction { |
22966 | static constexpr OpcodeID opcodeID = op_yield; |
22967 | |
22968 | static void emit(BytecodeGenerator* gen, VirtualRegister generator, unsigned yieldPoint, VirtualRegister argument) |
22969 | { |
22970 | |
22971 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, generator, yieldPoint, argument) |
22972 | || emit<OpcodeSize::Wide, Assert, true>(gen, generator, yieldPoint, argument); |
22973 | } |
22974 | |
22975 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
22976 | static bool emit(BytecodeGenerator* gen, VirtualRegister generator, unsigned yieldPoint, VirtualRegister argument) |
22977 | { |
22978 | bool didEmit = emitImpl<size, recordOpcode>(gen, generator, yieldPoint, argument); |
22979 | if (shouldAssert == Assert) |
22980 | ASSERT(didEmit); |
22981 | return didEmit; |
22982 | } |
22983 | |
22984 | private: |
22985 | template<OpcodeSize size, bool recordOpcode> |
22986 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister generator, unsigned yieldPoint, VirtualRegister argument) |
22987 | { |
22988 | if (size == OpcodeSize::Wide) |
22989 | gen->alignWideOpcode(); |
22990 | if (Fits<unsigned, size>::check(opcodeID) |
22991 | && Fits<VirtualRegister, size>::check(generator) |
22992 | && Fits<unsigned, size>::check(yieldPoint) |
22993 | && Fits<VirtualRegister, size>::check(argument) |
22994 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
22995 | if (recordOpcode) |
22996 | gen->recordOpcode(opcodeID); |
22997 | if (size == OpcodeSize::Wide) |
22998 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
22999 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
23000 | gen->write(Fits<VirtualRegister, size>::convert(generator)); |
23001 | gen->write(Fits<unsigned, size>::convert(yieldPoint)); |
23002 | gen->write(Fits<VirtualRegister, size>::convert(argument)); |
23003 | return true; |
23004 | } |
23005 | return false; |
23006 | } |
23007 | |
23008 | public: |
23009 | template<typename Block> |
23010 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
23011 | { |
23012 | dumper->printLocationAndOp(__location, &"*yield" [!__isWide]); |
23013 | dumper->dumpOperand(m_generator, true); |
23014 | dumper->dumpOperand(m_yieldPoint, false); |
23015 | dumper->dumpOperand(m_argument, false); |
23016 | } |
23017 | |
23018 | OpYield(const uint8_t* stream) |
23019 | : m_generator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
23020 | , m_yieldPoint(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2])) |
23021 | , m_argument(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3])) |
23022 | { |
23023 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23024 | } |
23025 | |
23026 | OpYield(const uint32_t* stream) |
23027 | : m_generator(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
23028 | , m_yieldPoint(Fits<unsigned, OpcodeSize::Wide>::convert(stream[2])) |
23029 | , m_argument(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[3])) |
23030 | { |
23031 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23032 | } |
23033 | |
23034 | static OpYield decode(const uint8_t* stream) |
23035 | { |
23036 | if (*stream != op_wide) |
23037 | return { stream }; |
23038 | |
23039 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
23040 | return { wideStream }; |
23041 | } |
23042 | |
23043 | template<typename Functor> |
23044 | void setGenerator(VirtualRegister value, Functor func) |
23045 | { |
23046 | if (isWide()) |
23047 | setGenerator<OpcodeSize::Wide>(value, func); |
23048 | else |
23049 | setGenerator<OpcodeSize::Narrow>(value, func); |
23050 | } |
23051 | |
23052 | template <OpcodeSize size, typename Functor> |
23053 | void setGenerator(VirtualRegister value, Functor func) |
23054 | { |
23055 | if (!Fits<VirtualRegister, size>::check(value)) |
23056 | value = func(); |
23057 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
23058 | *stream = Fits<VirtualRegister, size>::convert(value); |
23059 | } |
23060 | |
23061 | template<typename Functor> |
23062 | void setYieldPoint(unsigned value, Functor func) |
23063 | { |
23064 | if (isWide()) |
23065 | setYieldPoint<OpcodeSize::Wide>(value, func); |
23066 | else |
23067 | setYieldPoint<OpcodeSize::Narrow>(value, func); |
23068 | } |
23069 | |
23070 | template <OpcodeSize size, typename Functor> |
23071 | void setYieldPoint(unsigned value, Functor func) |
23072 | { |
23073 | if (!Fits<unsigned, size>::check(value)) |
23074 | value = func(); |
23075 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
23076 | *stream = Fits<unsigned, size>::convert(value); |
23077 | } |
23078 | |
23079 | template<typename Functor> |
23080 | void setArgument(VirtualRegister value, Functor func) |
23081 | { |
23082 | if (isWide()) |
23083 | setArgument<OpcodeSize::Wide>(value, func); |
23084 | else |
23085 | setArgument<OpcodeSize::Narrow>(value, func); |
23086 | } |
23087 | |
23088 | template <OpcodeSize size, typename Functor> |
23089 | void setArgument(VirtualRegister value, Functor func) |
23090 | { |
23091 | if (!Fits<VirtualRegister, size>::check(value)) |
23092 | value = func(); |
23093 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
23094 | *stream = Fits<VirtualRegister, size>::convert(value); |
23095 | } |
23096 | |
23097 | VirtualRegister m_generator; |
23098 | unsigned m_yieldPoint; |
23099 | VirtualRegister m_argument; |
23100 | }; |
23101 | |
23102 | struct OpCheckTraps : public Instruction { |
23103 | static constexpr OpcodeID opcodeID = op_check_traps; |
23104 | |
23105 | static void emit(BytecodeGenerator* gen) |
23106 | { |
23107 | |
23108 | emit<OpcodeSize::Narrow, NoAssert, true>(gen) |
23109 | || emit<OpcodeSize::Wide, Assert, true>(gen); |
23110 | } |
23111 | |
23112 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
23113 | static bool emit(BytecodeGenerator* gen) |
23114 | { |
23115 | bool didEmit = emitImpl<size, recordOpcode>(gen); |
23116 | if (shouldAssert == Assert) |
23117 | ASSERT(didEmit); |
23118 | return didEmit; |
23119 | } |
23120 | |
23121 | private: |
23122 | template<OpcodeSize size, bool recordOpcode> |
23123 | static bool emitImpl(BytecodeGenerator* gen) |
23124 | { |
23125 | if (size == OpcodeSize::Wide) |
23126 | gen->alignWideOpcode(); |
23127 | if (Fits<unsigned, size>::check(opcodeID) |
23128 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
23129 | if (recordOpcode) |
23130 | gen->recordOpcode(opcodeID); |
23131 | if (size == OpcodeSize::Wide) |
23132 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
23133 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
23134 | return true; |
23135 | } |
23136 | return false; |
23137 | } |
23138 | |
23139 | public: |
23140 | template<typename Block> |
23141 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
23142 | { |
23143 | dumper->printLocationAndOp(__location, &"*check_traps" [!__isWide]); |
23144 | |
23145 | } |
23146 | |
23147 | OpCheckTraps(const uint8_t* stream) |
23148 | |
23149 | { |
23150 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23151 | } |
23152 | |
23153 | OpCheckTraps(const uint32_t* stream) |
23154 | |
23155 | { |
23156 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23157 | } |
23158 | |
23159 | static OpCheckTraps decode(const uint8_t* stream) |
23160 | { |
23161 | if (*stream != op_wide) |
23162 | return { stream }; |
23163 | |
23164 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
23165 | return { wideStream }; |
23166 | } |
23167 | |
23168 | |
23169 | |
23170 | }; |
23171 | |
23172 | struct OpLogShadowChickenPrologue : public Instruction { |
23173 | static constexpr OpcodeID opcodeID = op_log_shadow_chicken_prologue; |
23174 | |
23175 | static void emit(BytecodeGenerator* gen, VirtualRegister scope) |
23176 | { |
23177 | |
23178 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, scope) |
23179 | || emit<OpcodeSize::Wide, Assert, true>(gen, scope); |
23180 | } |
23181 | |
23182 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
23183 | static bool emit(BytecodeGenerator* gen, VirtualRegister scope) |
23184 | { |
23185 | bool didEmit = emitImpl<size, recordOpcode>(gen, scope); |
23186 | if (shouldAssert == Assert) |
23187 | ASSERT(didEmit); |
23188 | return didEmit; |
23189 | } |
23190 | |
23191 | private: |
23192 | template<OpcodeSize size, bool recordOpcode> |
23193 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister scope) |
23194 | { |
23195 | if (size == OpcodeSize::Wide) |
23196 | gen->alignWideOpcode(); |
23197 | if (Fits<unsigned, size>::check(opcodeID) |
23198 | && Fits<VirtualRegister, size>::check(scope) |
23199 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
23200 | if (recordOpcode) |
23201 | gen->recordOpcode(opcodeID); |
23202 | if (size == OpcodeSize::Wide) |
23203 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
23204 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
23205 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
23206 | return true; |
23207 | } |
23208 | return false; |
23209 | } |
23210 | |
23211 | public: |
23212 | template<typename Block> |
23213 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
23214 | { |
23215 | dumper->printLocationAndOp(__location, &"*log_shadow_chicken_prologue" [!__isWide]); |
23216 | dumper->dumpOperand(m_scope, true); |
23217 | } |
23218 | |
23219 | OpLogShadowChickenPrologue(const uint8_t* stream) |
23220 | : m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
23221 | { |
23222 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23223 | } |
23224 | |
23225 | OpLogShadowChickenPrologue(const uint32_t* stream) |
23226 | : m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
23227 | { |
23228 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23229 | } |
23230 | |
23231 | static OpLogShadowChickenPrologue decode(const uint8_t* stream) |
23232 | { |
23233 | if (*stream != op_wide) |
23234 | return { stream }; |
23235 | |
23236 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
23237 | return { wideStream }; |
23238 | } |
23239 | |
23240 | template<typename Functor> |
23241 | void setScope(VirtualRegister value, Functor func) |
23242 | { |
23243 | if (isWide()) |
23244 | setScope<OpcodeSize::Wide>(value, func); |
23245 | else |
23246 | setScope<OpcodeSize::Narrow>(value, func); |
23247 | } |
23248 | |
23249 | template <OpcodeSize size, typename Functor> |
23250 | void setScope(VirtualRegister value, Functor func) |
23251 | { |
23252 | if (!Fits<VirtualRegister, size>::check(value)) |
23253 | value = func(); |
23254 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
23255 | *stream = Fits<VirtualRegister, size>::convert(value); |
23256 | } |
23257 | |
23258 | VirtualRegister m_scope; |
23259 | }; |
23260 | |
23261 | struct OpLogShadowChickenTail : public Instruction { |
23262 | static constexpr OpcodeID opcodeID = op_log_shadow_chicken_tail; |
23263 | |
23264 | static void emit(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope) |
23265 | { |
23266 | |
23267 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, thisValue, scope) |
23268 | || emit<OpcodeSize::Wide, Assert, true>(gen, thisValue, scope); |
23269 | } |
23270 | |
23271 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
23272 | static bool emit(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope) |
23273 | { |
23274 | bool didEmit = emitImpl<size, recordOpcode>(gen, thisValue, scope); |
23275 | if (shouldAssert == Assert) |
23276 | ASSERT(didEmit); |
23277 | return didEmit; |
23278 | } |
23279 | |
23280 | private: |
23281 | template<OpcodeSize size, bool recordOpcode> |
23282 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope) |
23283 | { |
23284 | if (size == OpcodeSize::Wide) |
23285 | gen->alignWideOpcode(); |
23286 | if (Fits<unsigned, size>::check(opcodeID) |
23287 | && Fits<VirtualRegister, size>::check(thisValue) |
23288 | && Fits<VirtualRegister, size>::check(scope) |
23289 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
23290 | if (recordOpcode) |
23291 | gen->recordOpcode(opcodeID); |
23292 | if (size == OpcodeSize::Wide) |
23293 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
23294 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
23295 | gen->write(Fits<VirtualRegister, size>::convert(thisValue)); |
23296 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
23297 | return true; |
23298 | } |
23299 | return false; |
23300 | } |
23301 | |
23302 | public: |
23303 | template<typename Block> |
23304 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
23305 | { |
23306 | dumper->printLocationAndOp(__location, &"*log_shadow_chicken_tail" [!__isWide]); |
23307 | dumper->dumpOperand(m_thisValue, true); |
23308 | dumper->dumpOperand(m_scope, false); |
23309 | } |
23310 | |
23311 | OpLogShadowChickenTail(const uint8_t* stream) |
23312 | : m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
23313 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
23314 | { |
23315 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23316 | } |
23317 | |
23318 | OpLogShadowChickenTail(const uint32_t* stream) |
23319 | : m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
23320 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
23321 | { |
23322 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23323 | } |
23324 | |
23325 | static OpLogShadowChickenTail decode(const uint8_t* stream) |
23326 | { |
23327 | if (*stream != op_wide) |
23328 | return { stream }; |
23329 | |
23330 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
23331 | return { wideStream }; |
23332 | } |
23333 | |
23334 | template<typename Functor> |
23335 | void setThisValue(VirtualRegister value, Functor func) |
23336 | { |
23337 | if (isWide()) |
23338 | setThisValue<OpcodeSize::Wide>(value, func); |
23339 | else |
23340 | setThisValue<OpcodeSize::Narrow>(value, func); |
23341 | } |
23342 | |
23343 | template <OpcodeSize size, typename Functor> |
23344 | void setThisValue(VirtualRegister value, Functor func) |
23345 | { |
23346 | if (!Fits<VirtualRegister, size>::check(value)) |
23347 | value = func(); |
23348 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
23349 | *stream = Fits<VirtualRegister, size>::convert(value); |
23350 | } |
23351 | |
23352 | template<typename Functor> |
23353 | void setScope(VirtualRegister value, Functor func) |
23354 | { |
23355 | if (isWide()) |
23356 | setScope<OpcodeSize::Wide>(value, func); |
23357 | else |
23358 | setScope<OpcodeSize::Narrow>(value, func); |
23359 | } |
23360 | |
23361 | template <OpcodeSize size, typename Functor> |
23362 | void setScope(VirtualRegister value, Functor func) |
23363 | { |
23364 | if (!Fits<VirtualRegister, size>::check(value)) |
23365 | value = func(); |
23366 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
23367 | *stream = Fits<VirtualRegister, size>::convert(value); |
23368 | } |
23369 | |
23370 | VirtualRegister m_thisValue; |
23371 | VirtualRegister m_scope; |
23372 | }; |
23373 | |
23374 | struct OpResolveScopeForHoistingFuncDeclInEval : public Instruction { |
23375 | static constexpr OpcodeID opcodeID = op_resolve_scope_for_hoisting_func_decl_in_eval; |
23376 | |
23377 | static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned property) |
23378 | { |
23379 | |
23380 | emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, property) |
23381 | || emit<OpcodeSize::Wide, Assert, true>(gen, dst, scope, property); |
23382 | } |
23383 | |
23384 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
23385 | static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned property) |
23386 | { |
23387 | bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, property); |
23388 | if (shouldAssert == Assert) |
23389 | ASSERT(didEmit); |
23390 | return didEmit; |
23391 | } |
23392 | |
23393 | private: |
23394 | template<OpcodeSize size, bool recordOpcode> |
23395 | static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned property) |
23396 | { |
23397 | if (size == OpcodeSize::Wide) |
23398 | gen->alignWideOpcode(); |
23399 | if (Fits<unsigned, size>::check(opcodeID) |
23400 | && Fits<VirtualRegister, size>::check(dst) |
23401 | && Fits<VirtualRegister, size>::check(scope) |
23402 | && Fits<unsigned, size>::check(property) |
23403 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
23404 | if (recordOpcode) |
23405 | gen->recordOpcode(opcodeID); |
23406 | if (size == OpcodeSize::Wide) |
23407 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
23408 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
23409 | gen->write(Fits<VirtualRegister, size>::convert(dst)); |
23410 | gen->write(Fits<VirtualRegister, size>::convert(scope)); |
23411 | gen->write(Fits<unsigned, size>::convert(property)); |
23412 | return true; |
23413 | } |
23414 | return false; |
23415 | } |
23416 | |
23417 | public: |
23418 | template<typename Block> |
23419 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
23420 | { |
23421 | dumper->printLocationAndOp(__location, &"*resolve_scope_for_hoisting_func_decl_in_eval" [!__isWide]); |
23422 | dumper->dumpOperand(m_dst, true); |
23423 | dumper->dumpOperand(m_scope, false); |
23424 | dumper->dumpOperand(m_property, false); |
23425 | } |
23426 | |
23427 | OpResolveScopeForHoistingFuncDeclInEval(const uint8_t* stream) |
23428 | : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1])) |
23429 | , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2])) |
23430 | , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3])) |
23431 | { |
23432 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23433 | } |
23434 | |
23435 | OpResolveScopeForHoistingFuncDeclInEval(const uint32_t* stream) |
23436 | : m_dst(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[1])) |
23437 | , m_scope(Fits<VirtualRegister, OpcodeSize::Wide>::convert(stream[2])) |
23438 | , m_property(Fits<unsigned, OpcodeSize::Wide>::convert(stream[3])) |
23439 | { |
23440 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23441 | } |
23442 | |
23443 | static OpResolveScopeForHoistingFuncDeclInEval decode(const uint8_t* stream) |
23444 | { |
23445 | if (*stream != op_wide) |
23446 | return { stream }; |
23447 | |
23448 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
23449 | return { wideStream }; |
23450 | } |
23451 | |
23452 | template<typename Functor> |
23453 | void setDst(VirtualRegister value, Functor func) |
23454 | { |
23455 | if (isWide()) |
23456 | setDst<OpcodeSize::Wide>(value, func); |
23457 | else |
23458 | setDst<OpcodeSize::Narrow>(value, func); |
23459 | } |
23460 | |
23461 | template <OpcodeSize size, typename Functor> |
23462 | void setDst(VirtualRegister value, Functor func) |
23463 | { |
23464 | if (!Fits<VirtualRegister, size>::check(value)) |
23465 | value = func(); |
23466 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value); |
23467 | *stream = Fits<VirtualRegister, size>::convert(value); |
23468 | } |
23469 | |
23470 | template<typename Functor> |
23471 | void setScope(VirtualRegister value, Functor func) |
23472 | { |
23473 | if (isWide()) |
23474 | setScope<OpcodeSize::Wide>(value, func); |
23475 | else |
23476 | setScope<OpcodeSize::Narrow>(value, func); |
23477 | } |
23478 | |
23479 | template <OpcodeSize size, typename Functor> |
23480 | void setScope(VirtualRegister value, Functor func) |
23481 | { |
23482 | if (!Fits<VirtualRegister, size>::check(value)) |
23483 | value = func(); |
23484 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value); |
23485 | *stream = Fits<VirtualRegister, size>::convert(value); |
23486 | } |
23487 | |
23488 | template<typename Functor> |
23489 | void setProperty(unsigned value, Functor func) |
23490 | { |
23491 | if (isWide()) |
23492 | setProperty<OpcodeSize::Wide>(value, func); |
23493 | else |
23494 | setProperty<OpcodeSize::Narrow>(value, func); |
23495 | } |
23496 | |
23497 | template <OpcodeSize size, typename Functor> |
23498 | void setProperty(unsigned value, Functor func) |
23499 | { |
23500 | if (!Fits<unsigned, size>::check(value)) |
23501 | value = func(); |
23502 | auto* stream = bitwise_cast<typename TypeBySize<size>::type*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value); |
23503 | *stream = Fits<unsigned, size>::convert(value); |
23504 | } |
23505 | |
23506 | VirtualRegister m_dst; |
23507 | VirtualRegister m_scope; |
23508 | unsigned m_property; |
23509 | }; |
23510 | |
23511 | struct OpNop : public Instruction { |
23512 | static constexpr OpcodeID opcodeID = op_nop; |
23513 | |
23514 | static void emit(BytecodeGenerator* gen) |
23515 | { |
23516 | |
23517 | emit<OpcodeSize::Narrow, NoAssert, true>(gen) |
23518 | || emit<OpcodeSize::Wide, Assert, true>(gen); |
23519 | } |
23520 | |
23521 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
23522 | static bool emit(BytecodeGenerator* gen) |
23523 | { |
23524 | bool didEmit = emitImpl<size, recordOpcode>(gen); |
23525 | if (shouldAssert == Assert) |
23526 | ASSERT(didEmit); |
23527 | return didEmit; |
23528 | } |
23529 | |
23530 | private: |
23531 | template<OpcodeSize size, bool recordOpcode> |
23532 | static bool emitImpl(BytecodeGenerator* gen) |
23533 | { |
23534 | if (size == OpcodeSize::Wide) |
23535 | gen->alignWideOpcode(); |
23536 | if (Fits<unsigned, size>::check(opcodeID) |
23537 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
23538 | if (recordOpcode) |
23539 | gen->recordOpcode(opcodeID); |
23540 | if (size == OpcodeSize::Wide) |
23541 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
23542 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
23543 | return true; |
23544 | } |
23545 | return false; |
23546 | } |
23547 | |
23548 | public: |
23549 | template<typename Block> |
23550 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
23551 | { |
23552 | dumper->printLocationAndOp(__location, &"*nop" [!__isWide]); |
23553 | |
23554 | } |
23555 | |
23556 | OpNop(const uint8_t* stream) |
23557 | |
23558 | { |
23559 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23560 | } |
23561 | |
23562 | OpNop(const uint32_t* stream) |
23563 | |
23564 | { |
23565 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23566 | } |
23567 | |
23568 | static OpNop decode(const uint8_t* stream) |
23569 | { |
23570 | if (*stream != op_wide) |
23571 | return { stream }; |
23572 | |
23573 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
23574 | return { wideStream }; |
23575 | } |
23576 | |
23577 | |
23578 | |
23579 | }; |
23580 | |
23581 | struct OpSuperSamplerBegin : public Instruction { |
23582 | static constexpr OpcodeID opcodeID = op_super_sampler_begin; |
23583 | |
23584 | static void emit(BytecodeGenerator* gen) |
23585 | { |
23586 | |
23587 | emit<OpcodeSize::Narrow, NoAssert, true>(gen) |
23588 | || emit<OpcodeSize::Wide, Assert, true>(gen); |
23589 | } |
23590 | |
23591 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
23592 | static bool emit(BytecodeGenerator* gen) |
23593 | { |
23594 | bool didEmit = emitImpl<size, recordOpcode>(gen); |
23595 | if (shouldAssert == Assert) |
23596 | ASSERT(didEmit); |
23597 | return didEmit; |
23598 | } |
23599 | |
23600 | private: |
23601 | template<OpcodeSize size, bool recordOpcode> |
23602 | static bool emitImpl(BytecodeGenerator* gen) |
23603 | { |
23604 | if (size == OpcodeSize::Wide) |
23605 | gen->alignWideOpcode(); |
23606 | if (Fits<unsigned, size>::check(opcodeID) |
23607 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
23608 | if (recordOpcode) |
23609 | gen->recordOpcode(opcodeID); |
23610 | if (size == OpcodeSize::Wide) |
23611 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
23612 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
23613 | return true; |
23614 | } |
23615 | return false; |
23616 | } |
23617 | |
23618 | public: |
23619 | template<typename Block> |
23620 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
23621 | { |
23622 | dumper->printLocationAndOp(__location, &"*super_sampler_begin" [!__isWide]); |
23623 | |
23624 | } |
23625 | |
23626 | OpSuperSamplerBegin(const uint8_t* stream) |
23627 | |
23628 | { |
23629 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23630 | } |
23631 | |
23632 | OpSuperSamplerBegin(const uint32_t* stream) |
23633 | |
23634 | { |
23635 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23636 | } |
23637 | |
23638 | static OpSuperSamplerBegin decode(const uint8_t* stream) |
23639 | { |
23640 | if (*stream != op_wide) |
23641 | return { stream }; |
23642 | |
23643 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
23644 | return { wideStream }; |
23645 | } |
23646 | |
23647 | |
23648 | |
23649 | }; |
23650 | |
23651 | struct OpSuperSamplerEnd : public Instruction { |
23652 | static constexpr OpcodeID opcodeID = op_super_sampler_end; |
23653 | |
23654 | static void emit(BytecodeGenerator* gen) |
23655 | { |
23656 | |
23657 | emit<OpcodeSize::Narrow, NoAssert, true>(gen) |
23658 | || emit<OpcodeSize::Wide, Assert, true>(gen); |
23659 | } |
23660 | |
23661 | template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true> |
23662 | static bool emit(BytecodeGenerator* gen) |
23663 | { |
23664 | bool didEmit = emitImpl<size, recordOpcode>(gen); |
23665 | if (shouldAssert == Assert) |
23666 | ASSERT(didEmit); |
23667 | return didEmit; |
23668 | } |
23669 | |
23670 | private: |
23671 | template<OpcodeSize size, bool recordOpcode> |
23672 | static bool emitImpl(BytecodeGenerator* gen) |
23673 | { |
23674 | if (size == OpcodeSize::Wide) |
23675 | gen->alignWideOpcode(); |
23676 | if (Fits<unsigned, size>::check(opcodeID) |
23677 | && (size == OpcodeSize::Wide ? Fits<unsigned, OpcodeSize::Narrow>::check(op_wide) : true)) { |
23678 | if (recordOpcode) |
23679 | gen->recordOpcode(opcodeID); |
23680 | if (size == OpcodeSize::Wide) |
23681 | gen->write(Fits<unsigned, OpcodeSize::Narrow>::convert(op_wide)); |
23682 | gen->write(Fits<unsigned, size>::convert(opcodeID)); |
23683 | return true; |
23684 | } |
23685 | return false; |
23686 | } |
23687 | |
23688 | public: |
23689 | template<typename Block> |
23690 | void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, bool __isWide) |
23691 | { |
23692 | dumper->printLocationAndOp(__location, &"*super_sampler_end" [!__isWide]); |
23693 | |
23694 | } |
23695 | |
23696 | OpSuperSamplerEnd(const uint8_t* stream) |
23697 | |
23698 | { |
23699 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23700 | } |
23701 | |
23702 | OpSuperSamplerEnd(const uint32_t* stream) |
23703 | |
23704 | { |
23705 | ASSERT_UNUSED(stream, stream[0] == opcodeID); |
23706 | } |
23707 | |
23708 | static OpSuperSamplerEnd decode(const uint8_t* stream) |
23709 | { |
23710 | if (*stream != op_wide) |
23711 | return { stream }; |
23712 | |
23713 | auto wideStream = bitwise_cast<const uint32_t*>(stream + 1); |
23714 | return { wideStream }; |
23715 | } |
23716 | |
23717 | |
23718 | |
23719 | }; |
23720 | |
23721 | template<typename Block> |
23722 | static void dumpBytecode(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, const Instruction* __instruction) |
23723 | { |
23724 | switch (__instruction->opcodeID()) { |
23725 | case op_create_this: |
23726 | __instruction->as<OpCreateThis>().dump(dumper, __location, __instruction->isWide()); |
23727 | break; |
23728 | case op_get_argument: |
23729 | __instruction->as<OpGetArgument>().dump(dumper, __location, __instruction->isWide()); |
23730 | break; |
23731 | case op_to_this: |
23732 | __instruction->as<OpToThis>().dump(dumper, __location, __instruction->isWide()); |
23733 | break; |
23734 | case op_new_object: |
23735 | __instruction->as<OpNewObject>().dump(dumper, __location, __instruction->isWide()); |
23736 | break; |
23737 | case op_new_array: |
23738 | __instruction->as<OpNewArray>().dump(dumper, __location, __instruction->isWide()); |
23739 | break; |
23740 | case op_new_array_with_size: |
23741 | __instruction->as<OpNewArrayWithSize>().dump(dumper, __location, __instruction->isWide()); |
23742 | break; |
23743 | case op_new_array_buffer: |
23744 | __instruction->as<OpNewArrayBuffer>().dump(dumper, __location, __instruction->isWide()); |
23745 | break; |
23746 | case op_add: |
23747 | __instruction->as<OpAdd>().dump(dumper, __location, __instruction->isWide()); |
23748 | break; |
23749 | case op_mul: |
23750 | __instruction->as<OpMul>().dump(dumper, __location, __instruction->isWide()); |
23751 | break; |
23752 | case op_div: |
23753 | __instruction->as<OpDiv>().dump(dumper, __location, __instruction->isWide()); |
23754 | break; |
23755 | case op_sub: |
23756 | __instruction->as<OpSub>().dump(dumper, __location, __instruction->isWide()); |
23757 | break; |
23758 | case op_bitand: |
23759 | __instruction->as<OpBitand>().dump(dumper, __location, __instruction->isWide()); |
23760 | break; |
23761 | case op_bitor: |
23762 | __instruction->as<OpBitor>().dump(dumper, __location, __instruction->isWide()); |
23763 | break; |
23764 | case op_bitxor: |
23765 | __instruction->as<OpBitxor>().dump(dumper, __location, __instruction->isWide()); |
23766 | break; |
23767 | case op_bitnot: |
23768 | __instruction->as<OpBitnot>().dump(dumper, __location, __instruction->isWide()); |
23769 | break; |
23770 | case op_to_object: |
23771 | __instruction->as<OpToObject>().dump(dumper, __location, __instruction->isWide()); |
23772 | break; |
23773 | case op_to_number: |
23774 | __instruction->as<OpToNumber>().dump(dumper, __location, __instruction->isWide()); |
23775 | break; |
23776 | case op_negate: |
23777 | __instruction->as<OpNegate>().dump(dumper, __location, __instruction->isWide()); |
23778 | break; |
23779 | case op_in_by_val: |
23780 | __instruction->as<OpInByVal>().dump(dumper, __location, __instruction->isWide()); |
23781 | break; |
23782 | case op_get_by_id: |
23783 | __instruction->as<OpGetById>().dump(dumper, __location, __instruction->isWide()); |
23784 | break; |
23785 | case op_get_by_id_with_this: |
23786 | __instruction->as<OpGetByIdWithThis>().dump(dumper, __location, __instruction->isWide()); |
23787 | break; |
23788 | case op_get_by_val_with_this: |
23789 | __instruction->as<OpGetByValWithThis>().dump(dumper, __location, __instruction->isWide()); |
23790 | break; |
23791 | case op_get_by_id_direct: |
23792 | __instruction->as<OpGetByIdDirect>().dump(dumper, __location, __instruction->isWide()); |
23793 | break; |
23794 | case op_try_get_by_id: |
23795 | __instruction->as<OpTryGetById>().dump(dumper, __location, __instruction->isWide()); |
23796 | break; |
23797 | case op_put_by_id: |
23798 | __instruction->as<OpPutById>().dump(dumper, __location, __instruction->isWide()); |
23799 | break; |
23800 | case op_get_by_val: |
23801 | __instruction->as<OpGetByVal>().dump(dumper, __location, __instruction->isWide()); |
23802 | break; |
23803 | case op_put_by_val: |
23804 | __instruction->as<OpPutByVal>().dump(dumper, __location, __instruction->isWide()); |
23805 | break; |
23806 | case op_put_by_val_direct: |
23807 | __instruction->as<OpPutByValDirect>().dump(dumper, __location, __instruction->isWide()); |
23808 | break; |
23809 | case op_jneq_ptr: |
23810 | __instruction->as<OpJneqPtr>().dump(dumper, __location, __instruction->isWide()); |
23811 | break; |
23812 | case op_call: |
23813 | __instruction->as<OpCall>().dump(dumper, __location, __instruction->isWide()); |
23814 | break; |
23815 | case op_tail_call: |
23816 | __instruction->as<OpTailCall>().dump(dumper, __location, __instruction->isWide()); |
23817 | break; |
23818 | case op_call_eval: |
23819 | __instruction->as<OpCallEval>().dump(dumper, __location, __instruction->isWide()); |
23820 | break; |
23821 | case op_call_varargs: |
23822 | __instruction->as<OpCallVarargs>().dump(dumper, __location, __instruction->isWide()); |
23823 | break; |
23824 | case op_tail_call_varargs: |
23825 | __instruction->as<OpTailCallVarargs>().dump(dumper, __location, __instruction->isWide()); |
23826 | break; |
23827 | case op_tail_call_forward_arguments: |
23828 | __instruction->as<OpTailCallForwardArguments>().dump(dumper, __location, __instruction->isWide()); |
23829 | break; |
23830 | case op_construct: |
23831 | __instruction->as<OpConstruct>().dump(dumper, __location, __instruction->isWide()); |
23832 | break; |
23833 | case op_construct_varargs: |
23834 | __instruction->as<OpConstructVarargs>().dump(dumper, __location, __instruction->isWide()); |
23835 | break; |
23836 | case op_resolve_scope: |
23837 | __instruction->as<OpResolveScope>().dump(dumper, __location, __instruction->isWide()); |
23838 | break; |
23839 | case op_get_from_scope: |
23840 | __instruction->as<OpGetFromScope>().dump(dumper, __location, __instruction->isWide()); |
23841 | break; |
23842 | case op_put_to_scope: |
23843 | __instruction->as<OpPutToScope>().dump(dumper, __location, __instruction->isWide()); |
23844 | break; |
23845 | case op_get_from_arguments: |
23846 | __instruction->as<OpGetFromArguments>().dump(dumper, __location, __instruction->isWide()); |
23847 | break; |
23848 | case op_catch: |
23849 | __instruction->as<OpCatch>().dump(dumper, __location, __instruction->isWide()); |
23850 | break; |
23851 | case op_profile_type: |
23852 | __instruction->as<OpProfileType>().dump(dumper, __location, __instruction->isWide()); |
23853 | break; |
23854 | case op_profile_control_flow: |
23855 | __instruction->as<OpProfileControlFlow>().dump(dumper, __location, __instruction->isWide()); |
23856 | break; |
23857 | case op_has_indexed_property: |
23858 | __instruction->as<OpHasIndexedProperty>().dump(dumper, __location, __instruction->isWide()); |
23859 | break; |
23860 | case op_get_direct_pname: |
23861 | __instruction->as<OpGetDirectPname>().dump(dumper, __location, __instruction->isWide()); |
23862 | break; |
23863 | case op_wide: |
23864 | __instruction->as<OpWide>().dump(dumper, __location, __instruction->isWide()); |
23865 | break; |
23866 | case op_enter: |
23867 | __instruction->as<OpEnter>().dump(dumper, __location, __instruction->isWide()); |
23868 | break; |
23869 | case op_get_scope: |
23870 | __instruction->as<OpGetScope>().dump(dumper, __location, __instruction->isWide()); |
23871 | break; |
23872 | case op_create_direct_arguments: |
23873 | __instruction->as<OpCreateDirectArguments>().dump(dumper, __location, __instruction->isWide()); |
23874 | break; |
23875 | case op_create_scoped_arguments: |
23876 | __instruction->as<OpCreateScopedArguments>().dump(dumper, __location, __instruction->isWide()); |
23877 | break; |
23878 | case op_create_cloned_arguments: |
23879 | __instruction->as<OpCreateClonedArguments>().dump(dumper, __location, __instruction->isWide()); |
23880 | break; |
23881 | case op_argument_count: |
23882 | __instruction->as<OpArgumentCount>().dump(dumper, __location, __instruction->isWide()); |
23883 | break; |
23884 | case op_check_tdz: |
23885 | __instruction->as<OpCheckTdz>().dump(dumper, __location, __instruction->isWide()); |
23886 | break; |
23887 | case op_new_array_with_spread: |
23888 | __instruction->as<OpNewArrayWithSpread>().dump(dumper, __location, __instruction->isWide()); |
23889 | break; |
23890 | case op_spread: |
23891 | __instruction->as<OpSpread>().dump(dumper, __location, __instruction->isWide()); |
23892 | break; |
23893 | case op_new_regexp: |
23894 | __instruction->as<OpNewRegexp>().dump(dumper, __location, __instruction->isWide()); |
23895 | break; |
23896 | case op_mov: |
23897 | __instruction->as<OpMov>().dump(dumper, __location, __instruction->isWide()); |
23898 | break; |
23899 | case op_eq: |
23900 | __instruction->as<OpEq>().dump(dumper, __location, __instruction->isWide()); |
23901 | break; |
23902 | case op_neq: |
23903 | __instruction->as<OpNeq>().dump(dumper, __location, __instruction->isWide()); |
23904 | break; |
23905 | case op_stricteq: |
23906 | __instruction->as<OpStricteq>().dump(dumper, __location, __instruction->isWide()); |
23907 | break; |
23908 | case op_nstricteq: |
23909 | __instruction->as<OpNstricteq>().dump(dumper, __location, __instruction->isWide()); |
23910 | break; |
23911 | case op_less: |
23912 | __instruction->as<OpLess>().dump(dumper, __location, __instruction->isWide()); |
23913 | break; |
23914 | case op_lesseq: |
23915 | __instruction->as<OpLesseq>().dump(dumper, __location, __instruction->isWide()); |
23916 | break; |
23917 | case op_greater: |
23918 | __instruction->as<OpGreater>().dump(dumper, __location, __instruction->isWide()); |
23919 | break; |
23920 | case op_greatereq: |
23921 | __instruction->as<OpGreatereq>().dump(dumper, __location, __instruction->isWide()); |
23922 | break; |
23923 | case op_below: |
23924 | __instruction->as<OpBelow>().dump(dumper, __location, __instruction->isWide()); |
23925 | break; |
23926 | case op_beloweq: |
23927 | __instruction->as<OpBeloweq>().dump(dumper, __location, __instruction->isWide()); |
23928 | break; |
23929 | case op_mod: |
23930 | __instruction->as<OpMod>().dump(dumper, __location, __instruction->isWide()); |
23931 | break; |
23932 | case op_pow: |
23933 | __instruction->as<OpPow>().dump(dumper, __location, __instruction->isWide()); |
23934 | break; |
23935 | case op_lshift: |
23936 | __instruction->as<OpLshift>().dump(dumper, __location, __instruction->isWide()); |
23937 | break; |
23938 | case op_rshift: |
23939 | __instruction->as<OpRshift>().dump(dumper, __location, __instruction->isWide()); |
23940 | break; |
23941 | case op_urshift: |
23942 | __instruction->as<OpUrshift>().dump(dumper, __location, __instruction->isWide()); |
23943 | break; |
23944 | case op_eq_null: |
23945 | __instruction->as<OpEqNull>().dump(dumper, __location, __instruction->isWide()); |
23946 | break; |
23947 | case op_neq_null: |
23948 | __instruction->as<OpNeqNull>().dump(dumper, __location, __instruction->isWide()); |
23949 | break; |
23950 | case op_to_string: |
23951 | __instruction->as<OpToString>().dump(dumper, __location, __instruction->isWide()); |
23952 | break; |
23953 | case op_unsigned: |
23954 | __instruction->as<OpUnsigned>().dump(dumper, __location, __instruction->isWide()); |
23955 | break; |
23956 | case op_is_empty: |
23957 | __instruction->as<OpIsEmpty>().dump(dumper, __location, __instruction->isWide()); |
23958 | break; |
23959 | case op_is_undefined: |
23960 | __instruction->as<OpIsUndefined>().dump(dumper, __location, __instruction->isWide()); |
23961 | break; |
23962 | case op_is_undefined_or_null: |
23963 | __instruction->as<OpIsUndefinedOrNull>().dump(dumper, __location, __instruction->isWide()); |
23964 | break; |
23965 | case op_is_boolean: |
23966 | __instruction->as<OpIsBoolean>().dump(dumper, __location, __instruction->isWide()); |
23967 | break; |
23968 | case op_is_number: |
23969 | __instruction->as<OpIsNumber>().dump(dumper, __location, __instruction->isWide()); |
23970 | break; |
23971 | case op_is_object: |
23972 | __instruction->as<OpIsObject>().dump(dumper, __location, __instruction->isWide()); |
23973 | break; |
23974 | case op_is_object_or_null: |
23975 | __instruction->as<OpIsObjectOrNull>().dump(dumper, __location, __instruction->isWide()); |
23976 | break; |
23977 | case op_is_function: |
23978 | __instruction->as<OpIsFunction>().dump(dumper, __location, __instruction->isWide()); |
23979 | break; |
23980 | case op_inc: |
23981 | __instruction->as<OpInc>().dump(dumper, __location, __instruction->isWide()); |
23982 | break; |
23983 | case op_dec: |
23984 | __instruction->as<OpDec>().dump(dumper, __location, __instruction->isWide()); |
23985 | break; |
23986 | case op_not: |
23987 | __instruction->as<OpNot>().dump(dumper, __location, __instruction->isWide()); |
23988 | break; |
23989 | case op_identity_with_profile: |
23990 | __instruction->as<OpIdentityWithProfile>().dump(dumper, __location, __instruction->isWide()); |
23991 | break; |
23992 | case op_overrides_has_instance: |
23993 | __instruction->as<OpOverridesHasInstance>().dump(dumper, __location, __instruction->isWide()); |
23994 | break; |
23995 | case op_instanceof: |
23996 | __instruction->as<OpInstanceof>().dump(dumper, __location, __instruction->isWide()); |
23997 | break; |
23998 | case op_instanceof_custom: |
23999 | __instruction->as<OpInstanceofCustom>().dump(dumper, __location, __instruction->isWide()); |
24000 | break; |
24001 | case op_typeof: |
24002 | __instruction->as<OpTypeof>().dump(dumper, __location, __instruction->isWide()); |
24003 | break; |
24004 | case op_is_cell_with_type: |
24005 | __instruction->as<OpIsCellWithType>().dump(dumper, __location, __instruction->isWide()); |
24006 | break; |
24007 | case op_in_by_id: |
24008 | __instruction->as<OpInById>().dump(dumper, __location, __instruction->isWide()); |
24009 | break; |
24010 | case op_put_by_id_with_this: |
24011 | __instruction->as<OpPutByIdWithThis>().dump(dumper, __location, __instruction->isWide()); |
24012 | break; |
24013 | case op_del_by_id: |
24014 | __instruction->as<OpDelById>().dump(dumper, __location, __instruction->isWide()); |
24015 | break; |
24016 | case op_put_by_val_with_this: |
24017 | __instruction->as<OpPutByValWithThis>().dump(dumper, __location, __instruction->isWide()); |
24018 | break; |
24019 | case op_del_by_val: |
24020 | __instruction->as<OpDelByVal>().dump(dumper, __location, __instruction->isWide()); |
24021 | break; |
24022 | case op_put_getter_by_id: |
24023 | __instruction->as<OpPutGetterById>().dump(dumper, __location, __instruction->isWide()); |
24024 | break; |
24025 | case op_put_setter_by_id: |
24026 | __instruction->as<OpPutSetterById>().dump(dumper, __location, __instruction->isWide()); |
24027 | break; |
24028 | case op_put_getter_setter_by_id: |
24029 | __instruction->as<OpPutGetterSetterById>().dump(dumper, __location, __instruction->isWide()); |
24030 | break; |
24031 | case op_put_getter_by_val: |
24032 | __instruction->as<OpPutGetterByVal>().dump(dumper, __location, __instruction->isWide()); |
24033 | break; |
24034 | case op_put_setter_by_val: |
24035 | __instruction->as<OpPutSetterByVal>().dump(dumper, __location, __instruction->isWide()); |
24036 | break; |
24037 | case op_define_data_property: |
24038 | __instruction->as<OpDefineDataProperty>().dump(dumper, __location, __instruction->isWide()); |
24039 | break; |
24040 | case op_define_accessor_property: |
24041 | __instruction->as<OpDefineAccessorProperty>().dump(dumper, __location, __instruction->isWide()); |
24042 | break; |
24043 | case op_jmp: |
24044 | __instruction->as<OpJmp>().dump(dumper, __location, __instruction->isWide()); |
24045 | break; |
24046 | case op_jtrue: |
24047 | __instruction->as<OpJtrue>().dump(dumper, __location, __instruction->isWide()); |
24048 | break; |
24049 | case op_jfalse: |
24050 | __instruction->as<OpJfalse>().dump(dumper, __location, __instruction->isWide()); |
24051 | break; |
24052 | case op_jeq_null: |
24053 | __instruction->as<OpJeqNull>().dump(dumper, __location, __instruction->isWide()); |
24054 | break; |
24055 | case op_jneq_null: |
24056 | __instruction->as<OpJneqNull>().dump(dumper, __location, __instruction->isWide()); |
24057 | break; |
24058 | case op_jeq: |
24059 | __instruction->as<OpJeq>().dump(dumper, __location, __instruction->isWide()); |
24060 | break; |
24061 | case op_jstricteq: |
24062 | __instruction->as<OpJstricteq>().dump(dumper, __location, __instruction->isWide()); |
24063 | break; |
24064 | case op_jneq: |
24065 | __instruction->as<OpJneq>().dump(dumper, __location, __instruction->isWide()); |
24066 | break; |
24067 | case op_jnstricteq: |
24068 | __instruction->as<OpJnstricteq>().dump(dumper, __location, __instruction->isWide()); |
24069 | break; |
24070 | case op_jless: |
24071 | __instruction->as<OpJless>().dump(dumper, __location, __instruction->isWide()); |
24072 | break; |
24073 | case op_jlesseq: |
24074 | __instruction->as<OpJlesseq>().dump(dumper, __location, __instruction->isWide()); |
24075 | break; |
24076 | case op_jgreater: |
24077 | __instruction->as<OpJgreater>().dump(dumper, __location, __instruction->isWide()); |
24078 | break; |
24079 | case op_jgreatereq: |
24080 | __instruction->as<OpJgreatereq>().dump(dumper, __location, __instruction->isWide()); |
24081 | break; |
24082 | case op_jnless: |
24083 | __instruction->as<OpJnless>().dump(dumper, __location, __instruction->isWide()); |
24084 | break; |
24085 | case op_jnlesseq: |
24086 | __instruction->as<OpJnlesseq>().dump(dumper, __location, __instruction->isWide()); |
24087 | break; |
24088 | case op_jngreater: |
24089 | __instruction->as<OpJngreater>().dump(dumper, __location, __instruction->isWide()); |
24090 | break; |
24091 | case op_jngreatereq: |
24092 | __instruction->as<OpJngreatereq>().dump(dumper, __location, __instruction->isWide()); |
24093 | break; |
24094 | case op_jbelow: |
24095 | __instruction->as<OpJbelow>().dump(dumper, __location, __instruction->isWide()); |
24096 | break; |
24097 | case op_jbeloweq: |
24098 | __instruction->as<OpJbeloweq>().dump(dumper, __location, __instruction->isWide()); |
24099 | break; |
24100 | case op_loop_hint: |
24101 | __instruction->as<OpLoopHint>().dump(dumper, __location, __instruction->isWide()); |
24102 | break; |
24103 | case op_switch_imm: |
24104 | __instruction->as<OpSwitchImm>().dump(dumper, __location, __instruction->isWide()); |
24105 | break; |
24106 | case op_switch_char: |
24107 | __instruction->as<OpSwitchChar>().dump(dumper, __location, __instruction->isWide()); |
24108 | break; |
24109 | case op_switch_string: |
24110 | __instruction->as<OpSwitchString>().dump(dumper, __location, __instruction->isWide()); |
24111 | break; |
24112 | case op_new_func: |
24113 | __instruction->as<OpNewFunc>().dump(dumper, __location, __instruction->isWide()); |
24114 | break; |
24115 | case op_new_func_exp: |
24116 | __instruction->as<OpNewFuncExp>().dump(dumper, __location, __instruction->isWide()); |
24117 | break; |
24118 | case op_new_generator_func: |
24119 | __instruction->as<OpNewGeneratorFunc>().dump(dumper, __location, __instruction->isWide()); |
24120 | break; |
24121 | case op_new_generator_func_exp: |
24122 | __instruction->as<OpNewGeneratorFuncExp>().dump(dumper, __location, __instruction->isWide()); |
24123 | break; |
24124 | case op_new_async_func: |
24125 | __instruction->as<OpNewAsyncFunc>().dump(dumper, __location, __instruction->isWide()); |
24126 | break; |
24127 | case op_new_async_func_exp: |
24128 | __instruction->as<OpNewAsyncFuncExp>().dump(dumper, __location, __instruction->isWide()); |
24129 | break; |
24130 | case op_new_async_generator_func: |
24131 | __instruction->as<OpNewAsyncGeneratorFunc>().dump(dumper, __location, __instruction->isWide()); |
24132 | break; |
24133 | case op_new_async_generator_func_exp: |
24134 | __instruction->as<OpNewAsyncGeneratorFuncExp>().dump(dumper, __location, __instruction->isWide()); |
24135 | break; |
24136 | case op_set_function_name: |
24137 | __instruction->as<OpSetFunctionName>().dump(dumper, __location, __instruction->isWide()); |
24138 | break; |
24139 | case op_ret: |
24140 | __instruction->as<OpRet>().dump(dumper, __location, __instruction->isWide()); |
24141 | break; |
24142 | case op_strcat: |
24143 | __instruction->as<OpStrcat>().dump(dumper, __location, __instruction->isWide()); |
24144 | break; |
24145 | case op_to_primitive: |
24146 | __instruction->as<OpToPrimitive>().dump(dumper, __location, __instruction->isWide()); |
24147 | break; |
24148 | case op_put_to_arguments: |
24149 | __instruction->as<OpPutToArguments>().dump(dumper, __location, __instruction->isWide()); |
24150 | break; |
24151 | case op_push_with_scope: |
24152 | __instruction->as<OpPushWithScope>().dump(dumper, __location, __instruction->isWide()); |
24153 | break; |
24154 | case op_create_lexical_environment: |
24155 | __instruction->as<OpCreateLexicalEnvironment>().dump(dumper, __location, __instruction->isWide()); |
24156 | break; |
24157 | case op_create_generator_frame_environment: |
24158 | __instruction->as<OpCreateGeneratorFrameEnvironment>().dump(dumper, __location, __instruction->isWide()); |
24159 | break; |
24160 | case op_get_parent_scope: |
24161 | __instruction->as<OpGetParentScope>().dump(dumper, __location, __instruction->isWide()); |
24162 | break; |
24163 | case op_throw: |
24164 | __instruction->as<OpThrow>().dump(dumper, __location, __instruction->isWide()); |
24165 | break; |
24166 | case op_throw_static_error: |
24167 | __instruction->as<OpThrowStaticError>().dump(dumper, __location, __instruction->isWide()); |
24168 | break; |
24169 | case op_debug: |
24170 | __instruction->as<OpDebug>().dump(dumper, __location, __instruction->isWide()); |
24171 | break; |
24172 | case op_end: |
24173 | __instruction->as<OpEnd>().dump(dumper, __location, __instruction->isWide()); |
24174 | break; |
24175 | case op_get_enumerable_length: |
24176 | __instruction->as<OpGetEnumerableLength>().dump(dumper, __location, __instruction->isWide()); |
24177 | break; |
24178 | case op_has_structure_property: |
24179 | __instruction->as<OpHasStructureProperty>().dump(dumper, __location, __instruction->isWide()); |
24180 | break; |
24181 | case op_has_generic_property: |
24182 | __instruction->as<OpHasGenericProperty>().dump(dumper, __location, __instruction->isWide()); |
24183 | break; |
24184 | case op_get_property_enumerator: |
24185 | __instruction->as<OpGetPropertyEnumerator>().dump(dumper, __location, __instruction->isWide()); |
24186 | break; |
24187 | case op_enumerator_structure_pname: |
24188 | __instruction->as<OpEnumeratorStructurePname>().dump(dumper, __location, __instruction->isWide()); |
24189 | break; |
24190 | case op_enumerator_generic_pname: |
24191 | __instruction->as<OpEnumeratorGenericPname>().dump(dumper, __location, __instruction->isWide()); |
24192 | break; |
24193 | case op_to_index_string: |
24194 | __instruction->as<OpToIndexString>().dump(dumper, __location, __instruction->isWide()); |
24195 | break; |
24196 | case op_unreachable: |
24197 | __instruction->as<OpUnreachable>().dump(dumper, __location, __instruction->isWide()); |
24198 | break; |
24199 | case op_create_rest: |
24200 | __instruction->as<OpCreateRest>().dump(dumper, __location, __instruction->isWide()); |
24201 | break; |
24202 | case op_get_rest_length: |
24203 | __instruction->as<OpGetRestLength>().dump(dumper, __location, __instruction->isWide()); |
24204 | break; |
24205 | case op_yield: |
24206 | __instruction->as<OpYield>().dump(dumper, __location, __instruction->isWide()); |
24207 | break; |
24208 | case op_check_traps: |
24209 | __instruction->as<OpCheckTraps>().dump(dumper, __location, __instruction->isWide()); |
24210 | break; |
24211 | case op_log_shadow_chicken_prologue: |
24212 | __instruction->as<OpLogShadowChickenPrologue>().dump(dumper, __location, __instruction->isWide()); |
24213 | break; |
24214 | case op_log_shadow_chicken_tail: |
24215 | __instruction->as<OpLogShadowChickenTail>().dump(dumper, __location, __instruction->isWide()); |
24216 | break; |
24217 | case op_resolve_scope_for_hoisting_func_decl_in_eval: |
24218 | __instruction->as<OpResolveScopeForHoistingFuncDeclInEval>().dump(dumper, __location, __instruction->isWide()); |
24219 | break; |
24220 | case op_nop: |
24221 | __instruction->as<OpNop>().dump(dumper, __location, __instruction->isWide()); |
24222 | break; |
24223 | case op_super_sampler_begin: |
24224 | __instruction->as<OpSuperSamplerBegin>().dump(dumper, __location, __instruction->isWide()); |
24225 | break; |
24226 | case op_super_sampler_end: |
24227 | __instruction->as<OpSuperSamplerEnd>().dump(dumper, __location, __instruction->isWide()); |
24228 | break; |
24229 | default: |
24230 | ASSERT_NOT_REACHED(); |
24231 | } |
24232 | } |
24233 | |
24234 | } // namespace JSC |
24235 | |