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
42namespace JSC {
43
44struct 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
71private:
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
97public:
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
213struct 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
240private:
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
264public:
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
358struct 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
385private:
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
407public:
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
481struct 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
508private:
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
532public:
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
626struct 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
653private:
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
681public:
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
819struct 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
846private:
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
870public:
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
964struct 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
991private:
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
1017public:
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
1133struct 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
1160private:
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
1188public:
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
1328struct 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
1355private:
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
1383public:
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
1523struct 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
1550private:
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
1578public:
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
1718struct 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
1745private:
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
1773public:
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
1913struct 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
1940private:
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
1966public:
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
2082struct 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
2109private:
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
2135public:
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
2251struct 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
2278private:
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
2304public:
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
2420struct 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
2447private:
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
2471public:
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
2565struct 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
2592private:
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
2618public:
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
2734struct 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
2761private:
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
2785public:
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
2879struct 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
2906private:
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
2932public:
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
3050struct 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
3077private:
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
3103public:
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
3219struct 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
3246private:
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
3272public:
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
3391struct 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
3418private:
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
3446public:
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
3584struct 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
3611private:
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
3639public:
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
3777struct 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
3804private:
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
3830public:
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
3948struct 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
3975private:
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
4001public:
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
4117struct 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
4144private:
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
4172public:
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
4313struct 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
4340private:
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
4366public:
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
4483struct 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
4510private:
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
4536public:
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
4652struct 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
4679private:
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
4705public:
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
4821struct 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
4848private:
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
4874public:
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
4990struct 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
5017private:
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
5045public:
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
5185struct 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
5212private:
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
5240public:
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
5380struct 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
5407private:
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
5435public:
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
5575struct 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
5602private:
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
5634public:
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
5817struct 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
5844private:
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
5876public:
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
6059struct 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
6086private:
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
6118public:
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
6301struct 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
6328private:
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
6356public:
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
6496struct 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
6523private:
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
6555public:
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
6738struct 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
6765private:
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
6795public:
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
6966struct 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
6993private:
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
7025public:
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
7216struct 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
7243private:
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
7275public:
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
7465struct 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
7492private:
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
7518public:
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
7634struct 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
7661private:
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
7685public:
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
7779struct 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
7806private:
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
7836public:
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
7996struct 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
8023private:
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
8045public:
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
8117struct 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
8144private:
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
8170public:
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
8286struct 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
8313private:
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
8343public:
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
8503struct 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
8522private:
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
8540public:
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
8573struct 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
8592private:
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
8610public:
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
8643struct 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
8662private:
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
8682public:
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
8732struct 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
8751private:
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
8771public:
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
8821struct 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
8840private:
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
8862public:
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
8934struct 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
8953private:
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
8973public:
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
9023struct 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
9042private:
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
9062public:
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
9112struct 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
9131private:
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
9151public:
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
9201struct 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
9220private:
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
9246public:
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
9362struct 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
9381private:
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
9403public:
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
9475struct 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
9494private:
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
9516public:
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
9588struct 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
9607private:
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
9629public:
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
9701struct 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
9720private:
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
9744public:
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
9838struct 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
9857private:
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
9881public:
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
9975struct 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
9994private:
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
10018public:
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
10112struct 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
10131private:
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
10155public:
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
10249struct 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
10268private:
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
10292public:
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
10386struct 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
10405private:
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
10429public:
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
10523struct 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
10542private:
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
10566public:
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
10660struct 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
10679private:
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
10703public:
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
10797struct 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
10816private:
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
10840public:
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
10934struct 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
10953private:
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
10977public:
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
11071struct 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
11090private:
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
11114public:
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
11208struct 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
11227private:
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
11251public:
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
11345struct 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
11364private:
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
11388public:
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
11482struct 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
11501private:
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
11525public:
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
11619struct 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
11638private:
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
11662public:
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
11756struct 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
11775private:
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
11797public:
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
11869struct 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
11888private:
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
11910public:
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
11982struct 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
12001private:
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
12023public:
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
12095struct 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
12114private:
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
12136public:
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
12208struct 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
12227private:
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
12249public:
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
12321struct 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
12340private:
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
12362public:
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
12434struct 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
12453private:
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
12475public:
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
12547struct 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
12566private:
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
12588public:
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
12660struct 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
12679private:
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
12701public:
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
12773struct 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
12792private:
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
12814public:
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
12886struct 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
12905private:
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
12927public:
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
12999struct 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
13018private:
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
13040public:
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
13112struct 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
13131private:
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
13151public:
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
13201struct 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
13220private:
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
13240public:
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
13290struct 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
13309private:
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
13331public:
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
13403struct 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
13422private:
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
13446public:
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
13540struct 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
13559private:
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
13583public:
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
13677struct 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
13696private:
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
13720public:
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
13814struct 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
13833private:
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
13859public:
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
13975struct 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
13994private:
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
14016public:
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
14088struct 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
14107private:
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
14131public:
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
14225struct 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
14244private:
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
14268public:
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
14362struct 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
14381private:
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
14407public:
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
14523struct 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
14542private:
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
14566public:
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
14660struct 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
14679private:
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
14705public:
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
14821struct 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
14840private:
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
14864public:
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
14958struct 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
14977private:
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
15003public:
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
15119struct 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
15138private:
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
15164public:
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
15280struct 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
15299private:
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
15327public:
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
15465struct 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
15484private:
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
15510public:
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
15626struct 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
15645private:
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
15671public:
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
15787struct 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
15806private:
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
15832public:
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
15948struct 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
15967private:
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
15995public:
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
16133struct 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
16152private:
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
16172public:
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
16222struct 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
16241private:
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
16263public:
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
16335struct 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
16354private:
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
16376public:
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
16448struct 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
16467private:
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
16489public:
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
16561struct 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
16580private:
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
16602public:
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
16674struct 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
16693private:
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
16717public:
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
16811struct 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
16830private:
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
16854public:
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
16948struct 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
16967private:
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
16991public:
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
17085struct 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
17104private:
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
17128public:
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
17222struct 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
17241private:
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
17265public:
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
17359struct 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
17378private:
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
17402public:
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
17496struct 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
17515private:
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
17539public:
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
17633struct 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
17652private:
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
17676public:
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
17770struct 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
17789private:
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
17813public:
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
17907struct 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
17926private:
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
17950public:
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
18044struct 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
18063private:
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
18087public:
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
18181struct 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
18200private:
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
18224public:
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
18318struct 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
18337private:
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
18361public:
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
18455struct 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
18474private:
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
18498public:
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
18592struct 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
18611private:
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
18629public:
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
18662struct 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
18681private:
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
18705public:
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
18799struct 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
18818private:
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
18842public:
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
18936struct 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
18955private:
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
18979public:
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
19073struct 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
19092private:
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
19116public:
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
19210struct 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
19229private:
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
19253public:
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
19347struct 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
19366private:
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
19390public:
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
19484struct 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
19503private:
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
19527public:
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
19621struct 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
19640private:
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
19664public:
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
19758struct 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
19777private:
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
19801public:
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
19895struct 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
19914private:
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
19938public:
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
20032struct 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
20051private:
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
20075public:
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
20169struct 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
20188private:
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
20210public:
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
20282struct 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
20301private:
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
20321public:
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
20371struct 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
20390private:
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
20414public:
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
20508struct 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
20527private:
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
20549public:
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
20621struct 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
20640private:
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
20664public:
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
20758struct 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
20777private:
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
20801public:
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
20895struct 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
20914private:
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
20940public:
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
21056struct 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
21075private:
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
21101public:
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
21217struct 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
21236private:
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
21258public:
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
21330struct 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
21349private:
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
21369public:
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
21419struct 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
21438private:
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
21460public:
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
21532struct 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
21551private:
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
21573public:
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
21645struct 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
21664private:
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
21684public:
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
21734struct 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
21753private:
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
21775public:
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
21847struct 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
21866private:
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
21892public:
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
22008struct 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
22027private:
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
22051public:
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
22145struct 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
22164private:
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
22186public:
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
22258struct 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
22277private:
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
22301public:
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
22395struct 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
22414private:
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
22438public:
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
22532struct 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
22551private:
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
22573public:
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
22645struct 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
22664private:
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
22682public:
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
22715struct 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
22734private:
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
22758public:
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
22852struct 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
22871private:
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
22893public:
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
22965struct 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
22984private:
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
23008public:
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
23102struct 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
23121private:
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
23139public:
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
23172struct 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
23191private:
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
23211public:
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
23261struct 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
23280private:
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
23302public:
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
23374struct 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
23393private:
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
23417public:
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
23511struct 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
23530private:
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
23548public:
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
23581struct 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
23600private:
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
23618public:
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
23651struct 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
23670private:
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
23688public:
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
23721template<typename Block>
23722static 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